arnaucube.com/blog/js/katex/katex.mjs
blog/js/katex/katex.mjsRaw
1/**
2 * Lexing or parsing positional information for error reporting.
3 * This object is immutable.
4 */
5class SourceLocation {
6 // The + prefix indicates that these fields aren't writeable
7 // Lexer holding the input string.
8 // Start offset, zero-based inclusive.
9 // End offset, zero-based exclusive.
10 constructor(lexer, start, end) {
11 this.lexer = void 0;
12 this.start = void 0;
13 this.end = void 0;
14 this.lexer = lexer;
15 this.start = start;
16 this.end = end;
17 }
18 /**
19 * Merges two `SourceLocation`s from location providers, given they are
20 * provided in order of appearance.
21 * - Returns the first one's location if only the first is provided.
22 * - Returns a merged range of the first and the last if both are provided
23 * and their lexers match.
24 * - Otherwise, returns null.
25 */
26
27
28 static range(first, second) {
29 if (!second) {
30 return first && first.loc;
31 } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) {
32 return null;
33 } else {
34 return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end);
35 }
36 }
37
38}
39
40/**
41 * Interface required to break circular dependency between Token, Lexer, and
42 * ParseError.
43 */
44
45/**
46 * The resulting token returned from `lex`.
47 *
48 * It consists of the token text plus some position information.
49 * The position information is essentially a range in an input string,
50 * but instead of referencing the bare input string, we refer to the lexer.
51 * That way it is possible to attach extra metadata to the input string,
52 * like for example a file name or similar.
53 *
54 * The position information is optional, so it is OK to construct synthetic
55 * tokens if appropriate. Not providing available position information may
56 * lead to degraded error reporting, though.
57 */
58class Token {
59 // don't expand the token
60 // used in \noexpand
61 constructor(text, // the text of this token
62 loc) {
63 this.text = void 0;
64 this.loc = void 0;
65 this.noexpand = void 0;
66 this.treatAsRelax = void 0;
67 this.text = text;
68 this.loc = loc;
69 }
70 /**
71 * Given a pair of tokens (this and endToken), compute a `Token` encompassing
72 * the whole input range enclosed by these two.
73 */
74
75
76 range(endToken, // last token of the range, inclusive
77 text // the text of the newly constructed token
78 ) {
79 return new Token(text, SourceLocation.range(this, endToken));
80 }
81
82}
83
84/**
85 * This is the ParseError class, which is the main error thrown by KaTeX
86 * functions when something has gone wrong. This is used to distinguish internal
87 * errors from errors in the expression that the user provided.
88 *
89 * If possible, a caller should provide a Token or ParseNode with information
90 * about where in the source string the problem occurred.
91 */
92class ParseError {
93 // Error position based on passed-in Token or ParseNode.
94 constructor(message, // The error message
95 token // An object providing position information
96 ) {
97 this.position = void 0;
98 var error = "KaTeX parse error: " + message;
99 var start;
100 var loc = token && token.loc;
101
102 if (loc && loc.start <= loc.end) {
103 // If we have the input and a position, make the error a bit fancier
104 // Get the input
105 var input = loc.lexer.input; // Prepend some information
106
107 start = loc.start;
108 var end = loc.end;
109
110 if (start === input.length) {
111 error += " at end of input: ";
112 } else {
113 error += " at position " + (start + 1) + ": ";
114 } // Underline token in question using combining underscores
115
116
117 var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error
118
119 var left;
120
121 if (start > 15) {
122 left = "…" + input.slice(start - 15, start);
123 } else {
124 left = input.slice(0, start);
125 }
126
127 var right;
128
129 if (end + 15 < input.length) {
130 right = input.slice(end, end + 15) + "…";
131 } else {
132 right = input.slice(end);
133 }
134
135 error += left + underlined + right;
136 } // Some hackery to make ParseError a prototype of Error
137 // See http://stackoverflow.com/a/8460753
138
139
140 var self = new Error(error);
141 self.name = "ParseError"; // $FlowFixMe
142
143 self.__proto__ = ParseError.prototype; // $FlowFixMe
144
145 self.position = start;
146 return self;
147 }
148
149} // $FlowFixMe More hackery
150
151
152ParseError.prototype.__proto__ = Error.prototype;
153
154/**
155 * This file contains a list of utility functions which are useful in other
156 * files.
157 */
158
159/**
160 * Return whether an element is contained in a list
161 */
162var contains = function contains(list, elem) {
163 return list.indexOf(elem) !== -1;
164};
165/**
166 * Provide a default value if a setting is undefined
167 * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022.
168 */
169
170
171var deflt = function deflt(setting, defaultIfUndefined) {
172 return setting === undefined ? defaultIfUndefined : setting;
173}; // hyphenate and escape adapted from Facebook's React under Apache 2 license
174
175
176var uppercase = /([A-Z])/g;
177
178var hyphenate = function hyphenate(str) {
179 return str.replace(uppercase, "-$1").toLowerCase();
180};
181
182var ESCAPE_LOOKUP = {
183 "&": "&",
184 ">": ">",
185 "<": "<",
186 "\"": """,
187 "'": "'"
188};
189var ESCAPE_REGEX = /[&><"']/g;
190/**
191 * Escapes text to prevent scripting attacks.
192 */
193
194function escape(text) {
195 return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
196}
197/**
198 * Sometimes we want to pull out the innermost element of a group. In most
199 * cases, this will just be the group itself, but when ordgroups and colors have
200 * a single element, we want to pull that out.
201 */
202
203
204var getBaseElem = function getBaseElem(group) {
205 if (group.type === "ordgroup") {
206 if (group.body.length === 1) {
207 return getBaseElem(group.body[0]);
208 } else {
209 return group;
210 }
211 } else if (group.type === "color") {
212 if (group.body.length === 1) {
213 return getBaseElem(group.body[0]);
214 } else {
215 return group;
216 }
217 } else if (group.type === "font") {
218 return getBaseElem(group.body);
219 } else {
220 return group;
221 }
222};
223/**
224 * TeXbook algorithms often reference "character boxes", which are simply groups
225 * with a single character in them. To decide if something is a character box,
226 * we find its innermost group, and see if it is a single character.
227 */
228
229
230var isCharacterBox = function isCharacterBox(group) {
231 var baseElem = getBaseElem(group); // These are all they types of groups which hold single characters
232
233 return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom";
234};
235
236var assert = function assert(value) {
237 if (!value) {
238 throw new Error('Expected non-null, but got ' + String(value));
239 }
240
241 return value;
242};
243/**
244 * Return the protocol of a URL, or "_relative" if the URL does not specify a
245 * protocol (and thus is relative).
246 */
247
248var protocolFromUrl = function protocolFromUrl(url) {
249 var protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url);
250 return protocol != null ? protocol[1] : "_relative";
251};
252var utils = {
253 contains,
254 deflt,
255 escape,
256 hyphenate,
257 getBaseElem,
258 isCharacterBox,
259 protocolFromUrl
260};
261
262/* eslint no-console:0 */
263// TODO: automatically generate documentation
264// TODO: check all properties on Settings exist
265// TODO: check the type of a property on Settings matches
266var SETTINGS_SCHEMA = {
267 displayMode: {
268 type: "boolean",
269 description: "Render math in display mode, which puts the math in " + "display style (so \\int and \\sum are large, for example), and " + "centers the math on the page on its own line.",
270 cli: "-d, --display-mode"
271 },
272 output: {
273 type: {
274 enum: ["htmlAndMathml", "html", "mathml"]
275 },
276 description: "Determines the markup language of the output.",
277 cli: "-F, --format <type>"
278 },
279 leqno: {
280 type: "boolean",
281 description: "Render display math in leqno style (left-justified tags)."
282 },
283 fleqn: {
284 type: "boolean",
285 description: "Render display math flush left."
286 },
287 throwOnError: {
288 type: "boolean",
289 default: true,
290 cli: "-t, --no-throw-on-error",
291 cliDescription: "Render errors (in the color given by --error-color) ins" + "tead of throwing a ParseError exception when encountering an error."
292 },
293 errorColor: {
294 type: "string",
295 default: "#cc0000",
296 cli: "-c, --error-color <color>",
297 cliDescription: "A color string given in the format 'rgb' or 'rrggbb' " + "(no #). This option determines the color of errors rendered by the " + "-t option.",
298 cliProcessor: color => "#" + color
299 },
300 macros: {
301 type: "object",
302 cli: "-m, --macro <def>",
303 cliDescription: "Define custom macro of the form '\\foo:expansion' (use " + "multiple -m arguments for multiple macros).",
304 cliDefault: [],
305 cliProcessor: (def, defs) => {
306 defs.push(def);
307 return defs;
308 }
309 },
310 minRuleThickness: {
311 type: "number",
312 description: "Specifies a minimum thickness, in ems, for fraction lines," + " `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, " + "`\\hdashline`, `\\underline`, `\\overline`, and the borders of " + "`\\fbox`, `\\boxed`, and `\\fcolorbox`.",
313 processor: t => Math.max(0, t),
314 cli: "--min-rule-thickness <size>",
315 cliProcessor: parseFloat
316 },
317 colorIsTextColor: {
318 type: "boolean",
319 description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, " + "instead of LaTeX's one-argument \\color mode change.",
320 cli: "-b, --color-is-text-color"
321 },
322 strict: {
323 type: [{
324 enum: ["warn", "ignore", "error"]
325 }, "boolean", "function"],
326 description: "Turn on strict / LaTeX faithfulness mode, which throws an " + "error if the input uses features that are not supported by LaTeX.",
327 cli: "-S, --strict",
328 cliDefault: false
329 },
330 trust: {
331 type: ["boolean", "function"],
332 description: "Trust the input, enabling all HTML features such as \\url.",
333 cli: "-T, --trust"
334 },
335 maxSize: {
336 type: "number",
337 default: Infinity,
338 description: "If non-zero, all user-specified sizes, e.g. in " + "\\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, " + "elements and spaces can be arbitrarily large",
339 processor: s => Math.max(0, s),
340 cli: "-s, --max-size <n>",
341 cliProcessor: parseInt
342 },
343 maxExpand: {
344 type: "number",
345 default: 1000,
346 description: "Limit the number of macro expansions to the specified " + "number, to prevent e.g. infinite macro loops. If set to Infinity, " + "the macro expander will try to fully expand as in LaTeX.",
347 processor: n => Math.max(0, n),
348 cli: "-e, --max-expand <n>",
349 cliProcessor: n => n === "Infinity" ? Infinity : parseInt(n)
350 },
351 globalGroup: {
352 type: "boolean",
353 cli: false
354 }
355};
356
357function getDefaultValue(schema) {
358 if (schema.default) {
359 return schema.default;
360 }
361
362 var type = schema.type;
363 var defaultType = Array.isArray(type) ? type[0] : type;
364
365 if (typeof defaultType !== 'string') {
366 return defaultType.enum[0];
367 }
368
369 switch (defaultType) {
370 case 'boolean':
371 return false;
372
373 case 'string':
374 return '';
375
376 case 'number':
377 return 0;
378
379 case 'object':
380 return {};
381 }
382}
383/**
384 * The main Settings object
385 *
386 * The current options stored are:
387 * - displayMode: Whether the expression should be typeset as inline math
388 * (false, the default), meaning that the math starts in
389 * \textstyle and is placed in an inline-block); or as display
390 * math (true), meaning that the math starts in \displaystyle
391 * and is placed in a block with vertical margin.
392 */
393
394
395class Settings {
396 constructor(options) {
397 this.displayMode = void 0;
398 this.output = void 0;
399 this.leqno = void 0;
400 this.fleqn = void 0;
401 this.throwOnError = void 0;
402 this.errorColor = void 0;
403 this.macros = void 0;
404 this.minRuleThickness = void 0;
405 this.colorIsTextColor = void 0;
406 this.strict = void 0;
407 this.trust = void 0;
408 this.maxSize = void 0;
409 this.maxExpand = void 0;
410 this.globalGroup = void 0;
411 // allow null options
412 options = options || {};
413
414 for (var prop in SETTINGS_SCHEMA) {
415 if (SETTINGS_SCHEMA.hasOwnProperty(prop)) {
416 // $FlowFixMe
417 var schema = SETTINGS_SCHEMA[prop]; // TODO: validate options
418 // $FlowFixMe
419
420 this[prop] = options[prop] !== undefined ? schema.processor ? schema.processor(options[prop]) : options[prop] : getDefaultValue(schema);
421 }
422 }
423 }
424 /**
425 * Report nonstrict (non-LaTeX-compatible) input.
426 * Can safely not be called if `this.strict` is false in JavaScript.
427 */
428
429
430 reportNonstrict(errorCode, errorMsg, token) {
431 var strict = this.strict;
432
433 if (typeof strict === "function") {
434 // Allow return value of strict function to be boolean or string
435 // (or null/undefined, meaning no further processing).
436 strict = strict(errorCode, errorMsg, token);
437 }
438
439 if (!strict || strict === "ignore") {
440 return;
441 } else if (strict === true || strict === "error") {
442 throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token);
443 } else if (strict === "warn") {
444 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
445 } else {
446 // won't happen in type-safe code
447 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
448 }
449 }
450 /**
451 * Check whether to apply strict (LaTeX-adhering) behavior for unusual
452 * input (like `\\`). Unlike `nonstrict`, will not throw an error;
453 * instead, "error" translates to a return value of `true`, while "ignore"
454 * translates to a return value of `false`. May still print a warning:
455 * "warn" prints a warning and returns `false`.
456 * This is for the second category of `errorCode`s listed in the README.
457 */
458
459
460 useStrictBehavior(errorCode, errorMsg, token) {
461 var strict = this.strict;
462
463 if (typeof strict === "function") {
464 // Allow return value of strict function to be boolean or string
465 // (or null/undefined, meaning no further processing).
466 // But catch any exceptions thrown by function, treating them
467 // like "error".
468 try {
469 strict = strict(errorCode, errorMsg, token);
470 } catch (error) {
471 strict = "error";
472 }
473 }
474
475 if (!strict || strict === "ignore") {
476 return false;
477 } else if (strict === true || strict === "error") {
478 return true;
479 } else if (strict === "warn") {
480 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
481 return false;
482 } else {
483 // won't happen in type-safe code
484 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
485 return false;
486 }
487 }
488 /**
489 * Check whether to test potentially dangerous input, and return
490 * `true` (trusted) or `false` (untrusted). The sole argument `context`
491 * should be an object with `command` field specifying the relevant LaTeX
492 * command (as a string starting with `\`), and any other arguments, etc.
493 * If `context` has a `url` field, a `protocol` field will automatically
494 * get added by this function (changing the specified object).
495 */
496
497
498 isTrusted(context) {
499 if (context.url && !context.protocol) {
500 context.protocol = utils.protocolFromUrl(context.url);
501 }
502
503 var trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
504 return Boolean(trust);
505 }
506
507}
508
509/**
510 * This file contains information and classes for the various kinds of styles
511 * used in TeX. It provides a generic `Style` class, which holds information
512 * about a specific style. It then provides instances of all the different kinds
513 * of styles possible, and provides functions to move between them and get
514 * information about them.
515 */
516
517/**
518 * The main style class. Contains a unique id for the style, a size (which is
519 * the same for cramped and uncramped version of a style), and a cramped flag.
520 */
521class Style {
522 constructor(id, size, cramped) {
523 this.id = void 0;
524 this.size = void 0;
525 this.cramped = void 0;
526 this.id = id;
527 this.size = size;
528 this.cramped = cramped;
529 }
530 /**
531 * Get the style of a superscript given a base in the current style.
532 */
533
534
535 sup() {
536 return styles[sup[this.id]];
537 }
538 /**
539 * Get the style of a subscript given a base in the current style.
540 */
541
542
543 sub() {
544 return styles[sub[this.id]];
545 }
546 /**
547 * Get the style of a fraction numerator given the fraction in the current
548 * style.
549 */
550
551
552 fracNum() {
553 return styles[fracNum[this.id]];
554 }
555 /**
556 * Get the style of a fraction denominator given the fraction in the current
557 * style.
558 */
559
560
561 fracDen() {
562 return styles[fracDen[this.id]];
563 }
564 /**
565 * Get the cramped version of a style (in particular, cramping a cramped style
566 * doesn't change the style).
567 */
568
569
570 cramp() {
571 return styles[cramp[this.id]];
572 }
573 /**
574 * Get a text or display version of this style.
575 */
576
577
578 text() {
579 return styles[text$1[this.id]];
580 }
581 /**
582 * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle)
583 */
584
585
586 isTight() {
587 return this.size >= 2;
588 }
589
590} // Export an interface for type checking, but don't expose the implementation.
591// This way, no more styles can be generated.
592
593
594// IDs of the different styles
595var D = 0;
596var Dc = 1;
597var T = 2;
598var Tc = 3;
599var S = 4;
600var Sc = 5;
601var SS = 6;
602var SSc = 7; // Instances of the different styles
603
604var styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)]; // Lookup tables for switching from one style to another
605
606var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
607var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
608var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
609var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
610var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
611var text$1 = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles.
612
613var Style$1 = {
614 DISPLAY: styles[D],
615 TEXT: styles[T],
616 SCRIPT: styles[S],
617 SCRIPTSCRIPT: styles[SS]
618};
619
620/*
621 * This file defines the Unicode scripts and script families that we
622 * support. To add new scripts or families, just add a new entry to the
623 * scriptData array below. Adding scripts to the scriptData array allows
624 * characters from that script to appear in \text{} environments.
625 */
626
627/**
628 * Each script or script family has a name and an array of blocks.
629 * Each block is an array of two numbers which specify the start and
630 * end points (inclusive) of a block of Unicode codepoints.
631 */
632
633/**
634 * Unicode block data for the families of scripts we support in \text{}.
635 * Scripts only need to appear here if they do not have font metrics.
636 */
637var scriptData = [{
638 // Latin characters beyond the Latin-1 characters we have metrics for.
639 // Needed for Czech, Hungarian and Turkish text, for example.
640 name: 'latin',
641 blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B
642 [0x0300, 0x036f] // Combining Diacritical marks
643 ]
644}, {
645 // The Cyrillic script used by Russian and related languages.
646 // A Cyrillic subset used to be supported as explicitly defined
647 // symbols in symbols.js
648 name: 'cyrillic',
649 blocks: [[0x0400, 0x04ff]]
650}, {
651 // Armenian
652 name: 'armenian',
653 blocks: [[0x0530, 0x058F]]
654}, {
655 // The Brahmic scripts of South and Southeast Asia
656 // Devanagari (0900–097F)
657 // Bengali (0980–09FF)
658 // Gurmukhi (0A00–0A7F)
659 // Gujarati (0A80–0AFF)
660 // Oriya (0B00–0B7F)
661 // Tamil (0B80–0BFF)
662 // Telugu (0C00–0C7F)
663 // Kannada (0C80–0CFF)
664 // Malayalam (0D00–0D7F)
665 // Sinhala (0D80–0DFF)
666 // Thai (0E00–0E7F)
667 // Lao (0E80–0EFF)
668 // Tibetan (0F00–0FFF)
669 // Myanmar (1000–109F)
670 name: 'brahmic',
671 blocks: [[0x0900, 0x109F]]
672}, {
673 name: 'georgian',
674 blocks: [[0x10A0, 0x10ff]]
675}, {
676 // Chinese and Japanese.
677 // The "k" in cjk is for Korean, but we've separated Korean out
678 name: "cjk",
679 blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana
680 [0x4E00, 0x9FAF], // CJK ideograms
681 [0xFF00, 0xFF60] // Fullwidth punctuation
682 // TODO: add halfwidth Katakana and Romanji glyphs
683 ]
684}, {
685 // Korean
686 name: 'hangul',
687 blocks: [[0xAC00, 0xD7AF]]
688}];
689/**
690 * Given a codepoint, return the name of the script or script family
691 * it is from, or null if it is not part of a known block
692 */
693
694function scriptFromCodepoint(codepoint) {
695 for (var i = 0; i < scriptData.length; i++) {
696 var script = scriptData[i];
697
698 for (var _i = 0; _i < script.blocks.length; _i++) {
699 var block = script.blocks[_i];
700
701 if (codepoint >= block[0] && codepoint <= block[1]) {
702 return script.name;
703 }
704 }
705 }
706
707 return null;
708}
709/**
710 * A flattened version of all the supported blocks in a single array.
711 * This is an optimization to make supportedCodepoint() fast.
712 */
713
714var allBlocks = [];
715scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b)));
716/**
717 * Given a codepoint, return true if it falls within one of the
718 * scripts or script families defined above and false otherwise.
719 *
720 * Micro benchmarks shows that this is faster than
721 * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test()
722 * in Firefox, Chrome and Node.
723 */
724
725function supportedCodepoint(codepoint) {
726 for (var i = 0; i < allBlocks.length; i += 2) {
727 if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) {
728 return true;
729 }
730 }
731
732 return false;
733}
734
735/**
736 * This file provides support to domTree.js and delimiter.js.
737 * It's a storehouse of path geometry for SVG images.
738 */
739// In all paths below, the viewBox-to-em scale is 1000:1.
740var hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping.
741// The viniculum of a \sqrt can be made thicker by a KaTeX rendering option.
742// Think of variable extraViniculum as two detours in the SVG path.
743// The detour begins at the lower left of the area labeled extraViniculum below.
744// The detour proceeds one extraViniculum distance up and slightly to the right,
745// displacing the radiused corner between surd and viniculum. The radius is
746// traversed as usual, then the detour resumes. It goes right, to the end of
747// the very long viniculumn, then down one extraViniculum distance,
748// after which it resumes regular path geometry for the radical.
749
750/* viniculum
751 /
752 /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum
753 / █████████████████████←0.04em (40 unit) std viniculum thickness
754 / /
755 / /
756 / /\
757 / / surd
758*/
759
760var sqrtMain = function sqrtMain(extraViniculum, hLinePad) {
761 // sqrtMain path geometry is from glyph U221A in the font KaTeX Main
762 return "M95," + (622 + extraViniculum + hLinePad) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + extraViniculum / 2.075 + " -" + extraViniculum + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + extraViniculum) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z";
763};
764
765var sqrtSize1 = function sqrtSize1(extraViniculum, hLinePad) {
766 // size1 is from glyph U221A in the font KaTeX_Size1-Regular
767 return "M263," + (601 + extraViniculum + hLinePad) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + extraViniculum / 2.084 + " -" + extraViniculum + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + extraViniculum) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z";
768};
769
770var sqrtSize2 = function sqrtSize2(extraViniculum, hLinePad) {
771 // size2 is from glyph U221A in the font KaTeX_Size2-Regular
772 return "M983 " + (10 + extraViniculum + hLinePad) + "\nl" + extraViniculum / 3.13 + " -" + extraViniculum + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + extraViniculum) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z";
773};
774
775var sqrtSize3 = function sqrtSize3(extraViniculum, hLinePad) {
776 // size3 is from glyph U221A in the font KaTeX_Size3-Regular
777 return "M424," + (2398 + extraViniculum + hLinePad) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + extraViniculum / 4.223 + " -" + extraViniculum + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + extraViniculum) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + extraViniculum) + " " + hLinePad + "\nh400000v" + (40 + extraViniculum) + "h-400000z";
778};
779
780var sqrtSize4 = function sqrtSize4(extraViniculum, hLinePad) {
781 // size4 is from glyph U221A in the font KaTeX_Size4-Regular
782 return "M473," + (2713 + extraViniculum + hLinePad) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + extraViniculum / 5.298 + " -" + extraViniculum + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + extraViniculum) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "H1017.7z";
783};
784
785var phasePath = function phasePath(y) {
786 var x = y / 2; // x coordinate at top of angle
787
788 return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z";
789};
790
791var sqrtTall = function sqrtTall(extraViniculum, hLinePad, viewBoxHeight) {
792 // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
793 // One path edge has a variable length. It runs vertically from the viniculumn
794 // to a point near (14 units) the bottom of the surd. The viniculum
795 // is normally 40 units thick. So the length of the line in question is:
796 var vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum;
797 return "M702 " + (extraViniculum + hLinePad) + "H400000" + (40 + extraViniculum) + "\nH742v" + vertSegment + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + hLinePad + "H400000v" + (40 + extraViniculum) + "H742z";
798};
799
800var sqrtPath = function sqrtPath(size, extraViniculum, viewBoxHeight) {
801 extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox.
802
803 var path = "";
804
805 switch (size) {
806 case "sqrtMain":
807 path = sqrtMain(extraViniculum, hLinePad);
808 break;
809
810 case "sqrtSize1":
811 path = sqrtSize1(extraViniculum, hLinePad);
812 break;
813
814 case "sqrtSize2":
815 path = sqrtSize2(extraViniculum, hLinePad);
816 break;
817
818 case "sqrtSize3":
819 path = sqrtSize3(extraViniculum, hLinePad);
820 break;
821
822 case "sqrtSize4":
823 path = sqrtSize4(extraViniculum, hLinePad);
824 break;
825
826 case "sqrtTall":
827 path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight);
828 }
829
830 return path;
831};
832var innerPath = function innerPath(name, height) {
833 // The inner part of stretchy tall delimiters
834 switch (name) {
835 case "\u239c":
836 return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z";
837
838 case "\u2223":
839 return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z";
840
841 case "\u2225":
842 return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z" + ("M367 0 H410 V" + height + " H367z M367 0 H410 V" + height + " H367z");
843
844 case "\u239f":
845 return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z";
846
847 case "\u23a2":
848 return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z";
849
850 case "\u23a5":
851 return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z";
852
853 case "\u23aa":
854 return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z";
855
856 case "\u23d0":
857 return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z";
858
859 case "\u2016":
860 return "M257 0 H300 V" + height + " H257z M257 0 H300 V" + height + " H257z" + ("M478 0 H521 V" + height + " H478z M478 0 H521 V" + height + " H478z");
861
862 default:
863 return "";
864 }
865};
866var path = {
867 // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main
868 doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",
869 // doublerightarrow is from glyph U+21D2 in font KaTeX Main
870 doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",
871 // leftarrow is from glyph U+2190 in font KaTeX Main
872 leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",
873 // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular
874 leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",
875 leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",
876 // overgroup is from the MnSymbol package (public domain)
877 leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",
878 leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",
879 // Harpoons are from glyph U+21BD in font KaTeX Main
880 leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",
881 leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",
882 leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",
883 leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",
884 // hook is from glyph U+21A9 in font KaTeX Main
885 lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",
886 leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",
887 leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",
888 // tofrom is from glyph U+21C4 in font KaTeX AMS Regular
889 leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",
890 longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",
891 midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",
892 midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",
893 oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",
894 oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",
895 oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",
896 oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",
897 rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",
898 rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",
899 rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",
900 rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",
901 rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",
902 rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",
903 rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",
904 rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",
905 rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",
906 righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",
907 rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",
908 rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",
909 // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular
910 twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",
911 twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",
912 // tilde1 is a modified version of a glyph from the MnSymbol package
913 tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",
914 // ditto tilde2, tilde3, & tilde4
915 tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",
916 tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",
917 tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",
918 // vec is from glyph U+20D7 in font KaTeX Main
919 vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",
920 // widehat1 is a modified version of a glyph from the MnSymbol package
921 widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",
922 // ditto widehat2, widehat3, & widehat4
923 widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
924 widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
925 widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
926 // widecheck paths are all inverted versions of widehat
927 widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",
928 widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
929 widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
930 widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
931 // The next ten paths support reaction arrows from the mhchem package.
932 // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX
933 // baraboveleftarrow is mostly from from glyph U+2190 in font KaTeX Main
934 baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",
935 // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main
936 rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",
937 // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end.
938 // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em
939 baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",
940 rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",
941 shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",
942 shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"
943};
944
945/**
946 * This node represents a document fragment, which contains elements, but when
947 * placed into the DOM doesn't have any representation itself. It only contains
948 * children and doesn't have any DOM node properties.
949 */
950class DocumentFragment {
951 // HtmlDomNode
952 // Never used; needed for satisfying interface.
953 constructor(children) {
954 this.children = void 0;
955 this.classes = void 0;
956 this.height = void 0;
957 this.depth = void 0;
958 this.maxFontSize = void 0;
959 this.style = void 0;
960 this.children = children;
961 this.classes = [];
962 this.height = 0;
963 this.depth = 0;
964 this.maxFontSize = 0;
965 this.style = {};
966 }
967
968 hasClass(className) {
969 return utils.contains(this.classes, className);
970 }
971 /** Convert the fragment into a node. */
972
973
974 toNode() {
975 var frag = document.createDocumentFragment();
976
977 for (var i = 0; i < this.children.length; i++) {
978 frag.appendChild(this.children[i].toNode());
979 }
980
981 return frag;
982 }
983 /** Convert the fragment into HTML markup. */
984
985
986 toMarkup() {
987 var markup = ""; // Simply concatenate the markup for the children together.
988
989 for (var i = 0; i < this.children.length; i++) {
990 markup += this.children[i].toMarkup();
991 }
992
993 return markup;
994 }
995 /**
996 * Converts the math node into a string, similar to innerText. Applies to
997 * MathDomNode's only.
998 */
999
1000
1001 toText() {
1002 // To avoid this, we would subclass documentFragment separately for
1003 // MathML, but polyfills for subclassing is expensive per PR 1469.
1004 // $FlowFixMe: Only works for ChildType = MathDomNode.
1005 var toText = child => child.toText();
1006
1007 return this.children.map(toText).join("");
1008 }
1009
1010}
1011
1012// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY.
1013var fontMetricsData = {
1014 "AMS-Regular": {
1015 "32": [0, 0, 0, 0, 0.25],
1016 "65": [0, 0.68889, 0, 0, 0.72222],
1017 "66": [0, 0.68889, 0, 0, 0.66667],
1018 "67": [0, 0.68889, 0, 0, 0.72222],
1019 "68": [0, 0.68889, 0, 0, 0.72222],
1020 "69": [0, 0.68889, 0, 0, 0.66667],
1021 "70": [0, 0.68889, 0, 0, 0.61111],
1022 "71": [0, 0.68889, 0, 0, 0.77778],
1023 "72": [0, 0.68889, 0, 0, 0.77778],
1024 "73": [0, 0.68889, 0, 0, 0.38889],
1025 "74": [0.16667, 0.68889, 0, 0, 0.5],
1026 "75": [0, 0.68889, 0, 0, 0.77778],
1027 "76": [0, 0.68889, 0, 0, 0.66667],
1028 "77": [0, 0.68889, 0, 0, 0.94445],
1029 "78": [0, 0.68889, 0, 0, 0.72222],
1030 "79": [0.16667, 0.68889, 0, 0, 0.77778],
1031 "80": [0, 0.68889, 0, 0, 0.61111],
1032 "81": [0.16667, 0.68889, 0, 0, 0.77778],
1033 "82": [0, 0.68889, 0, 0, 0.72222],
1034 "83": [0, 0.68889, 0, 0, 0.55556],
1035 "84": [0, 0.68889, 0, 0, 0.66667],
1036 "85": [0, 0.68889, 0, 0, 0.72222],
1037 "86": [0, 0.68889, 0, 0, 0.72222],
1038 "87": [0, 0.68889, 0, 0, 1.0],
1039 "88": [0, 0.68889, 0, 0, 0.72222],
1040 "89": [0, 0.68889, 0, 0, 0.72222],
1041 "90": [0, 0.68889, 0, 0, 0.66667],
1042 "107": [0, 0.68889, 0, 0, 0.55556],
1043 "160": [0, 0, 0, 0, 0.25],
1044 "165": [0, 0.675, 0.025, 0, 0.75],
1045 "174": [0.15559, 0.69224, 0, 0, 0.94666],
1046 "240": [0, 0.68889, 0, 0, 0.55556],
1047 "295": [0, 0.68889, 0, 0, 0.54028],
1048 "710": [0, 0.825, 0, 0, 2.33334],
1049 "732": [0, 0.9, 0, 0, 2.33334],
1050 "770": [0, 0.825, 0, 0, 2.33334],
1051 "771": [0, 0.9, 0, 0, 2.33334],
1052 "989": [0.08167, 0.58167, 0, 0, 0.77778],
1053 "1008": [0, 0.43056, 0.04028, 0, 0.66667],
1054 "8245": [0, 0.54986, 0, 0, 0.275],
1055 "8463": [0, 0.68889, 0, 0, 0.54028],
1056 "8487": [0, 0.68889, 0, 0, 0.72222],
1057 "8498": [0, 0.68889, 0, 0, 0.55556],
1058 "8502": [0, 0.68889, 0, 0, 0.66667],
1059 "8503": [0, 0.68889, 0, 0, 0.44445],
1060 "8504": [0, 0.68889, 0, 0, 0.66667],
1061 "8513": [0, 0.68889, 0, 0, 0.63889],
1062 "8592": [-0.03598, 0.46402, 0, 0, 0.5],
1063 "8594": [-0.03598, 0.46402, 0, 0, 0.5],
1064 "8602": [-0.13313, 0.36687, 0, 0, 1.0],
1065 "8603": [-0.13313, 0.36687, 0, 0, 1.0],
1066 "8606": [0.01354, 0.52239, 0, 0, 1.0],
1067 "8608": [0.01354, 0.52239, 0, 0, 1.0],
1068 "8610": [0.01354, 0.52239, 0, 0, 1.11111],
1069 "8611": [0.01354, 0.52239, 0, 0, 1.11111],
1070 "8619": [0, 0.54986, 0, 0, 1.0],
1071 "8620": [0, 0.54986, 0, 0, 1.0],
1072 "8621": [-0.13313, 0.37788, 0, 0, 1.38889],
1073 "8622": [-0.13313, 0.36687, 0, 0, 1.0],
1074 "8624": [0, 0.69224, 0, 0, 0.5],
1075 "8625": [0, 0.69224, 0, 0, 0.5],
1076 "8630": [0, 0.43056, 0, 0, 1.0],
1077 "8631": [0, 0.43056, 0, 0, 1.0],
1078 "8634": [0.08198, 0.58198, 0, 0, 0.77778],
1079 "8635": [0.08198, 0.58198, 0, 0, 0.77778],
1080 "8638": [0.19444, 0.69224, 0, 0, 0.41667],
1081 "8639": [0.19444, 0.69224, 0, 0, 0.41667],
1082 "8642": [0.19444, 0.69224, 0, 0, 0.41667],
1083 "8643": [0.19444, 0.69224, 0, 0, 0.41667],
1084 "8644": [0.1808, 0.675, 0, 0, 1.0],
1085 "8646": [0.1808, 0.675, 0, 0, 1.0],
1086 "8647": [0.1808, 0.675, 0, 0, 1.0],
1087 "8648": [0.19444, 0.69224, 0, 0, 0.83334],
1088 "8649": [0.1808, 0.675, 0, 0, 1.0],
1089 "8650": [0.19444, 0.69224, 0, 0, 0.83334],
1090 "8651": [0.01354, 0.52239, 0, 0, 1.0],
1091 "8652": [0.01354, 0.52239, 0, 0, 1.0],
1092 "8653": [-0.13313, 0.36687, 0, 0, 1.0],
1093 "8654": [-0.13313, 0.36687, 0, 0, 1.0],
1094 "8655": [-0.13313, 0.36687, 0, 0, 1.0],
1095 "8666": [0.13667, 0.63667, 0, 0, 1.0],
1096 "8667": [0.13667, 0.63667, 0, 0, 1.0],
1097 "8669": [-0.13313, 0.37788, 0, 0, 1.0],
1098 "8672": [-0.064, 0.437, 0, 0, 1.334],
1099 "8674": [-0.064, 0.437, 0, 0, 1.334],
1100 "8705": [0, 0.825, 0, 0, 0.5],
1101 "8708": [0, 0.68889, 0, 0, 0.55556],
1102 "8709": [0.08167, 0.58167, 0, 0, 0.77778],
1103 "8717": [0, 0.43056, 0, 0, 0.42917],
1104 "8722": [-0.03598, 0.46402, 0, 0, 0.5],
1105 "8724": [0.08198, 0.69224, 0, 0, 0.77778],
1106 "8726": [0.08167, 0.58167, 0, 0, 0.77778],
1107 "8733": [0, 0.69224, 0, 0, 0.77778],
1108 "8736": [0, 0.69224, 0, 0, 0.72222],
1109 "8737": [0, 0.69224, 0, 0, 0.72222],
1110 "8738": [0.03517, 0.52239, 0, 0, 0.72222],
1111 "8739": [0.08167, 0.58167, 0, 0, 0.22222],
1112 "8740": [0.25142, 0.74111, 0, 0, 0.27778],
1113 "8741": [0.08167, 0.58167, 0, 0, 0.38889],
1114 "8742": [0.25142, 0.74111, 0, 0, 0.5],
1115 "8756": [0, 0.69224, 0, 0, 0.66667],
1116 "8757": [0, 0.69224, 0, 0, 0.66667],
1117 "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
1118 "8765": [-0.13313, 0.37788, 0, 0, 0.77778],
1119 "8769": [-0.13313, 0.36687, 0, 0, 0.77778],
1120 "8770": [-0.03625, 0.46375, 0, 0, 0.77778],
1121 "8774": [0.30274, 0.79383, 0, 0, 0.77778],
1122 "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
1123 "8778": [0.08167, 0.58167, 0, 0, 0.77778],
1124 "8782": [0.06062, 0.54986, 0, 0, 0.77778],
1125 "8783": [0.06062, 0.54986, 0, 0, 0.77778],
1126 "8785": [0.08198, 0.58198, 0, 0, 0.77778],
1127 "8786": [0.08198, 0.58198, 0, 0, 0.77778],
1128 "8787": [0.08198, 0.58198, 0, 0, 0.77778],
1129 "8790": [0, 0.69224, 0, 0, 0.77778],
1130 "8791": [0.22958, 0.72958, 0, 0, 0.77778],
1131 "8796": [0.08198, 0.91667, 0, 0, 0.77778],
1132 "8806": [0.25583, 0.75583, 0, 0, 0.77778],
1133 "8807": [0.25583, 0.75583, 0, 0, 0.77778],
1134 "8808": [0.25142, 0.75726, 0, 0, 0.77778],
1135 "8809": [0.25142, 0.75726, 0, 0, 0.77778],
1136 "8812": [0.25583, 0.75583, 0, 0, 0.5],
1137 "8814": [0.20576, 0.70576, 0, 0, 0.77778],
1138 "8815": [0.20576, 0.70576, 0, 0, 0.77778],
1139 "8816": [0.30274, 0.79383, 0, 0, 0.77778],
1140 "8817": [0.30274, 0.79383, 0, 0, 0.77778],
1141 "8818": [0.22958, 0.72958, 0, 0, 0.77778],
1142 "8819": [0.22958, 0.72958, 0, 0, 0.77778],
1143 "8822": [0.1808, 0.675, 0, 0, 0.77778],
1144 "8823": [0.1808, 0.675, 0, 0, 0.77778],
1145 "8828": [0.13667, 0.63667, 0, 0, 0.77778],
1146 "8829": [0.13667, 0.63667, 0, 0, 0.77778],
1147 "8830": [0.22958, 0.72958, 0, 0, 0.77778],
1148 "8831": [0.22958, 0.72958, 0, 0, 0.77778],
1149 "8832": [0.20576, 0.70576, 0, 0, 0.77778],
1150 "8833": [0.20576, 0.70576, 0, 0, 0.77778],
1151 "8840": [0.30274, 0.79383, 0, 0, 0.77778],
1152 "8841": [0.30274, 0.79383, 0, 0, 0.77778],
1153 "8842": [0.13597, 0.63597, 0, 0, 0.77778],
1154 "8843": [0.13597, 0.63597, 0, 0, 0.77778],
1155 "8847": [0.03517, 0.54986, 0, 0, 0.77778],
1156 "8848": [0.03517, 0.54986, 0, 0, 0.77778],
1157 "8858": [0.08198, 0.58198, 0, 0, 0.77778],
1158 "8859": [0.08198, 0.58198, 0, 0, 0.77778],
1159 "8861": [0.08198, 0.58198, 0, 0, 0.77778],
1160 "8862": [0, 0.675, 0, 0, 0.77778],
1161 "8863": [0, 0.675, 0, 0, 0.77778],
1162 "8864": [0, 0.675, 0, 0, 0.77778],
1163 "8865": [0, 0.675, 0, 0, 0.77778],
1164 "8872": [0, 0.69224, 0, 0, 0.61111],
1165 "8873": [0, 0.69224, 0, 0, 0.72222],
1166 "8874": [0, 0.69224, 0, 0, 0.88889],
1167 "8876": [0, 0.68889, 0, 0, 0.61111],
1168 "8877": [0, 0.68889, 0, 0, 0.61111],
1169 "8878": [0, 0.68889, 0, 0, 0.72222],
1170 "8879": [0, 0.68889, 0, 0, 0.72222],
1171 "8882": [0.03517, 0.54986, 0, 0, 0.77778],
1172 "8883": [0.03517, 0.54986, 0, 0, 0.77778],
1173 "8884": [0.13667, 0.63667, 0, 0, 0.77778],
1174 "8885": [0.13667, 0.63667, 0, 0, 0.77778],
1175 "8888": [0, 0.54986, 0, 0, 1.11111],
1176 "8890": [0.19444, 0.43056, 0, 0, 0.55556],
1177 "8891": [0.19444, 0.69224, 0, 0, 0.61111],
1178 "8892": [0.19444, 0.69224, 0, 0, 0.61111],
1179 "8901": [0, 0.54986, 0, 0, 0.27778],
1180 "8903": [0.08167, 0.58167, 0, 0, 0.77778],
1181 "8905": [0.08167, 0.58167, 0, 0, 0.77778],
1182 "8906": [0.08167, 0.58167, 0, 0, 0.77778],
1183 "8907": [0, 0.69224, 0, 0, 0.77778],
1184 "8908": [0, 0.69224, 0, 0, 0.77778],
1185 "8909": [-0.03598, 0.46402, 0, 0, 0.77778],
1186 "8910": [0, 0.54986, 0, 0, 0.76042],
1187 "8911": [0, 0.54986, 0, 0, 0.76042],
1188 "8912": [0.03517, 0.54986, 0, 0, 0.77778],
1189 "8913": [0.03517, 0.54986, 0, 0, 0.77778],
1190 "8914": [0, 0.54986, 0, 0, 0.66667],
1191 "8915": [0, 0.54986, 0, 0, 0.66667],
1192 "8916": [0, 0.69224, 0, 0, 0.66667],
1193 "8918": [0.0391, 0.5391, 0, 0, 0.77778],
1194 "8919": [0.0391, 0.5391, 0, 0, 0.77778],
1195 "8920": [0.03517, 0.54986, 0, 0, 1.33334],
1196 "8921": [0.03517, 0.54986, 0, 0, 1.33334],
1197 "8922": [0.38569, 0.88569, 0, 0, 0.77778],
1198 "8923": [0.38569, 0.88569, 0, 0, 0.77778],
1199 "8926": [0.13667, 0.63667, 0, 0, 0.77778],
1200 "8927": [0.13667, 0.63667, 0, 0, 0.77778],
1201 "8928": [0.30274, 0.79383, 0, 0, 0.77778],
1202 "8929": [0.30274, 0.79383, 0, 0, 0.77778],
1203 "8934": [0.23222, 0.74111, 0, 0, 0.77778],
1204 "8935": [0.23222, 0.74111, 0, 0, 0.77778],
1205 "8936": [0.23222, 0.74111, 0, 0, 0.77778],
1206 "8937": [0.23222, 0.74111, 0, 0, 0.77778],
1207 "8938": [0.20576, 0.70576, 0, 0, 0.77778],
1208 "8939": [0.20576, 0.70576, 0, 0, 0.77778],
1209 "8940": [0.30274, 0.79383, 0, 0, 0.77778],
1210 "8941": [0.30274, 0.79383, 0, 0, 0.77778],
1211 "8994": [0.19444, 0.69224, 0, 0, 0.77778],
1212 "8995": [0.19444, 0.69224, 0, 0, 0.77778],
1213 "9416": [0.15559, 0.69224, 0, 0, 0.90222],
1214 "9484": [0, 0.69224, 0, 0, 0.5],
1215 "9488": [0, 0.69224, 0, 0, 0.5],
1216 "9492": [0, 0.37788, 0, 0, 0.5],
1217 "9496": [0, 0.37788, 0, 0, 0.5],
1218 "9585": [0.19444, 0.68889, 0, 0, 0.88889],
1219 "9586": [0.19444, 0.74111, 0, 0, 0.88889],
1220 "9632": [0, 0.675, 0, 0, 0.77778],
1221 "9633": [0, 0.675, 0, 0, 0.77778],
1222 "9650": [0, 0.54986, 0, 0, 0.72222],
1223 "9651": [0, 0.54986, 0, 0, 0.72222],
1224 "9654": [0.03517, 0.54986, 0, 0, 0.77778],
1225 "9660": [0, 0.54986, 0, 0, 0.72222],
1226 "9661": [0, 0.54986, 0, 0, 0.72222],
1227 "9664": [0.03517, 0.54986, 0, 0, 0.77778],
1228 "9674": [0.11111, 0.69224, 0, 0, 0.66667],
1229 "9733": [0.19444, 0.69224, 0, 0, 0.94445],
1230 "10003": [0, 0.69224, 0, 0, 0.83334],
1231 "10016": [0, 0.69224, 0, 0, 0.83334],
1232 "10731": [0.11111, 0.69224, 0, 0, 0.66667],
1233 "10846": [0.19444, 0.75583, 0, 0, 0.61111],
1234 "10877": [0.13667, 0.63667, 0, 0, 0.77778],
1235 "10878": [0.13667, 0.63667, 0, 0, 0.77778],
1236 "10885": [0.25583, 0.75583, 0, 0, 0.77778],
1237 "10886": [0.25583, 0.75583, 0, 0, 0.77778],
1238 "10887": [0.13597, 0.63597, 0, 0, 0.77778],
1239 "10888": [0.13597, 0.63597, 0, 0, 0.77778],
1240 "10889": [0.26167, 0.75726, 0, 0, 0.77778],
1241 "10890": [0.26167, 0.75726, 0, 0, 0.77778],
1242 "10891": [0.48256, 0.98256, 0, 0, 0.77778],
1243 "10892": [0.48256, 0.98256, 0, 0, 0.77778],
1244 "10901": [0.13667, 0.63667, 0, 0, 0.77778],
1245 "10902": [0.13667, 0.63667, 0, 0, 0.77778],
1246 "10933": [0.25142, 0.75726, 0, 0, 0.77778],
1247 "10934": [0.25142, 0.75726, 0, 0, 0.77778],
1248 "10935": [0.26167, 0.75726, 0, 0, 0.77778],
1249 "10936": [0.26167, 0.75726, 0, 0, 0.77778],
1250 "10937": [0.26167, 0.75726, 0, 0, 0.77778],
1251 "10938": [0.26167, 0.75726, 0, 0, 0.77778],
1252 "10949": [0.25583, 0.75583, 0, 0, 0.77778],
1253 "10950": [0.25583, 0.75583, 0, 0, 0.77778],
1254 "10955": [0.28481, 0.79383, 0, 0, 0.77778],
1255 "10956": [0.28481, 0.79383, 0, 0, 0.77778],
1256 "57350": [0.08167, 0.58167, 0, 0, 0.22222],
1257 "57351": [0.08167, 0.58167, 0, 0, 0.38889],
1258 "57352": [0.08167, 0.58167, 0, 0, 0.77778],
1259 "57353": [0, 0.43056, 0.04028, 0, 0.66667],
1260 "57356": [0.25142, 0.75726, 0, 0, 0.77778],
1261 "57357": [0.25142, 0.75726, 0, 0, 0.77778],
1262 "57358": [0.41951, 0.91951, 0, 0, 0.77778],
1263 "57359": [0.30274, 0.79383, 0, 0, 0.77778],
1264 "57360": [0.30274, 0.79383, 0, 0, 0.77778],
1265 "57361": [0.41951, 0.91951, 0, 0, 0.77778],
1266 "57366": [0.25142, 0.75726, 0, 0, 0.77778],
1267 "57367": [0.25142, 0.75726, 0, 0, 0.77778],
1268 "57368": [0.25142, 0.75726, 0, 0, 0.77778],
1269 "57369": [0.25142, 0.75726, 0, 0, 0.77778],
1270 "57370": [0.13597, 0.63597, 0, 0, 0.77778],
1271 "57371": [0.13597, 0.63597, 0, 0, 0.77778]
1272 },
1273 "Caligraphic-Regular": {
1274 "32": [0, 0, 0, 0, 0.25],
1275 "65": [0, 0.68333, 0, 0.19445, 0.79847],
1276 "66": [0, 0.68333, 0.03041, 0.13889, 0.65681],
1277 "67": [0, 0.68333, 0.05834, 0.13889, 0.52653],
1278 "68": [0, 0.68333, 0.02778, 0.08334, 0.77139],
1279 "69": [0, 0.68333, 0.08944, 0.11111, 0.52778],
1280 "70": [0, 0.68333, 0.09931, 0.11111, 0.71875],
1281 "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487],
1282 "72": [0, 0.68333, 0.00965, 0.11111, 0.84452],
1283 "73": [0, 0.68333, 0.07382, 0, 0.54452],
1284 "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778],
1285 "75": [0, 0.68333, 0.01445, 0.05556, 0.76195],
1286 "76": [0, 0.68333, 0, 0.13889, 0.68972],
1287 "77": [0, 0.68333, 0, 0.13889, 1.2009],
1288 "78": [0, 0.68333, 0.14736, 0.08334, 0.82049],
1289 "79": [0, 0.68333, 0.02778, 0.11111, 0.79611],
1290 "80": [0, 0.68333, 0.08222, 0.08334, 0.69556],
1291 "81": [0.09722, 0.68333, 0, 0.11111, 0.81667],
1292 "82": [0, 0.68333, 0, 0.08334, 0.8475],
1293 "83": [0, 0.68333, 0.075, 0.13889, 0.60556],
1294 "84": [0, 0.68333, 0.25417, 0, 0.54464],
1295 "85": [0, 0.68333, 0.09931, 0.08334, 0.62583],
1296 "86": [0, 0.68333, 0.08222, 0, 0.61278],
1297 "87": [0, 0.68333, 0.08222, 0.08334, 0.98778],
1298 "88": [0, 0.68333, 0.14643, 0.13889, 0.7133],
1299 "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834],
1300 "90": [0, 0.68333, 0.07944, 0.13889, 0.72473],
1301 "160": [0, 0, 0, 0, 0.25]
1302 },
1303 "Fraktur-Regular": {
1304 "32": [0, 0, 0, 0, 0.25],
1305 "33": [0, 0.69141, 0, 0, 0.29574],
1306 "34": [0, 0.69141, 0, 0, 0.21471],
1307 "38": [0, 0.69141, 0, 0, 0.73786],
1308 "39": [0, 0.69141, 0, 0, 0.21201],
1309 "40": [0.24982, 0.74947, 0, 0, 0.38865],
1310 "41": [0.24982, 0.74947, 0, 0, 0.38865],
1311 "42": [0, 0.62119, 0, 0, 0.27764],
1312 "43": [0.08319, 0.58283, 0, 0, 0.75623],
1313 "44": [0, 0.10803, 0, 0, 0.27764],
1314 "45": [0.08319, 0.58283, 0, 0, 0.75623],
1315 "46": [0, 0.10803, 0, 0, 0.27764],
1316 "47": [0.24982, 0.74947, 0, 0, 0.50181],
1317 "48": [0, 0.47534, 0, 0, 0.50181],
1318 "49": [0, 0.47534, 0, 0, 0.50181],
1319 "50": [0, 0.47534, 0, 0, 0.50181],
1320 "51": [0.18906, 0.47534, 0, 0, 0.50181],
1321 "52": [0.18906, 0.47534, 0, 0, 0.50181],
1322 "53": [0.18906, 0.47534, 0, 0, 0.50181],
1323 "54": [0, 0.69141, 0, 0, 0.50181],
1324 "55": [0.18906, 0.47534, 0, 0, 0.50181],
1325 "56": [0, 0.69141, 0, 0, 0.50181],
1326 "57": [0.18906, 0.47534, 0, 0, 0.50181],
1327 "58": [0, 0.47534, 0, 0, 0.21606],
1328 "59": [0.12604, 0.47534, 0, 0, 0.21606],
1329 "61": [-0.13099, 0.36866, 0, 0, 0.75623],
1330 "63": [0, 0.69141, 0, 0, 0.36245],
1331 "65": [0, 0.69141, 0, 0, 0.7176],
1332 "66": [0, 0.69141, 0, 0, 0.88397],
1333 "67": [0, 0.69141, 0, 0, 0.61254],
1334 "68": [0, 0.69141, 0, 0, 0.83158],
1335 "69": [0, 0.69141, 0, 0, 0.66278],
1336 "70": [0.12604, 0.69141, 0, 0, 0.61119],
1337 "71": [0, 0.69141, 0, 0, 0.78539],
1338 "72": [0.06302, 0.69141, 0, 0, 0.7203],
1339 "73": [0, 0.69141, 0, 0, 0.55448],
1340 "74": [0.12604, 0.69141, 0, 0, 0.55231],
1341 "75": [0, 0.69141, 0, 0, 0.66845],
1342 "76": [0, 0.69141, 0, 0, 0.66602],
1343 "77": [0, 0.69141, 0, 0, 1.04953],
1344 "78": [0, 0.69141, 0, 0, 0.83212],
1345 "79": [0, 0.69141, 0, 0, 0.82699],
1346 "80": [0.18906, 0.69141, 0, 0, 0.82753],
1347 "81": [0.03781, 0.69141, 0, 0, 0.82699],
1348 "82": [0, 0.69141, 0, 0, 0.82807],
1349 "83": [0, 0.69141, 0, 0, 0.82861],
1350 "84": [0, 0.69141, 0, 0, 0.66899],
1351 "85": [0, 0.69141, 0, 0, 0.64576],
1352 "86": [0, 0.69141, 0, 0, 0.83131],
1353 "87": [0, 0.69141, 0, 0, 1.04602],
1354 "88": [0, 0.69141, 0, 0, 0.71922],
1355 "89": [0.18906, 0.69141, 0, 0, 0.83293],
1356 "90": [0.12604, 0.69141, 0, 0, 0.60201],
1357 "91": [0.24982, 0.74947, 0, 0, 0.27764],
1358 "93": [0.24982, 0.74947, 0, 0, 0.27764],
1359 "94": [0, 0.69141, 0, 0, 0.49965],
1360 "97": [0, 0.47534, 0, 0, 0.50046],
1361 "98": [0, 0.69141, 0, 0, 0.51315],
1362 "99": [0, 0.47534, 0, 0, 0.38946],
1363 "100": [0, 0.62119, 0, 0, 0.49857],
1364 "101": [0, 0.47534, 0, 0, 0.40053],
1365 "102": [0.18906, 0.69141, 0, 0, 0.32626],
1366 "103": [0.18906, 0.47534, 0, 0, 0.5037],
1367 "104": [0.18906, 0.69141, 0, 0, 0.52126],
1368 "105": [0, 0.69141, 0, 0, 0.27899],
1369 "106": [0, 0.69141, 0, 0, 0.28088],
1370 "107": [0, 0.69141, 0, 0, 0.38946],
1371 "108": [0, 0.69141, 0, 0, 0.27953],
1372 "109": [0, 0.47534, 0, 0, 0.76676],
1373 "110": [0, 0.47534, 0, 0, 0.52666],
1374 "111": [0, 0.47534, 0, 0, 0.48885],
1375 "112": [0.18906, 0.52396, 0, 0, 0.50046],
1376 "113": [0.18906, 0.47534, 0, 0, 0.48912],
1377 "114": [0, 0.47534, 0, 0, 0.38919],
1378 "115": [0, 0.47534, 0, 0, 0.44266],
1379 "116": [0, 0.62119, 0, 0, 0.33301],
1380 "117": [0, 0.47534, 0, 0, 0.5172],
1381 "118": [0, 0.52396, 0, 0, 0.5118],
1382 "119": [0, 0.52396, 0, 0, 0.77351],
1383 "120": [0.18906, 0.47534, 0, 0, 0.38865],
1384 "121": [0.18906, 0.47534, 0, 0, 0.49884],
1385 "122": [0.18906, 0.47534, 0, 0, 0.39054],
1386 "160": [0, 0, 0, 0, 0.25],
1387 "8216": [0, 0.69141, 0, 0, 0.21471],
1388 "8217": [0, 0.69141, 0, 0, 0.21471],
1389 "58112": [0, 0.62119, 0, 0, 0.49749],
1390 "58113": [0, 0.62119, 0, 0, 0.4983],
1391 "58114": [0.18906, 0.69141, 0, 0, 0.33328],
1392 "58115": [0.18906, 0.69141, 0, 0, 0.32923],
1393 "58116": [0.18906, 0.47534, 0, 0, 0.50343],
1394 "58117": [0, 0.69141, 0, 0, 0.33301],
1395 "58118": [0, 0.62119, 0, 0, 0.33409],
1396 "58119": [0, 0.47534, 0, 0, 0.50073]
1397 },
1398 "Main-Bold": {
1399 "32": [0, 0, 0, 0, 0.25],
1400 "33": [0, 0.69444, 0, 0, 0.35],
1401 "34": [0, 0.69444, 0, 0, 0.60278],
1402 "35": [0.19444, 0.69444, 0, 0, 0.95833],
1403 "36": [0.05556, 0.75, 0, 0, 0.575],
1404 "37": [0.05556, 0.75, 0, 0, 0.95833],
1405 "38": [0, 0.69444, 0, 0, 0.89444],
1406 "39": [0, 0.69444, 0, 0, 0.31944],
1407 "40": [0.25, 0.75, 0, 0, 0.44722],
1408 "41": [0.25, 0.75, 0, 0, 0.44722],
1409 "42": [0, 0.75, 0, 0, 0.575],
1410 "43": [0.13333, 0.63333, 0, 0, 0.89444],
1411 "44": [0.19444, 0.15556, 0, 0, 0.31944],
1412 "45": [0, 0.44444, 0, 0, 0.38333],
1413 "46": [0, 0.15556, 0, 0, 0.31944],
1414 "47": [0.25, 0.75, 0, 0, 0.575],
1415 "48": [0, 0.64444, 0, 0, 0.575],
1416 "49": [0, 0.64444, 0, 0, 0.575],
1417 "50": [0, 0.64444, 0, 0, 0.575],
1418 "51": [0, 0.64444, 0, 0, 0.575],
1419 "52": [0, 0.64444, 0, 0, 0.575],
1420 "53": [0, 0.64444, 0, 0, 0.575],
1421 "54": [0, 0.64444, 0, 0, 0.575],
1422 "55": [0, 0.64444, 0, 0, 0.575],
1423 "56": [0, 0.64444, 0, 0, 0.575],
1424 "57": [0, 0.64444, 0, 0, 0.575],
1425 "58": [0, 0.44444, 0, 0, 0.31944],
1426 "59": [0.19444, 0.44444, 0, 0, 0.31944],
1427 "60": [0.08556, 0.58556, 0, 0, 0.89444],
1428 "61": [-0.10889, 0.39111, 0, 0, 0.89444],
1429 "62": [0.08556, 0.58556, 0, 0, 0.89444],
1430 "63": [0, 0.69444, 0, 0, 0.54305],
1431 "64": [0, 0.69444, 0, 0, 0.89444],
1432 "65": [0, 0.68611, 0, 0, 0.86944],
1433 "66": [0, 0.68611, 0, 0, 0.81805],
1434 "67": [0, 0.68611, 0, 0, 0.83055],
1435 "68": [0, 0.68611, 0, 0, 0.88194],
1436 "69": [0, 0.68611, 0, 0, 0.75555],
1437 "70": [0, 0.68611, 0, 0, 0.72361],
1438 "71": [0, 0.68611, 0, 0, 0.90416],
1439 "72": [0, 0.68611, 0, 0, 0.9],
1440 "73": [0, 0.68611, 0, 0, 0.43611],
1441 "74": [0, 0.68611, 0, 0, 0.59444],
1442 "75": [0, 0.68611, 0, 0, 0.90138],
1443 "76": [0, 0.68611, 0, 0, 0.69166],
1444 "77": [0, 0.68611, 0, 0, 1.09166],
1445 "78": [0, 0.68611, 0, 0, 0.9],
1446 "79": [0, 0.68611, 0, 0, 0.86388],
1447 "80": [0, 0.68611, 0, 0, 0.78611],
1448 "81": [0.19444, 0.68611, 0, 0, 0.86388],
1449 "82": [0, 0.68611, 0, 0, 0.8625],
1450 "83": [0, 0.68611, 0, 0, 0.63889],
1451 "84": [0, 0.68611, 0, 0, 0.8],
1452 "85": [0, 0.68611, 0, 0, 0.88472],
1453 "86": [0, 0.68611, 0.01597, 0, 0.86944],
1454 "87": [0, 0.68611, 0.01597, 0, 1.18888],
1455 "88": [0, 0.68611, 0, 0, 0.86944],
1456 "89": [0, 0.68611, 0.02875, 0, 0.86944],
1457 "90": [0, 0.68611, 0, 0, 0.70277],
1458 "91": [0.25, 0.75, 0, 0, 0.31944],
1459 "92": [0.25, 0.75, 0, 0, 0.575],
1460 "93": [0.25, 0.75, 0, 0, 0.31944],
1461 "94": [0, 0.69444, 0, 0, 0.575],
1462 "95": [0.31, 0.13444, 0.03194, 0, 0.575],
1463 "97": [0, 0.44444, 0, 0, 0.55902],
1464 "98": [0, 0.69444, 0, 0, 0.63889],
1465 "99": [0, 0.44444, 0, 0, 0.51111],
1466 "100": [0, 0.69444, 0, 0, 0.63889],
1467 "101": [0, 0.44444, 0, 0, 0.52708],
1468 "102": [0, 0.69444, 0.10903, 0, 0.35139],
1469 "103": [0.19444, 0.44444, 0.01597, 0, 0.575],
1470 "104": [0, 0.69444, 0, 0, 0.63889],
1471 "105": [0, 0.69444, 0, 0, 0.31944],
1472 "106": [0.19444, 0.69444, 0, 0, 0.35139],
1473 "107": [0, 0.69444, 0, 0, 0.60694],
1474 "108": [0, 0.69444, 0, 0, 0.31944],
1475 "109": [0, 0.44444, 0, 0, 0.95833],
1476 "110": [0, 0.44444, 0, 0, 0.63889],
1477 "111": [0, 0.44444, 0, 0, 0.575],
1478 "112": [0.19444, 0.44444, 0, 0, 0.63889],
1479 "113": [0.19444, 0.44444, 0, 0, 0.60694],
1480 "114": [0, 0.44444, 0, 0, 0.47361],
1481 "115": [0, 0.44444, 0, 0, 0.45361],
1482 "116": [0, 0.63492, 0, 0, 0.44722],
1483 "117": [0, 0.44444, 0, 0, 0.63889],
1484 "118": [0, 0.44444, 0.01597, 0, 0.60694],
1485 "119": [0, 0.44444, 0.01597, 0, 0.83055],
1486 "120": [0, 0.44444, 0, 0, 0.60694],
1487 "121": [0.19444, 0.44444, 0.01597, 0, 0.60694],
1488 "122": [0, 0.44444, 0, 0, 0.51111],
1489 "123": [0.25, 0.75, 0, 0, 0.575],
1490 "124": [0.25, 0.75, 0, 0, 0.31944],
1491 "125": [0.25, 0.75, 0, 0, 0.575],
1492 "126": [0.35, 0.34444, 0, 0, 0.575],
1493 "160": [0, 0, 0, 0, 0.25],
1494 "163": [0, 0.69444, 0, 0, 0.86853],
1495 "168": [0, 0.69444, 0, 0, 0.575],
1496 "172": [0, 0.44444, 0, 0, 0.76666],
1497 "176": [0, 0.69444, 0, 0, 0.86944],
1498 "177": [0.13333, 0.63333, 0, 0, 0.89444],
1499 "184": [0.17014, 0, 0, 0, 0.51111],
1500 "198": [0, 0.68611, 0, 0, 1.04166],
1501 "215": [0.13333, 0.63333, 0, 0, 0.89444],
1502 "216": [0.04861, 0.73472, 0, 0, 0.89444],
1503 "223": [0, 0.69444, 0, 0, 0.59722],
1504 "230": [0, 0.44444, 0, 0, 0.83055],
1505 "247": [0.13333, 0.63333, 0, 0, 0.89444],
1506 "248": [0.09722, 0.54167, 0, 0, 0.575],
1507 "305": [0, 0.44444, 0, 0, 0.31944],
1508 "338": [0, 0.68611, 0, 0, 1.16944],
1509 "339": [0, 0.44444, 0, 0, 0.89444],
1510 "567": [0.19444, 0.44444, 0, 0, 0.35139],
1511 "710": [0, 0.69444, 0, 0, 0.575],
1512 "711": [0, 0.63194, 0, 0, 0.575],
1513 "713": [0, 0.59611, 0, 0, 0.575],
1514 "714": [0, 0.69444, 0, 0, 0.575],
1515 "715": [0, 0.69444, 0, 0, 0.575],
1516 "728": [0, 0.69444, 0, 0, 0.575],
1517 "729": [0, 0.69444, 0, 0, 0.31944],
1518 "730": [0, 0.69444, 0, 0, 0.86944],
1519 "732": [0, 0.69444, 0, 0, 0.575],
1520 "733": [0, 0.69444, 0, 0, 0.575],
1521 "915": [0, 0.68611, 0, 0, 0.69166],
1522 "916": [0, 0.68611, 0, 0, 0.95833],
1523 "920": [0, 0.68611, 0, 0, 0.89444],
1524 "923": [0, 0.68611, 0, 0, 0.80555],
1525 "926": [0, 0.68611, 0, 0, 0.76666],
1526 "928": [0, 0.68611, 0, 0, 0.9],
1527 "931": [0, 0.68611, 0, 0, 0.83055],
1528 "933": [0, 0.68611, 0, 0, 0.89444],
1529 "934": [0, 0.68611, 0, 0, 0.83055],
1530 "936": [0, 0.68611, 0, 0, 0.89444],
1531 "937": [0, 0.68611, 0, 0, 0.83055],
1532 "8211": [0, 0.44444, 0.03194, 0, 0.575],
1533 "8212": [0, 0.44444, 0.03194, 0, 1.14999],
1534 "8216": [0, 0.69444, 0, 0, 0.31944],
1535 "8217": [0, 0.69444, 0, 0, 0.31944],
1536 "8220": [0, 0.69444, 0, 0, 0.60278],
1537 "8221": [0, 0.69444, 0, 0, 0.60278],
1538 "8224": [0.19444, 0.69444, 0, 0, 0.51111],
1539 "8225": [0.19444, 0.69444, 0, 0, 0.51111],
1540 "8242": [0, 0.55556, 0, 0, 0.34444],
1541 "8407": [0, 0.72444, 0.15486, 0, 0.575],
1542 "8463": [0, 0.69444, 0, 0, 0.66759],
1543 "8465": [0, 0.69444, 0, 0, 0.83055],
1544 "8467": [0, 0.69444, 0, 0, 0.47361],
1545 "8472": [0.19444, 0.44444, 0, 0, 0.74027],
1546 "8476": [0, 0.69444, 0, 0, 0.83055],
1547 "8501": [0, 0.69444, 0, 0, 0.70277],
1548 "8592": [-0.10889, 0.39111, 0, 0, 1.14999],
1549 "8593": [0.19444, 0.69444, 0, 0, 0.575],
1550 "8594": [-0.10889, 0.39111, 0, 0, 1.14999],
1551 "8595": [0.19444, 0.69444, 0, 0, 0.575],
1552 "8596": [-0.10889, 0.39111, 0, 0, 1.14999],
1553 "8597": [0.25, 0.75, 0, 0, 0.575],
1554 "8598": [0.19444, 0.69444, 0, 0, 1.14999],
1555 "8599": [0.19444, 0.69444, 0, 0, 1.14999],
1556 "8600": [0.19444, 0.69444, 0, 0, 1.14999],
1557 "8601": [0.19444, 0.69444, 0, 0, 1.14999],
1558 "8636": [-0.10889, 0.39111, 0, 0, 1.14999],
1559 "8637": [-0.10889, 0.39111, 0, 0, 1.14999],
1560 "8640": [-0.10889, 0.39111, 0, 0, 1.14999],
1561 "8641": [-0.10889, 0.39111, 0, 0, 1.14999],
1562 "8656": [-0.10889, 0.39111, 0, 0, 1.14999],
1563 "8657": [0.19444, 0.69444, 0, 0, 0.70277],
1564 "8658": [-0.10889, 0.39111, 0, 0, 1.14999],
1565 "8659": [0.19444, 0.69444, 0, 0, 0.70277],
1566 "8660": [-0.10889, 0.39111, 0, 0, 1.14999],
1567 "8661": [0.25, 0.75, 0, 0, 0.70277],
1568 "8704": [0, 0.69444, 0, 0, 0.63889],
1569 "8706": [0, 0.69444, 0.06389, 0, 0.62847],
1570 "8707": [0, 0.69444, 0, 0, 0.63889],
1571 "8709": [0.05556, 0.75, 0, 0, 0.575],
1572 "8711": [0, 0.68611, 0, 0, 0.95833],
1573 "8712": [0.08556, 0.58556, 0, 0, 0.76666],
1574 "8715": [0.08556, 0.58556, 0, 0, 0.76666],
1575 "8722": [0.13333, 0.63333, 0, 0, 0.89444],
1576 "8723": [0.13333, 0.63333, 0, 0, 0.89444],
1577 "8725": [0.25, 0.75, 0, 0, 0.575],
1578 "8726": [0.25, 0.75, 0, 0, 0.575],
1579 "8727": [-0.02778, 0.47222, 0, 0, 0.575],
1580 "8728": [-0.02639, 0.47361, 0, 0, 0.575],
1581 "8729": [-0.02639, 0.47361, 0, 0, 0.575],
1582 "8730": [0.18, 0.82, 0, 0, 0.95833],
1583 "8733": [0, 0.44444, 0, 0, 0.89444],
1584 "8734": [0, 0.44444, 0, 0, 1.14999],
1585 "8736": [0, 0.69224, 0, 0, 0.72222],
1586 "8739": [0.25, 0.75, 0, 0, 0.31944],
1587 "8741": [0.25, 0.75, 0, 0, 0.575],
1588 "8743": [0, 0.55556, 0, 0, 0.76666],
1589 "8744": [0, 0.55556, 0, 0, 0.76666],
1590 "8745": [0, 0.55556, 0, 0, 0.76666],
1591 "8746": [0, 0.55556, 0, 0, 0.76666],
1592 "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875],
1593 "8764": [-0.10889, 0.39111, 0, 0, 0.89444],
1594 "8768": [0.19444, 0.69444, 0, 0, 0.31944],
1595 "8771": [0.00222, 0.50222, 0, 0, 0.89444],
1596 "8773": [0.027, 0.638, 0, 0, 0.894],
1597 "8776": [0.02444, 0.52444, 0, 0, 0.89444],
1598 "8781": [0.00222, 0.50222, 0, 0, 0.89444],
1599 "8801": [0.00222, 0.50222, 0, 0, 0.89444],
1600 "8804": [0.19667, 0.69667, 0, 0, 0.89444],
1601 "8805": [0.19667, 0.69667, 0, 0, 0.89444],
1602 "8810": [0.08556, 0.58556, 0, 0, 1.14999],
1603 "8811": [0.08556, 0.58556, 0, 0, 1.14999],
1604 "8826": [0.08556, 0.58556, 0, 0, 0.89444],
1605 "8827": [0.08556, 0.58556, 0, 0, 0.89444],
1606 "8834": [0.08556, 0.58556, 0, 0, 0.89444],
1607 "8835": [0.08556, 0.58556, 0, 0, 0.89444],
1608 "8838": [0.19667, 0.69667, 0, 0, 0.89444],
1609 "8839": [0.19667, 0.69667, 0, 0, 0.89444],
1610 "8846": [0, 0.55556, 0, 0, 0.76666],
1611 "8849": [0.19667, 0.69667, 0, 0, 0.89444],
1612 "8850": [0.19667, 0.69667, 0, 0, 0.89444],
1613 "8851": [0, 0.55556, 0, 0, 0.76666],
1614 "8852": [0, 0.55556, 0, 0, 0.76666],
1615 "8853": [0.13333, 0.63333, 0, 0, 0.89444],
1616 "8854": [0.13333, 0.63333, 0, 0, 0.89444],
1617 "8855": [0.13333, 0.63333, 0, 0, 0.89444],
1618 "8856": [0.13333, 0.63333, 0, 0, 0.89444],
1619 "8857": [0.13333, 0.63333, 0, 0, 0.89444],
1620 "8866": [0, 0.69444, 0, 0, 0.70277],
1621 "8867": [0, 0.69444, 0, 0, 0.70277],
1622 "8868": [0, 0.69444, 0, 0, 0.89444],
1623 "8869": [0, 0.69444, 0, 0, 0.89444],
1624 "8900": [-0.02639, 0.47361, 0, 0, 0.575],
1625 "8901": [-0.02639, 0.47361, 0, 0, 0.31944],
1626 "8902": [-0.02778, 0.47222, 0, 0, 0.575],
1627 "8968": [0.25, 0.75, 0, 0, 0.51111],
1628 "8969": [0.25, 0.75, 0, 0, 0.51111],
1629 "8970": [0.25, 0.75, 0, 0, 0.51111],
1630 "8971": [0.25, 0.75, 0, 0, 0.51111],
1631 "8994": [-0.13889, 0.36111, 0, 0, 1.14999],
1632 "8995": [-0.13889, 0.36111, 0, 0, 1.14999],
1633 "9651": [0.19444, 0.69444, 0, 0, 1.02222],
1634 "9657": [-0.02778, 0.47222, 0, 0, 0.575],
1635 "9661": [0.19444, 0.69444, 0, 0, 1.02222],
1636 "9667": [-0.02778, 0.47222, 0, 0, 0.575],
1637 "9711": [0.19444, 0.69444, 0, 0, 1.14999],
1638 "9824": [0.12963, 0.69444, 0, 0, 0.89444],
1639 "9825": [0.12963, 0.69444, 0, 0, 0.89444],
1640 "9826": [0.12963, 0.69444, 0, 0, 0.89444],
1641 "9827": [0.12963, 0.69444, 0, 0, 0.89444],
1642 "9837": [0, 0.75, 0, 0, 0.44722],
1643 "9838": [0.19444, 0.69444, 0, 0, 0.44722],
1644 "9839": [0.19444, 0.69444, 0, 0, 0.44722],
1645 "10216": [0.25, 0.75, 0, 0, 0.44722],
1646 "10217": [0.25, 0.75, 0, 0, 0.44722],
1647 "10815": [0, 0.68611, 0, 0, 0.9],
1648 "10927": [0.19667, 0.69667, 0, 0, 0.89444],
1649 "10928": [0.19667, 0.69667, 0, 0, 0.89444],
1650 "57376": [0.19444, 0.69444, 0, 0, 0]
1651 },
1652 "Main-BoldItalic": {
1653 "32": [0, 0, 0, 0, 0.25],
1654 "33": [0, 0.69444, 0.11417, 0, 0.38611],
1655 "34": [0, 0.69444, 0.07939, 0, 0.62055],
1656 "35": [0.19444, 0.69444, 0.06833, 0, 0.94444],
1657 "37": [0.05556, 0.75, 0.12861, 0, 0.94444],
1658 "38": [0, 0.69444, 0.08528, 0, 0.88555],
1659 "39": [0, 0.69444, 0.12945, 0, 0.35555],
1660 "40": [0.25, 0.75, 0.15806, 0, 0.47333],
1661 "41": [0.25, 0.75, 0.03306, 0, 0.47333],
1662 "42": [0, 0.75, 0.14333, 0, 0.59111],
1663 "43": [0.10333, 0.60333, 0.03306, 0, 0.88555],
1664 "44": [0.19444, 0.14722, 0, 0, 0.35555],
1665 "45": [0, 0.44444, 0.02611, 0, 0.41444],
1666 "46": [0, 0.14722, 0, 0, 0.35555],
1667 "47": [0.25, 0.75, 0.15806, 0, 0.59111],
1668 "48": [0, 0.64444, 0.13167, 0, 0.59111],
1669 "49": [0, 0.64444, 0.13167, 0, 0.59111],
1670 "50": [0, 0.64444, 0.13167, 0, 0.59111],
1671 "51": [0, 0.64444, 0.13167, 0, 0.59111],
1672 "52": [0.19444, 0.64444, 0.13167, 0, 0.59111],
1673 "53": [0, 0.64444, 0.13167, 0, 0.59111],
1674 "54": [0, 0.64444, 0.13167, 0, 0.59111],
1675 "55": [0.19444, 0.64444, 0.13167, 0, 0.59111],
1676 "56": [0, 0.64444, 0.13167, 0, 0.59111],
1677 "57": [0, 0.64444, 0.13167, 0, 0.59111],
1678 "58": [0, 0.44444, 0.06695, 0, 0.35555],
1679 "59": [0.19444, 0.44444, 0.06695, 0, 0.35555],
1680 "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555],
1681 "63": [0, 0.69444, 0.11472, 0, 0.59111],
1682 "64": [0, 0.69444, 0.09208, 0, 0.88555],
1683 "65": [0, 0.68611, 0, 0, 0.86555],
1684 "66": [0, 0.68611, 0.0992, 0, 0.81666],
1685 "67": [0, 0.68611, 0.14208, 0, 0.82666],
1686 "68": [0, 0.68611, 0.09062, 0, 0.87555],
1687 "69": [0, 0.68611, 0.11431, 0, 0.75666],
1688 "70": [0, 0.68611, 0.12903, 0, 0.72722],
1689 "71": [0, 0.68611, 0.07347, 0, 0.89527],
1690 "72": [0, 0.68611, 0.17208, 0, 0.8961],
1691 "73": [0, 0.68611, 0.15681, 0, 0.47166],
1692 "74": [0, 0.68611, 0.145, 0, 0.61055],
1693 "75": [0, 0.68611, 0.14208, 0, 0.89499],
1694 "76": [0, 0.68611, 0, 0, 0.69777],
1695 "77": [0, 0.68611, 0.17208, 0, 1.07277],
1696 "78": [0, 0.68611, 0.17208, 0, 0.8961],
1697 "79": [0, 0.68611, 0.09062, 0, 0.85499],
1698 "80": [0, 0.68611, 0.0992, 0, 0.78721],
1699 "81": [0.19444, 0.68611, 0.09062, 0, 0.85499],
1700 "82": [0, 0.68611, 0.02559, 0, 0.85944],
1701 "83": [0, 0.68611, 0.11264, 0, 0.64999],
1702 "84": [0, 0.68611, 0.12903, 0, 0.7961],
1703 "85": [0, 0.68611, 0.17208, 0, 0.88083],
1704 "86": [0, 0.68611, 0.18625, 0, 0.86555],
1705 "87": [0, 0.68611, 0.18625, 0, 1.15999],
1706 "88": [0, 0.68611, 0.15681, 0, 0.86555],
1707 "89": [0, 0.68611, 0.19803, 0, 0.86555],
1708 "90": [0, 0.68611, 0.14208, 0, 0.70888],
1709 "91": [0.25, 0.75, 0.1875, 0, 0.35611],
1710 "93": [0.25, 0.75, 0.09972, 0, 0.35611],
1711 "94": [0, 0.69444, 0.06709, 0, 0.59111],
1712 "95": [0.31, 0.13444, 0.09811, 0, 0.59111],
1713 "97": [0, 0.44444, 0.09426, 0, 0.59111],
1714 "98": [0, 0.69444, 0.07861, 0, 0.53222],
1715 "99": [0, 0.44444, 0.05222, 0, 0.53222],
1716 "100": [0, 0.69444, 0.10861, 0, 0.59111],
1717 "101": [0, 0.44444, 0.085, 0, 0.53222],
1718 "102": [0.19444, 0.69444, 0.21778, 0, 0.4],
1719 "103": [0.19444, 0.44444, 0.105, 0, 0.53222],
1720 "104": [0, 0.69444, 0.09426, 0, 0.59111],
1721 "105": [0, 0.69326, 0.11387, 0, 0.35555],
1722 "106": [0.19444, 0.69326, 0.1672, 0, 0.35555],
1723 "107": [0, 0.69444, 0.11111, 0, 0.53222],
1724 "108": [0, 0.69444, 0.10861, 0, 0.29666],
1725 "109": [0, 0.44444, 0.09426, 0, 0.94444],
1726 "110": [0, 0.44444, 0.09426, 0, 0.64999],
1727 "111": [0, 0.44444, 0.07861, 0, 0.59111],
1728 "112": [0.19444, 0.44444, 0.07861, 0, 0.59111],
1729 "113": [0.19444, 0.44444, 0.105, 0, 0.53222],
1730 "114": [0, 0.44444, 0.11111, 0, 0.50167],
1731 "115": [0, 0.44444, 0.08167, 0, 0.48694],
1732 "116": [0, 0.63492, 0.09639, 0, 0.385],
1733 "117": [0, 0.44444, 0.09426, 0, 0.62055],
1734 "118": [0, 0.44444, 0.11111, 0, 0.53222],
1735 "119": [0, 0.44444, 0.11111, 0, 0.76777],
1736 "120": [0, 0.44444, 0.12583, 0, 0.56055],
1737 "121": [0.19444, 0.44444, 0.105, 0, 0.56166],
1738 "122": [0, 0.44444, 0.13889, 0, 0.49055],
1739 "126": [0.35, 0.34444, 0.11472, 0, 0.59111],
1740 "160": [0, 0, 0, 0, 0.25],
1741 "168": [0, 0.69444, 0.11473, 0, 0.59111],
1742 "176": [0, 0.69444, 0, 0, 0.94888],
1743 "184": [0.17014, 0, 0, 0, 0.53222],
1744 "198": [0, 0.68611, 0.11431, 0, 1.02277],
1745 "216": [0.04861, 0.73472, 0.09062, 0, 0.88555],
1746 "223": [0.19444, 0.69444, 0.09736, 0, 0.665],
1747 "230": [0, 0.44444, 0.085, 0, 0.82666],
1748 "248": [0.09722, 0.54167, 0.09458, 0, 0.59111],
1749 "305": [0, 0.44444, 0.09426, 0, 0.35555],
1750 "338": [0, 0.68611, 0.11431, 0, 1.14054],
1751 "339": [0, 0.44444, 0.085, 0, 0.82666],
1752 "567": [0.19444, 0.44444, 0.04611, 0, 0.385],
1753 "710": [0, 0.69444, 0.06709, 0, 0.59111],
1754 "711": [0, 0.63194, 0.08271, 0, 0.59111],
1755 "713": [0, 0.59444, 0.10444, 0, 0.59111],
1756 "714": [0, 0.69444, 0.08528, 0, 0.59111],
1757 "715": [0, 0.69444, 0, 0, 0.59111],
1758 "728": [0, 0.69444, 0.10333, 0, 0.59111],
1759 "729": [0, 0.69444, 0.12945, 0, 0.35555],
1760 "730": [0, 0.69444, 0, 0, 0.94888],
1761 "732": [0, 0.69444, 0.11472, 0, 0.59111],
1762 "733": [0, 0.69444, 0.11472, 0, 0.59111],
1763 "915": [0, 0.68611, 0.12903, 0, 0.69777],
1764 "916": [0, 0.68611, 0, 0, 0.94444],
1765 "920": [0, 0.68611, 0.09062, 0, 0.88555],
1766 "923": [0, 0.68611, 0, 0, 0.80666],
1767 "926": [0, 0.68611, 0.15092, 0, 0.76777],
1768 "928": [0, 0.68611, 0.17208, 0, 0.8961],
1769 "931": [0, 0.68611, 0.11431, 0, 0.82666],
1770 "933": [0, 0.68611, 0.10778, 0, 0.88555],
1771 "934": [0, 0.68611, 0.05632, 0, 0.82666],
1772 "936": [0, 0.68611, 0.10778, 0, 0.88555],
1773 "937": [0, 0.68611, 0.0992, 0, 0.82666],
1774 "8211": [0, 0.44444, 0.09811, 0, 0.59111],
1775 "8212": [0, 0.44444, 0.09811, 0, 1.18221],
1776 "8216": [0, 0.69444, 0.12945, 0, 0.35555],
1777 "8217": [0, 0.69444, 0.12945, 0, 0.35555],
1778 "8220": [0, 0.69444, 0.16772, 0, 0.62055],
1779 "8221": [0, 0.69444, 0.07939, 0, 0.62055]
1780 },
1781 "Main-Italic": {
1782 "32": [0, 0, 0, 0, 0.25],
1783 "33": [0, 0.69444, 0.12417, 0, 0.30667],
1784 "34": [0, 0.69444, 0.06961, 0, 0.51444],
1785 "35": [0.19444, 0.69444, 0.06616, 0, 0.81777],
1786 "37": [0.05556, 0.75, 0.13639, 0, 0.81777],
1787 "38": [0, 0.69444, 0.09694, 0, 0.76666],
1788 "39": [0, 0.69444, 0.12417, 0, 0.30667],
1789 "40": [0.25, 0.75, 0.16194, 0, 0.40889],
1790 "41": [0.25, 0.75, 0.03694, 0, 0.40889],
1791 "42": [0, 0.75, 0.14917, 0, 0.51111],
1792 "43": [0.05667, 0.56167, 0.03694, 0, 0.76666],
1793 "44": [0.19444, 0.10556, 0, 0, 0.30667],
1794 "45": [0, 0.43056, 0.02826, 0, 0.35778],
1795 "46": [0, 0.10556, 0, 0, 0.30667],
1796 "47": [0.25, 0.75, 0.16194, 0, 0.51111],
1797 "48": [0, 0.64444, 0.13556, 0, 0.51111],
1798 "49": [0, 0.64444, 0.13556, 0, 0.51111],
1799 "50": [0, 0.64444, 0.13556, 0, 0.51111],
1800 "51": [0, 0.64444, 0.13556, 0, 0.51111],
1801 "52": [0.19444, 0.64444, 0.13556, 0, 0.51111],
1802 "53": [0, 0.64444, 0.13556, 0, 0.51111],
1803 "54": [0, 0.64444, 0.13556, 0, 0.51111],
1804 "55": [0.19444, 0.64444, 0.13556, 0, 0.51111],
1805 "56": [0, 0.64444, 0.13556, 0, 0.51111],
1806 "57": [0, 0.64444, 0.13556, 0, 0.51111],
1807 "58": [0, 0.43056, 0.0582, 0, 0.30667],
1808 "59": [0.19444, 0.43056, 0.0582, 0, 0.30667],
1809 "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666],
1810 "63": [0, 0.69444, 0.1225, 0, 0.51111],
1811 "64": [0, 0.69444, 0.09597, 0, 0.76666],
1812 "65": [0, 0.68333, 0, 0, 0.74333],
1813 "66": [0, 0.68333, 0.10257, 0, 0.70389],
1814 "67": [0, 0.68333, 0.14528, 0, 0.71555],
1815 "68": [0, 0.68333, 0.09403, 0, 0.755],
1816 "69": [0, 0.68333, 0.12028, 0, 0.67833],
1817 "70": [0, 0.68333, 0.13305, 0, 0.65277],
1818 "71": [0, 0.68333, 0.08722, 0, 0.77361],
1819 "72": [0, 0.68333, 0.16389, 0, 0.74333],
1820 "73": [0, 0.68333, 0.15806, 0, 0.38555],
1821 "74": [0, 0.68333, 0.14028, 0, 0.525],
1822 "75": [0, 0.68333, 0.14528, 0, 0.76888],
1823 "76": [0, 0.68333, 0, 0, 0.62722],
1824 "77": [0, 0.68333, 0.16389, 0, 0.89666],
1825 "78": [0, 0.68333, 0.16389, 0, 0.74333],
1826 "79": [0, 0.68333, 0.09403, 0, 0.76666],
1827 "80": [0, 0.68333, 0.10257, 0, 0.67833],
1828 "81": [0.19444, 0.68333, 0.09403, 0, 0.76666],
1829 "82": [0, 0.68333, 0.03868, 0, 0.72944],
1830 "83": [0, 0.68333, 0.11972, 0, 0.56222],
1831 "84": [0, 0.68333, 0.13305, 0, 0.71555],
1832 "85": [0, 0.68333, 0.16389, 0, 0.74333],
1833 "86": [0, 0.68333, 0.18361, 0, 0.74333],
1834 "87": [0, 0.68333, 0.18361, 0, 0.99888],
1835 "88": [0, 0.68333, 0.15806, 0, 0.74333],
1836 "89": [0, 0.68333, 0.19383, 0, 0.74333],
1837 "90": [0, 0.68333, 0.14528, 0, 0.61333],
1838 "91": [0.25, 0.75, 0.1875, 0, 0.30667],
1839 "93": [0.25, 0.75, 0.10528, 0, 0.30667],
1840 "94": [0, 0.69444, 0.06646, 0, 0.51111],
1841 "95": [0.31, 0.12056, 0.09208, 0, 0.51111],
1842 "97": [0, 0.43056, 0.07671, 0, 0.51111],
1843 "98": [0, 0.69444, 0.06312, 0, 0.46],
1844 "99": [0, 0.43056, 0.05653, 0, 0.46],
1845 "100": [0, 0.69444, 0.10333, 0, 0.51111],
1846 "101": [0, 0.43056, 0.07514, 0, 0.46],
1847 "102": [0.19444, 0.69444, 0.21194, 0, 0.30667],
1848 "103": [0.19444, 0.43056, 0.08847, 0, 0.46],
1849 "104": [0, 0.69444, 0.07671, 0, 0.51111],
1850 "105": [0, 0.65536, 0.1019, 0, 0.30667],
1851 "106": [0.19444, 0.65536, 0.14467, 0, 0.30667],
1852 "107": [0, 0.69444, 0.10764, 0, 0.46],
1853 "108": [0, 0.69444, 0.10333, 0, 0.25555],
1854 "109": [0, 0.43056, 0.07671, 0, 0.81777],
1855 "110": [0, 0.43056, 0.07671, 0, 0.56222],
1856 "111": [0, 0.43056, 0.06312, 0, 0.51111],
1857 "112": [0.19444, 0.43056, 0.06312, 0, 0.51111],
1858 "113": [0.19444, 0.43056, 0.08847, 0, 0.46],
1859 "114": [0, 0.43056, 0.10764, 0, 0.42166],
1860 "115": [0, 0.43056, 0.08208, 0, 0.40889],
1861 "116": [0, 0.61508, 0.09486, 0, 0.33222],
1862 "117": [0, 0.43056, 0.07671, 0, 0.53666],
1863 "118": [0, 0.43056, 0.10764, 0, 0.46],
1864 "119": [0, 0.43056, 0.10764, 0, 0.66444],
1865 "120": [0, 0.43056, 0.12042, 0, 0.46389],
1866 "121": [0.19444, 0.43056, 0.08847, 0, 0.48555],
1867 "122": [0, 0.43056, 0.12292, 0, 0.40889],
1868 "126": [0.35, 0.31786, 0.11585, 0, 0.51111],
1869 "160": [0, 0, 0, 0, 0.25],
1870 "168": [0, 0.66786, 0.10474, 0, 0.51111],
1871 "176": [0, 0.69444, 0, 0, 0.83129],
1872 "184": [0.17014, 0, 0, 0, 0.46],
1873 "198": [0, 0.68333, 0.12028, 0, 0.88277],
1874 "216": [0.04861, 0.73194, 0.09403, 0, 0.76666],
1875 "223": [0.19444, 0.69444, 0.10514, 0, 0.53666],
1876 "230": [0, 0.43056, 0.07514, 0, 0.71555],
1877 "248": [0.09722, 0.52778, 0.09194, 0, 0.51111],
1878 "338": [0, 0.68333, 0.12028, 0, 0.98499],
1879 "339": [0, 0.43056, 0.07514, 0, 0.71555],
1880 "710": [0, 0.69444, 0.06646, 0, 0.51111],
1881 "711": [0, 0.62847, 0.08295, 0, 0.51111],
1882 "713": [0, 0.56167, 0.10333, 0, 0.51111],
1883 "714": [0, 0.69444, 0.09694, 0, 0.51111],
1884 "715": [0, 0.69444, 0, 0, 0.51111],
1885 "728": [0, 0.69444, 0.10806, 0, 0.51111],
1886 "729": [0, 0.66786, 0.11752, 0, 0.30667],
1887 "730": [0, 0.69444, 0, 0, 0.83129],
1888 "732": [0, 0.66786, 0.11585, 0, 0.51111],
1889 "733": [0, 0.69444, 0.1225, 0, 0.51111],
1890 "915": [0, 0.68333, 0.13305, 0, 0.62722],
1891 "916": [0, 0.68333, 0, 0, 0.81777],
1892 "920": [0, 0.68333, 0.09403, 0, 0.76666],
1893 "923": [0, 0.68333, 0, 0, 0.69222],
1894 "926": [0, 0.68333, 0.15294, 0, 0.66444],
1895 "928": [0, 0.68333, 0.16389, 0, 0.74333],
1896 "931": [0, 0.68333, 0.12028, 0, 0.71555],
1897 "933": [0, 0.68333, 0.11111, 0, 0.76666],
1898 "934": [0, 0.68333, 0.05986, 0, 0.71555],
1899 "936": [0, 0.68333, 0.11111, 0, 0.76666],
1900 "937": [0, 0.68333, 0.10257, 0, 0.71555],
1901 "8211": [0, 0.43056, 0.09208, 0, 0.51111],
1902 "8212": [0, 0.43056, 0.09208, 0, 1.02222],
1903 "8216": [0, 0.69444, 0.12417, 0, 0.30667],
1904 "8217": [0, 0.69444, 0.12417, 0, 0.30667],
1905 "8220": [0, 0.69444, 0.1685, 0, 0.51444],
1906 "8221": [0, 0.69444, 0.06961, 0, 0.51444],
1907 "8463": [0, 0.68889, 0, 0, 0.54028]
1908 },
1909 "Main-Regular": {
1910 "32": [0, 0, 0, 0, 0.25],
1911 "33": [0, 0.69444, 0, 0, 0.27778],
1912 "34": [0, 0.69444, 0, 0, 0.5],
1913 "35": [0.19444, 0.69444, 0, 0, 0.83334],
1914 "36": [0.05556, 0.75, 0, 0, 0.5],
1915 "37": [0.05556, 0.75, 0, 0, 0.83334],
1916 "38": [0, 0.69444, 0, 0, 0.77778],
1917 "39": [0, 0.69444, 0, 0, 0.27778],
1918 "40": [0.25, 0.75, 0, 0, 0.38889],
1919 "41": [0.25, 0.75, 0, 0, 0.38889],
1920 "42": [0, 0.75, 0, 0, 0.5],
1921 "43": [0.08333, 0.58333, 0, 0, 0.77778],
1922 "44": [0.19444, 0.10556, 0, 0, 0.27778],
1923 "45": [0, 0.43056, 0, 0, 0.33333],
1924 "46": [0, 0.10556, 0, 0, 0.27778],
1925 "47": [0.25, 0.75, 0, 0, 0.5],
1926 "48": [0, 0.64444, 0, 0, 0.5],
1927 "49": [0, 0.64444, 0, 0, 0.5],
1928 "50": [0, 0.64444, 0, 0, 0.5],
1929 "51": [0, 0.64444, 0, 0, 0.5],
1930 "52": [0, 0.64444, 0, 0, 0.5],
1931 "53": [0, 0.64444, 0, 0, 0.5],
1932 "54": [0, 0.64444, 0, 0, 0.5],
1933 "55": [0, 0.64444, 0, 0, 0.5],
1934 "56": [0, 0.64444, 0, 0, 0.5],
1935 "57": [0, 0.64444, 0, 0, 0.5],
1936 "58": [0, 0.43056, 0, 0, 0.27778],
1937 "59": [0.19444, 0.43056, 0, 0, 0.27778],
1938 "60": [0.0391, 0.5391, 0, 0, 0.77778],
1939 "61": [-0.13313, 0.36687, 0, 0, 0.77778],
1940 "62": [0.0391, 0.5391, 0, 0, 0.77778],
1941 "63": [0, 0.69444, 0, 0, 0.47222],
1942 "64": [0, 0.69444, 0, 0, 0.77778],
1943 "65": [0, 0.68333, 0, 0, 0.75],
1944 "66": [0, 0.68333, 0, 0, 0.70834],
1945 "67": [0, 0.68333, 0, 0, 0.72222],
1946 "68": [0, 0.68333, 0, 0, 0.76389],
1947 "69": [0, 0.68333, 0, 0, 0.68056],
1948 "70": [0, 0.68333, 0, 0, 0.65278],
1949 "71": [0, 0.68333, 0, 0, 0.78472],
1950 "72": [0, 0.68333, 0, 0, 0.75],
1951 "73": [0, 0.68333, 0, 0, 0.36111],
1952 "74": [0, 0.68333, 0, 0, 0.51389],
1953 "75": [0, 0.68333, 0, 0, 0.77778],
1954 "76": [0, 0.68333, 0, 0, 0.625],
1955 "77": [0, 0.68333, 0, 0, 0.91667],
1956 "78": [0, 0.68333, 0, 0, 0.75],
1957 "79": [0, 0.68333, 0, 0, 0.77778],
1958 "80": [0, 0.68333, 0, 0, 0.68056],
1959 "81": [0.19444, 0.68333, 0, 0, 0.77778],
1960 "82": [0, 0.68333, 0, 0, 0.73611],
1961 "83": [0, 0.68333, 0, 0, 0.55556],
1962 "84": [0, 0.68333, 0, 0, 0.72222],
1963 "85": [0, 0.68333, 0, 0, 0.75],
1964 "86": [0, 0.68333, 0.01389, 0, 0.75],
1965 "87": [0, 0.68333, 0.01389, 0, 1.02778],
1966 "88": [0, 0.68333, 0, 0, 0.75],
1967 "89": [0, 0.68333, 0.025, 0, 0.75],
1968 "90": [0, 0.68333, 0, 0, 0.61111],
1969 "91": [0.25, 0.75, 0, 0, 0.27778],
1970 "92": [0.25, 0.75, 0, 0, 0.5],
1971 "93": [0.25, 0.75, 0, 0, 0.27778],
1972 "94": [0, 0.69444, 0, 0, 0.5],
1973 "95": [0.31, 0.12056, 0.02778, 0, 0.5],
1974 "97": [0, 0.43056, 0, 0, 0.5],
1975 "98": [0, 0.69444, 0, 0, 0.55556],
1976 "99": [0, 0.43056, 0, 0, 0.44445],
1977 "100": [0, 0.69444, 0, 0, 0.55556],
1978 "101": [0, 0.43056, 0, 0, 0.44445],
1979 "102": [0, 0.69444, 0.07778, 0, 0.30556],
1980 "103": [0.19444, 0.43056, 0.01389, 0, 0.5],
1981 "104": [0, 0.69444, 0, 0, 0.55556],
1982 "105": [0, 0.66786, 0, 0, 0.27778],
1983 "106": [0.19444, 0.66786, 0, 0, 0.30556],
1984 "107": [0, 0.69444, 0, 0, 0.52778],
1985 "108": [0, 0.69444, 0, 0, 0.27778],
1986 "109": [0, 0.43056, 0, 0, 0.83334],
1987 "110": [0, 0.43056, 0, 0, 0.55556],
1988 "111": [0, 0.43056, 0, 0, 0.5],
1989 "112": [0.19444, 0.43056, 0, 0, 0.55556],
1990 "113": [0.19444, 0.43056, 0, 0, 0.52778],
1991 "114": [0, 0.43056, 0, 0, 0.39167],
1992 "115": [0, 0.43056, 0, 0, 0.39445],
1993 "116": [0, 0.61508, 0, 0, 0.38889],
1994 "117": [0, 0.43056, 0, 0, 0.55556],
1995 "118": [0, 0.43056, 0.01389, 0, 0.52778],
1996 "119": [0, 0.43056, 0.01389, 0, 0.72222],
1997 "120": [0, 0.43056, 0, 0, 0.52778],
1998 "121": [0.19444, 0.43056, 0.01389, 0, 0.52778],
1999 "122": [0, 0.43056, 0, 0, 0.44445],
2000 "123": [0.25, 0.75, 0, 0, 0.5],
2001 "124": [0.25, 0.75, 0, 0, 0.27778],
2002 "125": [0.25, 0.75, 0, 0, 0.5],
2003 "126": [0.35, 0.31786, 0, 0, 0.5],
2004 "160": [0, 0, 0, 0, 0.25],
2005 "163": [0, 0.69444, 0, 0, 0.76909],
2006 "167": [0.19444, 0.69444, 0, 0, 0.44445],
2007 "168": [0, 0.66786, 0, 0, 0.5],
2008 "172": [0, 0.43056, 0, 0, 0.66667],
2009 "176": [0, 0.69444, 0, 0, 0.75],
2010 "177": [0.08333, 0.58333, 0, 0, 0.77778],
2011 "182": [0.19444, 0.69444, 0, 0, 0.61111],
2012 "184": [0.17014, 0, 0, 0, 0.44445],
2013 "198": [0, 0.68333, 0, 0, 0.90278],
2014 "215": [0.08333, 0.58333, 0, 0, 0.77778],
2015 "216": [0.04861, 0.73194, 0, 0, 0.77778],
2016 "223": [0, 0.69444, 0, 0, 0.5],
2017 "230": [0, 0.43056, 0, 0, 0.72222],
2018 "247": [0.08333, 0.58333, 0, 0, 0.77778],
2019 "248": [0.09722, 0.52778, 0, 0, 0.5],
2020 "305": [0, 0.43056, 0, 0, 0.27778],
2021 "338": [0, 0.68333, 0, 0, 1.01389],
2022 "339": [0, 0.43056, 0, 0, 0.77778],
2023 "567": [0.19444, 0.43056, 0, 0, 0.30556],
2024 "710": [0, 0.69444, 0, 0, 0.5],
2025 "711": [0, 0.62847, 0, 0, 0.5],
2026 "713": [0, 0.56778, 0, 0, 0.5],
2027 "714": [0, 0.69444, 0, 0, 0.5],
2028 "715": [0, 0.69444, 0, 0, 0.5],
2029 "728": [0, 0.69444, 0, 0, 0.5],
2030 "729": [0, 0.66786, 0, 0, 0.27778],
2031 "730": [0, 0.69444, 0, 0, 0.75],
2032 "732": [0, 0.66786, 0, 0, 0.5],
2033 "733": [0, 0.69444, 0, 0, 0.5],
2034 "915": [0, 0.68333, 0, 0, 0.625],
2035 "916": [0, 0.68333, 0, 0, 0.83334],
2036 "920": [0, 0.68333, 0, 0, 0.77778],
2037 "923": [0, 0.68333, 0, 0, 0.69445],
2038 "926": [0, 0.68333, 0, 0, 0.66667],
2039 "928": [0, 0.68333, 0, 0, 0.75],
2040 "931": [0, 0.68333, 0, 0, 0.72222],
2041 "933": [0, 0.68333, 0, 0, 0.77778],
2042 "934": [0, 0.68333, 0, 0, 0.72222],
2043 "936": [0, 0.68333, 0, 0, 0.77778],
2044 "937": [0, 0.68333, 0, 0, 0.72222],
2045 "8211": [0, 0.43056, 0.02778, 0, 0.5],
2046 "8212": [0, 0.43056, 0.02778, 0, 1.0],
2047 "8216": [0, 0.69444, 0, 0, 0.27778],
2048 "8217": [0, 0.69444, 0, 0, 0.27778],
2049 "8220": [0, 0.69444, 0, 0, 0.5],
2050 "8221": [0, 0.69444, 0, 0, 0.5],
2051 "8224": [0.19444, 0.69444, 0, 0, 0.44445],
2052 "8225": [0.19444, 0.69444, 0, 0, 0.44445],
2053 "8230": [0, 0.123, 0, 0, 1.172],
2054 "8242": [0, 0.55556, 0, 0, 0.275],
2055 "8407": [0, 0.71444, 0.15382, 0, 0.5],
2056 "8463": [0, 0.68889, 0, 0, 0.54028],
2057 "8465": [0, 0.69444, 0, 0, 0.72222],
2058 "8467": [0, 0.69444, 0, 0.11111, 0.41667],
2059 "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646],
2060 "8476": [0, 0.69444, 0, 0, 0.72222],
2061 "8501": [0, 0.69444, 0, 0, 0.61111],
2062 "8592": [-0.13313, 0.36687, 0, 0, 1.0],
2063 "8593": [0.19444, 0.69444, 0, 0, 0.5],
2064 "8594": [-0.13313, 0.36687, 0, 0, 1.0],
2065 "8595": [0.19444, 0.69444, 0, 0, 0.5],
2066 "8596": [-0.13313, 0.36687, 0, 0, 1.0],
2067 "8597": [0.25, 0.75, 0, 0, 0.5],
2068 "8598": [0.19444, 0.69444, 0, 0, 1.0],
2069 "8599": [0.19444, 0.69444, 0, 0, 1.0],
2070 "8600": [0.19444, 0.69444, 0, 0, 1.0],
2071 "8601": [0.19444, 0.69444, 0, 0, 1.0],
2072 "8614": [0.011, 0.511, 0, 0, 1.0],
2073 "8617": [0.011, 0.511, 0, 0, 1.126],
2074 "8618": [0.011, 0.511, 0, 0, 1.126],
2075 "8636": [-0.13313, 0.36687, 0, 0, 1.0],
2076 "8637": [-0.13313, 0.36687, 0, 0, 1.0],
2077 "8640": [-0.13313, 0.36687, 0, 0, 1.0],
2078 "8641": [-0.13313, 0.36687, 0, 0, 1.0],
2079 "8652": [0.011, 0.671, 0, 0, 1.0],
2080 "8656": [-0.13313, 0.36687, 0, 0, 1.0],
2081 "8657": [0.19444, 0.69444, 0, 0, 0.61111],
2082 "8658": [-0.13313, 0.36687, 0, 0, 1.0],
2083 "8659": [0.19444, 0.69444, 0, 0, 0.61111],
2084 "8660": [-0.13313, 0.36687, 0, 0, 1.0],
2085 "8661": [0.25, 0.75, 0, 0, 0.61111],
2086 "8704": [0, 0.69444, 0, 0, 0.55556],
2087 "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309],
2088 "8707": [0, 0.69444, 0, 0, 0.55556],
2089 "8709": [0.05556, 0.75, 0, 0, 0.5],
2090 "8711": [0, 0.68333, 0, 0, 0.83334],
2091 "8712": [0.0391, 0.5391, 0, 0, 0.66667],
2092 "8715": [0.0391, 0.5391, 0, 0, 0.66667],
2093 "8722": [0.08333, 0.58333, 0, 0, 0.77778],
2094 "8723": [0.08333, 0.58333, 0, 0, 0.77778],
2095 "8725": [0.25, 0.75, 0, 0, 0.5],
2096 "8726": [0.25, 0.75, 0, 0, 0.5],
2097 "8727": [-0.03472, 0.46528, 0, 0, 0.5],
2098 "8728": [-0.05555, 0.44445, 0, 0, 0.5],
2099 "8729": [-0.05555, 0.44445, 0, 0, 0.5],
2100 "8730": [0.2, 0.8, 0, 0, 0.83334],
2101 "8733": [0, 0.43056, 0, 0, 0.77778],
2102 "8734": [0, 0.43056, 0, 0, 1.0],
2103 "8736": [0, 0.69224, 0, 0, 0.72222],
2104 "8739": [0.25, 0.75, 0, 0, 0.27778],
2105 "8741": [0.25, 0.75, 0, 0, 0.5],
2106 "8743": [0, 0.55556, 0, 0, 0.66667],
2107 "8744": [0, 0.55556, 0, 0, 0.66667],
2108 "8745": [0, 0.55556, 0, 0, 0.66667],
2109 "8746": [0, 0.55556, 0, 0, 0.66667],
2110 "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667],
2111 "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
2112 "8768": [0.19444, 0.69444, 0, 0, 0.27778],
2113 "8771": [-0.03625, 0.46375, 0, 0, 0.77778],
2114 "8773": [-0.022, 0.589, 0, 0, 0.778],
2115 "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
2116 "8781": [-0.03625, 0.46375, 0, 0, 0.77778],
2117 "8784": [-0.133, 0.673, 0, 0, 0.778],
2118 "8801": [-0.03625, 0.46375, 0, 0, 0.77778],
2119 "8804": [0.13597, 0.63597, 0, 0, 0.77778],
2120 "8805": [0.13597, 0.63597, 0, 0, 0.77778],
2121 "8810": [0.0391, 0.5391, 0, 0, 1.0],
2122 "8811": [0.0391, 0.5391, 0, 0, 1.0],
2123 "8826": [0.0391, 0.5391, 0, 0, 0.77778],
2124 "8827": [0.0391, 0.5391, 0, 0, 0.77778],
2125 "8834": [0.0391, 0.5391, 0, 0, 0.77778],
2126 "8835": [0.0391, 0.5391, 0, 0, 0.77778],
2127 "8838": [0.13597, 0.63597, 0, 0, 0.77778],
2128 "8839": [0.13597, 0.63597, 0, 0, 0.77778],
2129 "8846": [0, 0.55556, 0, 0, 0.66667],
2130 "8849": [0.13597, 0.63597, 0, 0, 0.77778],
2131 "8850": [0.13597, 0.63597, 0, 0, 0.77778],
2132 "8851": [0, 0.55556, 0, 0, 0.66667],
2133 "8852": [0, 0.55556, 0, 0, 0.66667],
2134 "8853": [0.08333, 0.58333, 0, 0, 0.77778],
2135 "8854": [0.08333, 0.58333, 0, 0, 0.77778],
2136 "8855": [0.08333, 0.58333, 0, 0, 0.77778],
2137 "8856": [0.08333, 0.58333, 0, 0, 0.77778],
2138 "8857": [0.08333, 0.58333, 0, 0, 0.77778],
2139 "8866": [0, 0.69444, 0, 0, 0.61111],
2140 "8867": [0, 0.69444, 0, 0, 0.61111],
2141 "8868": [0, 0.69444, 0, 0, 0.77778],
2142 "8869": [0, 0.69444, 0, 0, 0.77778],
2143 "8872": [0.249, 0.75, 0, 0, 0.867],
2144 "8900": [-0.05555, 0.44445, 0, 0, 0.5],
2145 "8901": [-0.05555, 0.44445, 0, 0, 0.27778],
2146 "8902": [-0.03472, 0.46528, 0, 0, 0.5],
2147 "8904": [0.005, 0.505, 0, 0, 0.9],
2148 "8942": [0.03, 0.903, 0, 0, 0.278],
2149 "8943": [-0.19, 0.313, 0, 0, 1.172],
2150 "8945": [-0.1, 0.823, 0, 0, 1.282],
2151 "8968": [0.25, 0.75, 0, 0, 0.44445],
2152 "8969": [0.25, 0.75, 0, 0, 0.44445],
2153 "8970": [0.25, 0.75, 0, 0, 0.44445],
2154 "8971": [0.25, 0.75, 0, 0, 0.44445],
2155 "8994": [-0.14236, 0.35764, 0, 0, 1.0],
2156 "8995": [-0.14236, 0.35764, 0, 0, 1.0],
2157 "9136": [0.244, 0.744, 0, 0, 0.412],
2158 "9137": [0.244, 0.745, 0, 0, 0.412],
2159 "9651": [0.19444, 0.69444, 0, 0, 0.88889],
2160 "9657": [-0.03472, 0.46528, 0, 0, 0.5],
2161 "9661": [0.19444, 0.69444, 0, 0, 0.88889],
2162 "9667": [-0.03472, 0.46528, 0, 0, 0.5],
2163 "9711": [0.19444, 0.69444, 0, 0, 1.0],
2164 "9824": [0.12963, 0.69444, 0, 0, 0.77778],
2165 "9825": [0.12963, 0.69444, 0, 0, 0.77778],
2166 "9826": [0.12963, 0.69444, 0, 0, 0.77778],
2167 "9827": [0.12963, 0.69444, 0, 0, 0.77778],
2168 "9837": [0, 0.75, 0, 0, 0.38889],
2169 "9838": [0.19444, 0.69444, 0, 0, 0.38889],
2170 "9839": [0.19444, 0.69444, 0, 0, 0.38889],
2171 "10216": [0.25, 0.75, 0, 0, 0.38889],
2172 "10217": [0.25, 0.75, 0, 0, 0.38889],
2173 "10222": [0.244, 0.744, 0, 0, 0.412],
2174 "10223": [0.244, 0.745, 0, 0, 0.412],
2175 "10229": [0.011, 0.511, 0, 0, 1.609],
2176 "10230": [0.011, 0.511, 0, 0, 1.638],
2177 "10231": [0.011, 0.511, 0, 0, 1.859],
2178 "10232": [0.024, 0.525, 0, 0, 1.609],
2179 "10233": [0.024, 0.525, 0, 0, 1.638],
2180 "10234": [0.024, 0.525, 0, 0, 1.858],
2181 "10236": [0.011, 0.511, 0, 0, 1.638],
2182 "10815": [0, 0.68333, 0, 0, 0.75],
2183 "10927": [0.13597, 0.63597, 0, 0, 0.77778],
2184 "10928": [0.13597, 0.63597, 0, 0, 0.77778],
2185 "57376": [0.19444, 0.69444, 0, 0, 0]
2186 },
2187 "Math-BoldItalic": {
2188 "32": [0, 0, 0, 0, 0.25],
2189 "48": [0, 0.44444, 0, 0, 0.575],
2190 "49": [0, 0.44444, 0, 0, 0.575],
2191 "50": [0, 0.44444, 0, 0, 0.575],
2192 "51": [0.19444, 0.44444, 0, 0, 0.575],
2193 "52": [0.19444, 0.44444, 0, 0, 0.575],
2194 "53": [0.19444, 0.44444, 0, 0, 0.575],
2195 "54": [0, 0.64444, 0, 0, 0.575],
2196 "55": [0.19444, 0.44444, 0, 0, 0.575],
2197 "56": [0, 0.64444, 0, 0, 0.575],
2198 "57": [0.19444, 0.44444, 0, 0, 0.575],
2199 "65": [0, 0.68611, 0, 0, 0.86944],
2200 "66": [0, 0.68611, 0.04835, 0, 0.8664],
2201 "67": [0, 0.68611, 0.06979, 0, 0.81694],
2202 "68": [0, 0.68611, 0.03194, 0, 0.93812],
2203 "69": [0, 0.68611, 0.05451, 0, 0.81007],
2204 "70": [0, 0.68611, 0.15972, 0, 0.68889],
2205 "71": [0, 0.68611, 0, 0, 0.88673],
2206 "72": [0, 0.68611, 0.08229, 0, 0.98229],
2207 "73": [0, 0.68611, 0.07778, 0, 0.51111],
2208 "74": [0, 0.68611, 0.10069, 0, 0.63125],
2209 "75": [0, 0.68611, 0.06979, 0, 0.97118],
2210 "76": [0, 0.68611, 0, 0, 0.75555],
2211 "77": [0, 0.68611, 0.11424, 0, 1.14201],
2212 "78": [0, 0.68611, 0.11424, 0, 0.95034],
2213 "79": [0, 0.68611, 0.03194, 0, 0.83666],
2214 "80": [0, 0.68611, 0.15972, 0, 0.72309],
2215 "81": [0.19444, 0.68611, 0, 0, 0.86861],
2216 "82": [0, 0.68611, 0.00421, 0, 0.87235],
2217 "83": [0, 0.68611, 0.05382, 0, 0.69271],
2218 "84": [0, 0.68611, 0.15972, 0, 0.63663],
2219 "85": [0, 0.68611, 0.11424, 0, 0.80027],
2220 "86": [0, 0.68611, 0.25555, 0, 0.67778],
2221 "87": [0, 0.68611, 0.15972, 0, 1.09305],
2222 "88": [0, 0.68611, 0.07778, 0, 0.94722],
2223 "89": [0, 0.68611, 0.25555, 0, 0.67458],
2224 "90": [0, 0.68611, 0.06979, 0, 0.77257],
2225 "97": [0, 0.44444, 0, 0, 0.63287],
2226 "98": [0, 0.69444, 0, 0, 0.52083],
2227 "99": [0, 0.44444, 0, 0, 0.51342],
2228 "100": [0, 0.69444, 0, 0, 0.60972],
2229 "101": [0, 0.44444, 0, 0, 0.55361],
2230 "102": [0.19444, 0.69444, 0.11042, 0, 0.56806],
2231 "103": [0.19444, 0.44444, 0.03704, 0, 0.5449],
2232 "104": [0, 0.69444, 0, 0, 0.66759],
2233 "105": [0, 0.69326, 0, 0, 0.4048],
2234 "106": [0.19444, 0.69326, 0.0622, 0, 0.47083],
2235 "107": [0, 0.69444, 0.01852, 0, 0.6037],
2236 "108": [0, 0.69444, 0.0088, 0, 0.34815],
2237 "109": [0, 0.44444, 0, 0, 1.0324],
2238 "110": [0, 0.44444, 0, 0, 0.71296],
2239 "111": [0, 0.44444, 0, 0, 0.58472],
2240 "112": [0.19444, 0.44444, 0, 0, 0.60092],
2241 "113": [0.19444, 0.44444, 0.03704, 0, 0.54213],
2242 "114": [0, 0.44444, 0.03194, 0, 0.5287],
2243 "115": [0, 0.44444, 0, 0, 0.53125],
2244 "116": [0, 0.63492, 0, 0, 0.41528],
2245 "117": [0, 0.44444, 0, 0, 0.68102],
2246 "118": [0, 0.44444, 0.03704, 0, 0.56666],
2247 "119": [0, 0.44444, 0.02778, 0, 0.83148],
2248 "120": [0, 0.44444, 0, 0, 0.65903],
2249 "121": [0.19444, 0.44444, 0.03704, 0, 0.59028],
2250 "122": [0, 0.44444, 0.04213, 0, 0.55509],
2251 "160": [0, 0, 0, 0, 0.25],
2252 "915": [0, 0.68611, 0.15972, 0, 0.65694],
2253 "916": [0, 0.68611, 0, 0, 0.95833],
2254 "920": [0, 0.68611, 0.03194, 0, 0.86722],
2255 "923": [0, 0.68611, 0, 0, 0.80555],
2256 "926": [0, 0.68611, 0.07458, 0, 0.84125],
2257 "928": [0, 0.68611, 0.08229, 0, 0.98229],
2258 "931": [0, 0.68611, 0.05451, 0, 0.88507],
2259 "933": [0, 0.68611, 0.15972, 0, 0.67083],
2260 "934": [0, 0.68611, 0, 0, 0.76666],
2261 "936": [0, 0.68611, 0.11653, 0, 0.71402],
2262 "937": [0, 0.68611, 0.04835, 0, 0.8789],
2263 "945": [0, 0.44444, 0, 0, 0.76064],
2264 "946": [0.19444, 0.69444, 0.03403, 0, 0.65972],
2265 "947": [0.19444, 0.44444, 0.06389, 0, 0.59003],
2266 "948": [0, 0.69444, 0.03819, 0, 0.52222],
2267 "949": [0, 0.44444, 0, 0, 0.52882],
2268 "950": [0.19444, 0.69444, 0.06215, 0, 0.50833],
2269 "951": [0.19444, 0.44444, 0.03704, 0, 0.6],
2270 "952": [0, 0.69444, 0.03194, 0, 0.5618],
2271 "953": [0, 0.44444, 0, 0, 0.41204],
2272 "954": [0, 0.44444, 0, 0, 0.66759],
2273 "955": [0, 0.69444, 0, 0, 0.67083],
2274 "956": [0.19444, 0.44444, 0, 0, 0.70787],
2275 "957": [0, 0.44444, 0.06898, 0, 0.57685],
2276 "958": [0.19444, 0.69444, 0.03021, 0, 0.50833],
2277 "959": [0, 0.44444, 0, 0, 0.58472],
2278 "960": [0, 0.44444, 0.03704, 0, 0.68241],
2279 "961": [0.19444, 0.44444, 0, 0, 0.6118],
2280 "962": [0.09722, 0.44444, 0.07917, 0, 0.42361],
2281 "963": [0, 0.44444, 0.03704, 0, 0.68588],
2282 "964": [0, 0.44444, 0.13472, 0, 0.52083],
2283 "965": [0, 0.44444, 0.03704, 0, 0.63055],
2284 "966": [0.19444, 0.44444, 0, 0, 0.74722],
2285 "967": [0.19444, 0.44444, 0, 0, 0.71805],
2286 "968": [0.19444, 0.69444, 0.03704, 0, 0.75833],
2287 "969": [0, 0.44444, 0.03704, 0, 0.71782],
2288 "977": [0, 0.69444, 0, 0, 0.69155],
2289 "981": [0.19444, 0.69444, 0, 0, 0.7125],
2290 "982": [0, 0.44444, 0.03194, 0, 0.975],
2291 "1009": [0.19444, 0.44444, 0, 0, 0.6118],
2292 "1013": [0, 0.44444, 0, 0, 0.48333],
2293 "57649": [0, 0.44444, 0, 0, 0.39352],
2294 "57911": [0.19444, 0.44444, 0, 0, 0.43889]
2295 },
2296 "Math-Italic": {
2297 "32": [0, 0, 0, 0, 0.25],
2298 "48": [0, 0.43056, 0, 0, 0.5],
2299 "49": [0, 0.43056, 0, 0, 0.5],
2300 "50": [0, 0.43056, 0, 0, 0.5],
2301 "51": [0.19444, 0.43056, 0, 0, 0.5],
2302 "52": [0.19444, 0.43056, 0, 0, 0.5],
2303 "53": [0.19444, 0.43056, 0, 0, 0.5],
2304 "54": [0, 0.64444, 0, 0, 0.5],
2305 "55": [0.19444, 0.43056, 0, 0, 0.5],
2306 "56": [0, 0.64444, 0, 0, 0.5],
2307 "57": [0.19444, 0.43056, 0, 0, 0.5],
2308 "65": [0, 0.68333, 0, 0.13889, 0.75],
2309 "66": [0, 0.68333, 0.05017, 0.08334, 0.75851],
2310 "67": [0, 0.68333, 0.07153, 0.08334, 0.71472],
2311 "68": [0, 0.68333, 0.02778, 0.05556, 0.82792],
2312 "69": [0, 0.68333, 0.05764, 0.08334, 0.7382],
2313 "70": [0, 0.68333, 0.13889, 0.08334, 0.64306],
2314 "71": [0, 0.68333, 0, 0.08334, 0.78625],
2315 "72": [0, 0.68333, 0.08125, 0.05556, 0.83125],
2316 "73": [0, 0.68333, 0.07847, 0.11111, 0.43958],
2317 "74": [0, 0.68333, 0.09618, 0.16667, 0.55451],
2318 "75": [0, 0.68333, 0.07153, 0.05556, 0.84931],
2319 "76": [0, 0.68333, 0, 0.02778, 0.68056],
2320 "77": [0, 0.68333, 0.10903, 0.08334, 0.97014],
2321 "78": [0, 0.68333, 0.10903, 0.08334, 0.80347],
2322 "79": [0, 0.68333, 0.02778, 0.08334, 0.76278],
2323 "80": [0, 0.68333, 0.13889, 0.08334, 0.64201],
2324 "81": [0.19444, 0.68333, 0, 0.08334, 0.79056],
2325 "82": [0, 0.68333, 0.00773, 0.08334, 0.75929],
2326 "83": [0, 0.68333, 0.05764, 0.08334, 0.6132],
2327 "84": [0, 0.68333, 0.13889, 0.08334, 0.58438],
2328 "85": [0, 0.68333, 0.10903, 0.02778, 0.68278],
2329 "86": [0, 0.68333, 0.22222, 0, 0.58333],
2330 "87": [0, 0.68333, 0.13889, 0, 0.94445],
2331 "88": [0, 0.68333, 0.07847, 0.08334, 0.82847],
2332 "89": [0, 0.68333, 0.22222, 0, 0.58056],
2333 "90": [0, 0.68333, 0.07153, 0.08334, 0.68264],
2334 "97": [0, 0.43056, 0, 0, 0.52859],
2335 "98": [0, 0.69444, 0, 0, 0.42917],
2336 "99": [0, 0.43056, 0, 0.05556, 0.43276],
2337 "100": [0, 0.69444, 0, 0.16667, 0.52049],
2338 "101": [0, 0.43056, 0, 0.05556, 0.46563],
2339 "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959],
2340 "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697],
2341 "104": [0, 0.69444, 0, 0, 0.57616],
2342 "105": [0, 0.65952, 0, 0, 0.34451],
2343 "106": [0.19444, 0.65952, 0.05724, 0, 0.41181],
2344 "107": [0, 0.69444, 0.03148, 0, 0.5206],
2345 "108": [0, 0.69444, 0.01968, 0.08334, 0.29838],
2346 "109": [0, 0.43056, 0, 0, 0.87801],
2347 "110": [0, 0.43056, 0, 0, 0.60023],
2348 "111": [0, 0.43056, 0, 0.05556, 0.48472],
2349 "112": [0.19444, 0.43056, 0, 0.08334, 0.50313],
2350 "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641],
2351 "114": [0, 0.43056, 0.02778, 0.05556, 0.45116],
2352 "115": [0, 0.43056, 0, 0.05556, 0.46875],
2353 "116": [0, 0.61508, 0, 0.08334, 0.36111],
2354 "117": [0, 0.43056, 0, 0.02778, 0.57246],
2355 "118": [0, 0.43056, 0.03588, 0.02778, 0.48472],
2356 "119": [0, 0.43056, 0.02691, 0.08334, 0.71592],
2357 "120": [0, 0.43056, 0, 0.02778, 0.57153],
2358 "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028],
2359 "122": [0, 0.43056, 0.04398, 0.05556, 0.46505],
2360 "160": [0, 0, 0, 0, 0.25],
2361 "915": [0, 0.68333, 0.13889, 0.08334, 0.61528],
2362 "916": [0, 0.68333, 0, 0.16667, 0.83334],
2363 "920": [0, 0.68333, 0.02778, 0.08334, 0.76278],
2364 "923": [0, 0.68333, 0, 0.16667, 0.69445],
2365 "926": [0, 0.68333, 0.07569, 0.08334, 0.74236],
2366 "928": [0, 0.68333, 0.08125, 0.05556, 0.83125],
2367 "931": [0, 0.68333, 0.05764, 0.08334, 0.77986],
2368 "933": [0, 0.68333, 0.13889, 0.05556, 0.58333],
2369 "934": [0, 0.68333, 0, 0.08334, 0.66667],
2370 "936": [0, 0.68333, 0.11, 0.05556, 0.61222],
2371 "937": [0, 0.68333, 0.05017, 0.08334, 0.7724],
2372 "945": [0, 0.43056, 0.0037, 0.02778, 0.6397],
2373 "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563],
2374 "947": [0.19444, 0.43056, 0.05556, 0, 0.51773],
2375 "948": [0, 0.69444, 0.03785, 0.05556, 0.44444],
2376 "949": [0, 0.43056, 0, 0.08334, 0.46632],
2377 "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375],
2378 "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653],
2379 "952": [0, 0.69444, 0.02778, 0.08334, 0.46944],
2380 "953": [0, 0.43056, 0, 0.05556, 0.35394],
2381 "954": [0, 0.43056, 0, 0, 0.57616],
2382 "955": [0, 0.69444, 0, 0, 0.58334],
2383 "956": [0.19444, 0.43056, 0, 0.02778, 0.60255],
2384 "957": [0, 0.43056, 0.06366, 0.02778, 0.49398],
2385 "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375],
2386 "959": [0, 0.43056, 0, 0.05556, 0.48472],
2387 "960": [0, 0.43056, 0.03588, 0, 0.57003],
2388 "961": [0.19444, 0.43056, 0, 0.08334, 0.51702],
2389 "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285],
2390 "963": [0, 0.43056, 0.03588, 0, 0.57141],
2391 "964": [0, 0.43056, 0.1132, 0.02778, 0.43715],
2392 "965": [0, 0.43056, 0.03588, 0.02778, 0.54028],
2393 "966": [0.19444, 0.43056, 0, 0.08334, 0.65417],
2394 "967": [0.19444, 0.43056, 0, 0.05556, 0.62569],
2395 "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139],
2396 "969": [0, 0.43056, 0.03588, 0, 0.62245],
2397 "977": [0, 0.69444, 0, 0.08334, 0.59144],
2398 "981": [0.19444, 0.69444, 0, 0.08334, 0.59583],
2399 "982": [0, 0.43056, 0.02778, 0, 0.82813],
2400 "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702],
2401 "1013": [0, 0.43056, 0, 0.05556, 0.4059],
2402 "57649": [0, 0.43056, 0, 0.02778, 0.32246],
2403 "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403]
2404 },
2405 "SansSerif-Bold": {
2406 "32": [0, 0, 0, 0, 0.25],
2407 "33": [0, 0.69444, 0, 0, 0.36667],
2408 "34": [0, 0.69444, 0, 0, 0.55834],
2409 "35": [0.19444, 0.69444, 0, 0, 0.91667],
2410 "36": [0.05556, 0.75, 0, 0, 0.55],
2411 "37": [0.05556, 0.75, 0, 0, 1.02912],
2412 "38": [0, 0.69444, 0, 0, 0.83056],
2413 "39": [0, 0.69444, 0, 0, 0.30556],
2414 "40": [0.25, 0.75, 0, 0, 0.42778],
2415 "41": [0.25, 0.75, 0, 0, 0.42778],
2416 "42": [0, 0.75, 0, 0, 0.55],
2417 "43": [0.11667, 0.61667, 0, 0, 0.85556],
2418 "44": [0.10556, 0.13056, 0, 0, 0.30556],
2419 "45": [0, 0.45833, 0, 0, 0.36667],
2420 "46": [0, 0.13056, 0, 0, 0.30556],
2421 "47": [0.25, 0.75, 0, 0, 0.55],
2422 "48": [0, 0.69444, 0, 0, 0.55],
2423 "49": [0, 0.69444, 0, 0, 0.55],
2424 "50": [0, 0.69444, 0, 0, 0.55],
2425 "51": [0, 0.69444, 0, 0, 0.55],
2426 "52": [0, 0.69444, 0, 0, 0.55],
2427 "53": [0, 0.69444, 0, 0, 0.55],
2428 "54": [0, 0.69444, 0, 0, 0.55],
2429 "55": [0, 0.69444, 0, 0, 0.55],
2430 "56": [0, 0.69444, 0, 0, 0.55],
2431 "57": [0, 0.69444, 0, 0, 0.55],
2432 "58": [0, 0.45833, 0, 0, 0.30556],
2433 "59": [0.10556, 0.45833, 0, 0, 0.30556],
2434 "61": [-0.09375, 0.40625, 0, 0, 0.85556],
2435 "63": [0, 0.69444, 0, 0, 0.51945],
2436 "64": [0, 0.69444, 0, 0, 0.73334],
2437 "65": [0, 0.69444, 0, 0, 0.73334],
2438 "66": [0, 0.69444, 0, 0, 0.73334],
2439 "67": [0, 0.69444, 0, 0, 0.70278],
2440 "68": [0, 0.69444, 0, 0, 0.79445],
2441 "69": [0, 0.69444, 0, 0, 0.64167],
2442 "70": [0, 0.69444, 0, 0, 0.61111],
2443 "71": [0, 0.69444, 0, 0, 0.73334],
2444 "72": [0, 0.69444, 0, 0, 0.79445],
2445 "73": [0, 0.69444, 0, 0, 0.33056],
2446 "74": [0, 0.69444, 0, 0, 0.51945],
2447 "75": [0, 0.69444, 0, 0, 0.76389],
2448 "76": [0, 0.69444, 0, 0, 0.58056],
2449 "77": [0, 0.69444, 0, 0, 0.97778],
2450 "78": [0, 0.69444, 0, 0, 0.79445],
2451 "79": [0, 0.69444, 0, 0, 0.79445],
2452 "80": [0, 0.69444, 0, 0, 0.70278],
2453 "81": [0.10556, 0.69444, 0, 0, 0.79445],
2454 "82": [0, 0.69444, 0, 0, 0.70278],
2455 "83": [0, 0.69444, 0, 0, 0.61111],
2456 "84": [0, 0.69444, 0, 0, 0.73334],
2457 "85": [0, 0.69444, 0, 0, 0.76389],
2458 "86": [0, 0.69444, 0.01528, 0, 0.73334],
2459 "87": [0, 0.69444, 0.01528, 0, 1.03889],
2460 "88": [0, 0.69444, 0, 0, 0.73334],
2461 "89": [0, 0.69444, 0.0275, 0, 0.73334],
2462 "90": [0, 0.69444, 0, 0, 0.67223],
2463 "91": [0.25, 0.75, 0, 0, 0.34306],
2464 "93": [0.25, 0.75, 0, 0, 0.34306],
2465 "94": [0, 0.69444, 0, 0, 0.55],
2466 "95": [0.35, 0.10833, 0.03056, 0, 0.55],
2467 "97": [0, 0.45833, 0, 0, 0.525],
2468 "98": [0, 0.69444, 0, 0, 0.56111],
2469 "99": [0, 0.45833, 0, 0, 0.48889],
2470 "100": [0, 0.69444, 0, 0, 0.56111],
2471 "101": [0, 0.45833, 0, 0, 0.51111],
2472 "102": [0, 0.69444, 0.07639, 0, 0.33611],
2473 "103": [0.19444, 0.45833, 0.01528, 0, 0.55],
2474 "104": [0, 0.69444, 0, 0, 0.56111],
2475 "105": [0, 0.69444, 0, 0, 0.25556],
2476 "106": [0.19444, 0.69444, 0, 0, 0.28611],
2477 "107": [0, 0.69444, 0, 0, 0.53056],
2478 "108": [0, 0.69444, 0, 0, 0.25556],
2479 "109": [0, 0.45833, 0, 0, 0.86667],
2480 "110": [0, 0.45833, 0, 0, 0.56111],
2481 "111": [0, 0.45833, 0, 0, 0.55],
2482 "112": [0.19444, 0.45833, 0, 0, 0.56111],
2483 "113": [0.19444, 0.45833, 0, 0, 0.56111],
2484 "114": [0, 0.45833, 0.01528, 0, 0.37222],
2485 "115": [0, 0.45833, 0, 0, 0.42167],
2486 "116": [0, 0.58929, 0, 0, 0.40417],
2487 "117": [0, 0.45833, 0, 0, 0.56111],
2488 "118": [0, 0.45833, 0.01528, 0, 0.5],
2489 "119": [0, 0.45833, 0.01528, 0, 0.74445],
2490 "120": [0, 0.45833, 0, 0, 0.5],
2491 "121": [0.19444, 0.45833, 0.01528, 0, 0.5],
2492 "122": [0, 0.45833, 0, 0, 0.47639],
2493 "126": [0.35, 0.34444, 0, 0, 0.55],
2494 "160": [0, 0, 0, 0, 0.25],
2495 "168": [0, 0.69444, 0, 0, 0.55],
2496 "176": [0, 0.69444, 0, 0, 0.73334],
2497 "180": [0, 0.69444, 0, 0, 0.55],
2498 "184": [0.17014, 0, 0, 0, 0.48889],
2499 "305": [0, 0.45833, 0, 0, 0.25556],
2500 "567": [0.19444, 0.45833, 0, 0, 0.28611],
2501 "710": [0, 0.69444, 0, 0, 0.55],
2502 "711": [0, 0.63542, 0, 0, 0.55],
2503 "713": [0, 0.63778, 0, 0, 0.55],
2504 "728": [0, 0.69444, 0, 0, 0.55],
2505 "729": [0, 0.69444, 0, 0, 0.30556],
2506 "730": [0, 0.69444, 0, 0, 0.73334],
2507 "732": [0, 0.69444, 0, 0, 0.55],
2508 "733": [0, 0.69444, 0, 0, 0.55],
2509 "915": [0, 0.69444, 0, 0, 0.58056],
2510 "916": [0, 0.69444, 0, 0, 0.91667],
2511 "920": [0, 0.69444, 0, 0, 0.85556],
2512 "923": [0, 0.69444, 0, 0, 0.67223],
2513 "926": [0, 0.69444, 0, 0, 0.73334],
2514 "928": [0, 0.69444, 0, 0, 0.79445],
2515 "931": [0, 0.69444, 0, 0, 0.79445],
2516 "933": [0, 0.69444, 0, 0, 0.85556],
2517 "934": [0, 0.69444, 0, 0, 0.79445],
2518 "936": [0, 0.69444, 0, 0, 0.85556],
2519 "937": [0, 0.69444, 0, 0, 0.79445],
2520 "8211": [0, 0.45833, 0.03056, 0, 0.55],
2521 "8212": [0, 0.45833, 0.03056, 0, 1.10001],
2522 "8216": [0, 0.69444, 0, 0, 0.30556],
2523 "8217": [0, 0.69444, 0, 0, 0.30556],
2524 "8220": [0, 0.69444, 0, 0, 0.55834],
2525 "8221": [0, 0.69444, 0, 0, 0.55834]
2526 },
2527 "SansSerif-Italic": {
2528 "32": [0, 0, 0, 0, 0.25],
2529 "33": [0, 0.69444, 0.05733, 0, 0.31945],
2530 "34": [0, 0.69444, 0.00316, 0, 0.5],
2531 "35": [0.19444, 0.69444, 0.05087, 0, 0.83334],
2532 "36": [0.05556, 0.75, 0.11156, 0, 0.5],
2533 "37": [0.05556, 0.75, 0.03126, 0, 0.83334],
2534 "38": [0, 0.69444, 0.03058, 0, 0.75834],
2535 "39": [0, 0.69444, 0.07816, 0, 0.27778],
2536 "40": [0.25, 0.75, 0.13164, 0, 0.38889],
2537 "41": [0.25, 0.75, 0.02536, 0, 0.38889],
2538 "42": [0, 0.75, 0.11775, 0, 0.5],
2539 "43": [0.08333, 0.58333, 0.02536, 0, 0.77778],
2540 "44": [0.125, 0.08333, 0, 0, 0.27778],
2541 "45": [0, 0.44444, 0.01946, 0, 0.33333],
2542 "46": [0, 0.08333, 0, 0, 0.27778],
2543 "47": [0.25, 0.75, 0.13164, 0, 0.5],
2544 "48": [0, 0.65556, 0.11156, 0, 0.5],
2545 "49": [0, 0.65556, 0.11156, 0, 0.5],
2546 "50": [0, 0.65556, 0.11156, 0, 0.5],
2547 "51": [0, 0.65556, 0.11156, 0, 0.5],
2548 "52": [0, 0.65556, 0.11156, 0, 0.5],
2549 "53": [0, 0.65556, 0.11156, 0, 0.5],
2550 "54": [0, 0.65556, 0.11156, 0, 0.5],
2551 "55": [0, 0.65556, 0.11156, 0, 0.5],
2552 "56": [0, 0.65556, 0.11156, 0, 0.5],
2553 "57": [0, 0.65556, 0.11156, 0, 0.5],
2554 "58": [0, 0.44444, 0.02502, 0, 0.27778],
2555 "59": [0.125, 0.44444, 0.02502, 0, 0.27778],
2556 "61": [-0.13, 0.37, 0.05087, 0, 0.77778],
2557 "63": [0, 0.69444, 0.11809, 0, 0.47222],
2558 "64": [0, 0.69444, 0.07555, 0, 0.66667],
2559 "65": [0, 0.69444, 0, 0, 0.66667],
2560 "66": [0, 0.69444, 0.08293, 0, 0.66667],
2561 "67": [0, 0.69444, 0.11983, 0, 0.63889],
2562 "68": [0, 0.69444, 0.07555, 0, 0.72223],
2563 "69": [0, 0.69444, 0.11983, 0, 0.59722],
2564 "70": [0, 0.69444, 0.13372, 0, 0.56945],
2565 "71": [0, 0.69444, 0.11983, 0, 0.66667],
2566 "72": [0, 0.69444, 0.08094, 0, 0.70834],
2567 "73": [0, 0.69444, 0.13372, 0, 0.27778],
2568 "74": [0, 0.69444, 0.08094, 0, 0.47222],
2569 "75": [0, 0.69444, 0.11983, 0, 0.69445],
2570 "76": [0, 0.69444, 0, 0, 0.54167],
2571 "77": [0, 0.69444, 0.08094, 0, 0.875],
2572 "78": [0, 0.69444, 0.08094, 0, 0.70834],
2573 "79": [0, 0.69444, 0.07555, 0, 0.73611],
2574 "80": [0, 0.69444, 0.08293, 0, 0.63889],
2575 "81": [0.125, 0.69444, 0.07555, 0, 0.73611],
2576 "82": [0, 0.69444, 0.08293, 0, 0.64584],
2577 "83": [0, 0.69444, 0.09205, 0, 0.55556],
2578 "84": [0, 0.69444, 0.13372, 0, 0.68056],
2579 "85": [0, 0.69444, 0.08094, 0, 0.6875],
2580 "86": [0, 0.69444, 0.1615, 0, 0.66667],
2581 "87": [0, 0.69444, 0.1615, 0, 0.94445],
2582 "88": [0, 0.69444, 0.13372, 0, 0.66667],
2583 "89": [0, 0.69444, 0.17261, 0, 0.66667],
2584 "90": [0, 0.69444, 0.11983, 0, 0.61111],
2585 "91": [0.25, 0.75, 0.15942, 0, 0.28889],
2586 "93": [0.25, 0.75, 0.08719, 0, 0.28889],
2587 "94": [0, 0.69444, 0.0799, 0, 0.5],
2588 "95": [0.35, 0.09444, 0.08616, 0, 0.5],
2589 "97": [0, 0.44444, 0.00981, 0, 0.48056],
2590 "98": [0, 0.69444, 0.03057, 0, 0.51667],
2591 "99": [0, 0.44444, 0.08336, 0, 0.44445],
2592 "100": [0, 0.69444, 0.09483, 0, 0.51667],
2593 "101": [0, 0.44444, 0.06778, 0, 0.44445],
2594 "102": [0, 0.69444, 0.21705, 0, 0.30556],
2595 "103": [0.19444, 0.44444, 0.10836, 0, 0.5],
2596 "104": [0, 0.69444, 0.01778, 0, 0.51667],
2597 "105": [0, 0.67937, 0.09718, 0, 0.23889],
2598 "106": [0.19444, 0.67937, 0.09162, 0, 0.26667],
2599 "107": [0, 0.69444, 0.08336, 0, 0.48889],
2600 "108": [0, 0.69444, 0.09483, 0, 0.23889],
2601 "109": [0, 0.44444, 0.01778, 0, 0.79445],
2602 "110": [0, 0.44444, 0.01778, 0, 0.51667],
2603 "111": [0, 0.44444, 0.06613, 0, 0.5],
2604 "112": [0.19444, 0.44444, 0.0389, 0, 0.51667],
2605 "113": [0.19444, 0.44444, 0.04169, 0, 0.51667],
2606 "114": [0, 0.44444, 0.10836, 0, 0.34167],
2607 "115": [0, 0.44444, 0.0778, 0, 0.38333],
2608 "116": [0, 0.57143, 0.07225, 0, 0.36111],
2609 "117": [0, 0.44444, 0.04169, 0, 0.51667],
2610 "118": [0, 0.44444, 0.10836, 0, 0.46111],
2611 "119": [0, 0.44444, 0.10836, 0, 0.68334],
2612 "120": [0, 0.44444, 0.09169, 0, 0.46111],
2613 "121": [0.19444, 0.44444, 0.10836, 0, 0.46111],
2614 "122": [0, 0.44444, 0.08752, 0, 0.43472],
2615 "126": [0.35, 0.32659, 0.08826, 0, 0.5],
2616 "160": [0, 0, 0, 0, 0.25],
2617 "168": [0, 0.67937, 0.06385, 0, 0.5],
2618 "176": [0, 0.69444, 0, 0, 0.73752],
2619 "184": [0.17014, 0, 0, 0, 0.44445],
2620 "305": [0, 0.44444, 0.04169, 0, 0.23889],
2621 "567": [0.19444, 0.44444, 0.04169, 0, 0.26667],
2622 "710": [0, 0.69444, 0.0799, 0, 0.5],
2623 "711": [0, 0.63194, 0.08432, 0, 0.5],
2624 "713": [0, 0.60889, 0.08776, 0, 0.5],
2625 "714": [0, 0.69444, 0.09205, 0, 0.5],
2626 "715": [0, 0.69444, 0, 0, 0.5],
2627 "728": [0, 0.69444, 0.09483, 0, 0.5],
2628 "729": [0, 0.67937, 0.07774, 0, 0.27778],
2629 "730": [0, 0.69444, 0, 0, 0.73752],
2630 "732": [0, 0.67659, 0.08826, 0, 0.5],
2631 "733": [0, 0.69444, 0.09205, 0, 0.5],
2632 "915": [0, 0.69444, 0.13372, 0, 0.54167],
2633 "916": [0, 0.69444, 0, 0, 0.83334],
2634 "920": [0, 0.69444, 0.07555, 0, 0.77778],
2635 "923": [0, 0.69444, 0, 0, 0.61111],
2636 "926": [0, 0.69444, 0.12816, 0, 0.66667],
2637 "928": [0, 0.69444, 0.08094, 0, 0.70834],
2638 "931": [0, 0.69444, 0.11983, 0, 0.72222],
2639 "933": [0, 0.69444, 0.09031, 0, 0.77778],
2640 "934": [0, 0.69444, 0.04603, 0, 0.72222],
2641 "936": [0, 0.69444, 0.09031, 0, 0.77778],
2642 "937": [0, 0.69444, 0.08293, 0, 0.72222],
2643 "8211": [0, 0.44444, 0.08616, 0, 0.5],
2644 "8212": [0, 0.44444, 0.08616, 0, 1.0],
2645 "8216": [0, 0.69444, 0.07816, 0, 0.27778],
2646 "8217": [0, 0.69444, 0.07816, 0, 0.27778],
2647 "8220": [0, 0.69444, 0.14205, 0, 0.5],
2648 "8221": [0, 0.69444, 0.00316, 0, 0.5]
2649 },
2650 "SansSerif-Regular": {
2651 "32": [0, 0, 0, 0, 0.25],
2652 "33": [0, 0.69444, 0, 0, 0.31945],
2653 "34": [0, 0.69444, 0, 0, 0.5],
2654 "35": [0.19444, 0.69444, 0, 0, 0.83334],
2655 "36": [0.05556, 0.75, 0, 0, 0.5],
2656 "37": [0.05556, 0.75, 0, 0, 0.83334],
2657 "38": [0, 0.69444, 0, 0, 0.75834],
2658 "39": [0, 0.69444, 0, 0, 0.27778],
2659 "40": [0.25, 0.75, 0, 0, 0.38889],
2660 "41": [0.25, 0.75, 0, 0, 0.38889],
2661 "42": [0, 0.75, 0, 0, 0.5],
2662 "43": [0.08333, 0.58333, 0, 0, 0.77778],
2663 "44": [0.125, 0.08333, 0, 0, 0.27778],
2664 "45": [0, 0.44444, 0, 0, 0.33333],
2665 "46": [0, 0.08333, 0, 0, 0.27778],
2666 "47": [0.25, 0.75, 0, 0, 0.5],
2667 "48": [0, 0.65556, 0, 0, 0.5],
2668 "49": [0, 0.65556, 0, 0, 0.5],
2669 "50": [0, 0.65556, 0, 0, 0.5],
2670 "51": [0, 0.65556, 0, 0, 0.5],
2671 "52": [0, 0.65556, 0, 0, 0.5],
2672 "53": [0, 0.65556, 0, 0, 0.5],
2673 "54": [0, 0.65556, 0, 0, 0.5],
2674 "55": [0, 0.65556, 0, 0, 0.5],
2675 "56": [0, 0.65556, 0, 0, 0.5],
2676 "57": [0, 0.65556, 0, 0, 0.5],
2677 "58": [0, 0.44444, 0, 0, 0.27778],
2678 "59": [0.125, 0.44444, 0, 0, 0.27778],
2679 "61": [-0.13, 0.37, 0, 0, 0.77778],
2680 "63": [0, 0.69444, 0, 0, 0.47222],
2681 "64": [0, 0.69444, 0, 0, 0.66667],
2682 "65": [0, 0.69444, 0, 0, 0.66667],
2683 "66": [0, 0.69444, 0, 0, 0.66667],
2684 "67": [0, 0.69444, 0, 0, 0.63889],
2685 "68": [0, 0.69444, 0, 0, 0.72223],
2686 "69": [0, 0.69444, 0, 0, 0.59722],
2687 "70": [0, 0.69444, 0, 0, 0.56945],
2688 "71": [0, 0.69444, 0, 0, 0.66667],
2689 "72": [0, 0.69444, 0, 0, 0.70834],
2690 "73": [0, 0.69444, 0, 0, 0.27778],
2691 "74": [0, 0.69444, 0, 0, 0.47222],
2692 "75": [0, 0.69444, 0, 0, 0.69445],
2693 "76": [0, 0.69444, 0, 0, 0.54167],
2694 "77": [0, 0.69444, 0, 0, 0.875],
2695 "78": [0, 0.69444, 0, 0, 0.70834],
2696 "79": [0, 0.69444, 0, 0, 0.73611],
2697 "80": [0, 0.69444, 0, 0, 0.63889],
2698 "81": [0.125, 0.69444, 0, 0, 0.73611],
2699 "82": [0, 0.69444, 0, 0, 0.64584],
2700 "83": [0, 0.69444, 0, 0, 0.55556],
2701 "84": [0, 0.69444, 0, 0, 0.68056],
2702 "85": [0, 0.69444, 0, 0, 0.6875],
2703 "86": [0, 0.69444, 0.01389, 0, 0.66667],
2704 "87": [0, 0.69444, 0.01389, 0, 0.94445],
2705 "88": [0, 0.69444, 0, 0, 0.66667],
2706 "89": [0, 0.69444, 0.025, 0, 0.66667],
2707 "90": [0, 0.69444, 0, 0, 0.61111],
2708 "91": [0.25, 0.75, 0, 0, 0.28889],
2709 "93": [0.25, 0.75, 0, 0, 0.28889],
2710 "94": [0, 0.69444, 0, 0, 0.5],
2711 "95": [0.35, 0.09444, 0.02778, 0, 0.5],
2712 "97": [0, 0.44444, 0, 0, 0.48056],
2713 "98": [0, 0.69444, 0, 0, 0.51667],
2714 "99": [0, 0.44444, 0, 0, 0.44445],
2715 "100": [0, 0.69444, 0, 0, 0.51667],
2716 "101": [0, 0.44444, 0, 0, 0.44445],
2717 "102": [0, 0.69444, 0.06944, 0, 0.30556],
2718 "103": [0.19444, 0.44444, 0.01389, 0, 0.5],
2719 "104": [0, 0.69444, 0, 0, 0.51667],
2720 "105": [0, 0.67937, 0, 0, 0.23889],
2721 "106": [0.19444, 0.67937, 0, 0, 0.26667],
2722 "107": [0, 0.69444, 0, 0, 0.48889],
2723 "108": [0, 0.69444, 0, 0, 0.23889],
2724 "109": [0, 0.44444, 0, 0, 0.79445],
2725 "110": [0, 0.44444, 0, 0, 0.51667],
2726 "111": [0, 0.44444, 0, 0, 0.5],
2727 "112": [0.19444, 0.44444, 0, 0, 0.51667],
2728 "113": [0.19444, 0.44444, 0, 0, 0.51667],
2729 "114": [0, 0.44444, 0.01389, 0, 0.34167],
2730 "115": [0, 0.44444, 0, 0, 0.38333],
2731 "116": [0, 0.57143, 0, 0, 0.36111],
2732 "117": [0, 0.44444, 0, 0, 0.51667],
2733 "118": [0, 0.44444, 0.01389, 0, 0.46111],
2734 "119": [0, 0.44444, 0.01389, 0, 0.68334],
2735 "120": [0, 0.44444, 0, 0, 0.46111],
2736 "121": [0.19444, 0.44444, 0.01389, 0, 0.46111],
2737 "122": [0, 0.44444, 0, 0, 0.43472],
2738 "126": [0.35, 0.32659, 0, 0, 0.5],
2739 "160": [0, 0, 0, 0, 0.25],
2740 "168": [0, 0.67937, 0, 0, 0.5],
2741 "176": [0, 0.69444, 0, 0, 0.66667],
2742 "184": [0.17014, 0, 0, 0, 0.44445],
2743 "305": [0, 0.44444, 0, 0, 0.23889],
2744 "567": [0.19444, 0.44444, 0, 0, 0.26667],
2745 "710": [0, 0.69444, 0, 0, 0.5],
2746 "711": [0, 0.63194, 0, 0, 0.5],
2747 "713": [0, 0.60889, 0, 0, 0.5],
2748 "714": [0, 0.69444, 0, 0, 0.5],
2749 "715": [0, 0.69444, 0, 0, 0.5],
2750 "728": [0, 0.69444, 0, 0, 0.5],
2751 "729": [0, 0.67937, 0, 0, 0.27778],
2752 "730": [0, 0.69444, 0, 0, 0.66667],
2753 "732": [0, 0.67659, 0, 0, 0.5],
2754 "733": [0, 0.69444, 0, 0, 0.5],
2755 "915": [0, 0.69444, 0, 0, 0.54167],
2756 "916": [0, 0.69444, 0, 0, 0.83334],
2757 "920": [0, 0.69444, 0, 0, 0.77778],
2758 "923": [0, 0.69444, 0, 0, 0.61111],
2759 "926": [0, 0.69444, 0, 0, 0.66667],
2760 "928": [0, 0.69444, 0, 0, 0.70834],
2761 "931": [0, 0.69444, 0, 0, 0.72222],
2762 "933": [0, 0.69444, 0, 0, 0.77778],
2763 "934": [0, 0.69444, 0, 0, 0.72222],
2764 "936": [0, 0.69444, 0, 0, 0.77778],
2765 "937": [0, 0.69444, 0, 0, 0.72222],
2766 "8211": [0, 0.44444, 0.02778, 0, 0.5],
2767 "8212": [0, 0.44444, 0.02778, 0, 1.0],
2768 "8216": [0, 0.69444, 0, 0, 0.27778],
2769 "8217": [0, 0.69444, 0, 0, 0.27778],
2770 "8220": [0, 0.69444, 0, 0, 0.5],
2771 "8221": [0, 0.69444, 0, 0, 0.5]
2772 },
2773 "Script-Regular": {
2774 "32": [0, 0, 0, 0, 0.25],
2775 "65": [0, 0.7, 0.22925, 0, 0.80253],
2776 "66": [0, 0.7, 0.04087, 0, 0.90757],
2777 "67": [0, 0.7, 0.1689, 0, 0.66619],
2778 "68": [0, 0.7, 0.09371, 0, 0.77443],
2779 "69": [0, 0.7, 0.18583, 0, 0.56162],
2780 "70": [0, 0.7, 0.13634, 0, 0.89544],
2781 "71": [0, 0.7, 0.17322, 0, 0.60961],
2782 "72": [0, 0.7, 0.29694, 0, 0.96919],
2783 "73": [0, 0.7, 0.19189, 0, 0.80907],
2784 "74": [0.27778, 0.7, 0.19189, 0, 1.05159],
2785 "75": [0, 0.7, 0.31259, 0, 0.91364],
2786 "76": [0, 0.7, 0.19189, 0, 0.87373],
2787 "77": [0, 0.7, 0.15981, 0, 1.08031],
2788 "78": [0, 0.7, 0.3525, 0, 0.9015],
2789 "79": [0, 0.7, 0.08078, 0, 0.73787],
2790 "80": [0, 0.7, 0.08078, 0, 1.01262],
2791 "81": [0, 0.7, 0.03305, 0, 0.88282],
2792 "82": [0, 0.7, 0.06259, 0, 0.85],
2793 "83": [0, 0.7, 0.19189, 0, 0.86767],
2794 "84": [0, 0.7, 0.29087, 0, 0.74697],
2795 "85": [0, 0.7, 0.25815, 0, 0.79996],
2796 "86": [0, 0.7, 0.27523, 0, 0.62204],
2797 "87": [0, 0.7, 0.27523, 0, 0.80532],
2798 "88": [0, 0.7, 0.26006, 0, 0.94445],
2799 "89": [0, 0.7, 0.2939, 0, 0.70961],
2800 "90": [0, 0.7, 0.24037, 0, 0.8212],
2801 "160": [0, 0, 0, 0, 0.25]
2802 },
2803 "Size1-Regular": {
2804 "32": [0, 0, 0, 0, 0.25],
2805 "40": [0.35001, 0.85, 0, 0, 0.45834],
2806 "41": [0.35001, 0.85, 0, 0, 0.45834],
2807 "47": [0.35001, 0.85, 0, 0, 0.57778],
2808 "91": [0.35001, 0.85, 0, 0, 0.41667],
2809 "92": [0.35001, 0.85, 0, 0, 0.57778],
2810 "93": [0.35001, 0.85, 0, 0, 0.41667],
2811 "123": [0.35001, 0.85, 0, 0, 0.58334],
2812 "125": [0.35001, 0.85, 0, 0, 0.58334],
2813 "160": [0, 0, 0, 0, 0.25],
2814 "710": [0, 0.72222, 0, 0, 0.55556],
2815 "732": [0, 0.72222, 0, 0, 0.55556],
2816 "770": [0, 0.72222, 0, 0, 0.55556],
2817 "771": [0, 0.72222, 0, 0, 0.55556],
2818 "8214": [-0.00099, 0.601, 0, 0, 0.77778],
2819 "8593": [1e-05, 0.6, 0, 0, 0.66667],
2820 "8595": [1e-05, 0.6, 0, 0, 0.66667],
2821 "8657": [1e-05, 0.6, 0, 0, 0.77778],
2822 "8659": [1e-05, 0.6, 0, 0, 0.77778],
2823 "8719": [0.25001, 0.75, 0, 0, 0.94445],
2824 "8720": [0.25001, 0.75, 0, 0, 0.94445],
2825 "8721": [0.25001, 0.75, 0, 0, 1.05556],
2826 "8730": [0.35001, 0.85, 0, 0, 1.0],
2827 "8739": [-0.00599, 0.606, 0, 0, 0.33333],
2828 "8741": [-0.00599, 0.606, 0, 0, 0.55556],
2829 "8747": [0.30612, 0.805, 0.19445, 0, 0.47222],
2830 "8748": [0.306, 0.805, 0.19445, 0, 0.47222],
2831 "8749": [0.306, 0.805, 0.19445, 0, 0.47222],
2832 "8750": [0.30612, 0.805, 0.19445, 0, 0.47222],
2833 "8896": [0.25001, 0.75, 0, 0, 0.83334],
2834 "8897": [0.25001, 0.75, 0, 0, 0.83334],
2835 "8898": [0.25001, 0.75, 0, 0, 0.83334],
2836 "8899": [0.25001, 0.75, 0, 0, 0.83334],
2837 "8968": [0.35001, 0.85, 0, 0, 0.47222],
2838 "8969": [0.35001, 0.85, 0, 0, 0.47222],
2839 "8970": [0.35001, 0.85, 0, 0, 0.47222],
2840 "8971": [0.35001, 0.85, 0, 0, 0.47222],
2841 "9168": [-0.00099, 0.601, 0, 0, 0.66667],
2842 "10216": [0.35001, 0.85, 0, 0, 0.47222],
2843 "10217": [0.35001, 0.85, 0, 0, 0.47222],
2844 "10752": [0.25001, 0.75, 0, 0, 1.11111],
2845 "10753": [0.25001, 0.75, 0, 0, 1.11111],
2846 "10754": [0.25001, 0.75, 0, 0, 1.11111],
2847 "10756": [0.25001, 0.75, 0, 0, 0.83334],
2848 "10758": [0.25001, 0.75, 0, 0, 0.83334]
2849 },
2850 "Size2-Regular": {
2851 "32": [0, 0, 0, 0, 0.25],
2852 "40": [0.65002, 1.15, 0, 0, 0.59722],
2853 "41": [0.65002, 1.15, 0, 0, 0.59722],
2854 "47": [0.65002, 1.15, 0, 0, 0.81111],
2855 "91": [0.65002, 1.15, 0, 0, 0.47222],
2856 "92": [0.65002, 1.15, 0, 0, 0.81111],
2857 "93": [0.65002, 1.15, 0, 0, 0.47222],
2858 "123": [0.65002, 1.15, 0, 0, 0.66667],
2859 "125": [0.65002, 1.15, 0, 0, 0.66667],
2860 "160": [0, 0, 0, 0, 0.25],
2861 "710": [0, 0.75, 0, 0, 1.0],
2862 "732": [0, 0.75, 0, 0, 1.0],
2863 "770": [0, 0.75, 0, 0, 1.0],
2864 "771": [0, 0.75, 0, 0, 1.0],
2865 "8719": [0.55001, 1.05, 0, 0, 1.27778],
2866 "8720": [0.55001, 1.05, 0, 0, 1.27778],
2867 "8721": [0.55001, 1.05, 0, 0, 1.44445],
2868 "8730": [0.65002, 1.15, 0, 0, 1.0],
2869 "8747": [0.86225, 1.36, 0.44445, 0, 0.55556],
2870 "8748": [0.862, 1.36, 0.44445, 0, 0.55556],
2871 "8749": [0.862, 1.36, 0.44445, 0, 0.55556],
2872 "8750": [0.86225, 1.36, 0.44445, 0, 0.55556],
2873 "8896": [0.55001, 1.05, 0, 0, 1.11111],
2874 "8897": [0.55001, 1.05, 0, 0, 1.11111],
2875 "8898": [0.55001, 1.05, 0, 0, 1.11111],
2876 "8899": [0.55001, 1.05, 0, 0, 1.11111],
2877 "8968": [0.65002, 1.15, 0, 0, 0.52778],
2878 "8969": [0.65002, 1.15, 0, 0, 0.52778],
2879 "8970": [0.65002, 1.15, 0, 0, 0.52778],
2880 "8971": [0.65002, 1.15, 0, 0, 0.52778],
2881 "10216": [0.65002, 1.15, 0, 0, 0.61111],
2882 "10217": [0.65002, 1.15, 0, 0, 0.61111],
2883 "10752": [0.55001, 1.05, 0, 0, 1.51112],
2884 "10753": [0.55001, 1.05, 0, 0, 1.51112],
2885 "10754": [0.55001, 1.05, 0, 0, 1.51112],
2886 "10756": [0.55001, 1.05, 0, 0, 1.11111],
2887 "10758": [0.55001, 1.05, 0, 0, 1.11111]
2888 },
2889 "Size3-Regular": {
2890 "32": [0, 0, 0, 0, 0.25],
2891 "40": [0.95003, 1.45, 0, 0, 0.73611],
2892 "41": [0.95003, 1.45, 0, 0, 0.73611],
2893 "47": [0.95003, 1.45, 0, 0, 1.04445],
2894 "91": [0.95003, 1.45, 0, 0, 0.52778],
2895 "92": [0.95003, 1.45, 0, 0, 1.04445],
2896 "93": [0.95003, 1.45, 0, 0, 0.52778],
2897 "123": [0.95003, 1.45, 0, 0, 0.75],
2898 "125": [0.95003, 1.45, 0, 0, 0.75],
2899 "160": [0, 0, 0, 0, 0.25],
2900 "710": [0, 0.75, 0, 0, 1.44445],
2901 "732": [0, 0.75, 0, 0, 1.44445],
2902 "770": [0, 0.75, 0, 0, 1.44445],
2903 "771": [0, 0.75, 0, 0, 1.44445],
2904 "8730": [0.95003, 1.45, 0, 0, 1.0],
2905 "8968": [0.95003, 1.45, 0, 0, 0.58334],
2906 "8969": [0.95003, 1.45, 0, 0, 0.58334],
2907 "8970": [0.95003, 1.45, 0, 0, 0.58334],
2908 "8971": [0.95003, 1.45, 0, 0, 0.58334],
2909 "10216": [0.95003, 1.45, 0, 0, 0.75],
2910 "10217": [0.95003, 1.45, 0, 0, 0.75]
2911 },
2912 "Size4-Regular": {
2913 "32": [0, 0, 0, 0, 0.25],
2914 "40": [1.25003, 1.75, 0, 0, 0.79167],
2915 "41": [1.25003, 1.75, 0, 0, 0.79167],
2916 "47": [1.25003, 1.75, 0, 0, 1.27778],
2917 "91": [1.25003, 1.75, 0, 0, 0.58334],
2918 "92": [1.25003, 1.75, 0, 0, 1.27778],
2919 "93": [1.25003, 1.75, 0, 0, 0.58334],
2920 "123": [1.25003, 1.75, 0, 0, 0.80556],
2921 "125": [1.25003, 1.75, 0, 0, 0.80556],
2922 "160": [0, 0, 0, 0, 0.25],
2923 "710": [0, 0.825, 0, 0, 1.8889],
2924 "732": [0, 0.825, 0, 0, 1.8889],
2925 "770": [0, 0.825, 0, 0, 1.8889],
2926 "771": [0, 0.825, 0, 0, 1.8889],
2927 "8730": [1.25003, 1.75, 0, 0, 1.0],
2928 "8968": [1.25003, 1.75, 0, 0, 0.63889],
2929 "8969": [1.25003, 1.75, 0, 0, 0.63889],
2930 "8970": [1.25003, 1.75, 0, 0, 0.63889],
2931 "8971": [1.25003, 1.75, 0, 0, 0.63889],
2932 "9115": [0.64502, 1.155, 0, 0, 0.875],
2933 "9116": [1e-05, 0.6, 0, 0, 0.875],
2934 "9117": [0.64502, 1.155, 0, 0, 0.875],
2935 "9118": [0.64502, 1.155, 0, 0, 0.875],
2936 "9119": [1e-05, 0.6, 0, 0, 0.875],
2937 "9120": [0.64502, 1.155, 0, 0, 0.875],
2938 "9121": [0.64502, 1.155, 0, 0, 0.66667],
2939 "9122": [-0.00099, 0.601, 0, 0, 0.66667],
2940 "9123": [0.64502, 1.155, 0, 0, 0.66667],
2941 "9124": [0.64502, 1.155, 0, 0, 0.66667],
2942 "9125": [-0.00099, 0.601, 0, 0, 0.66667],
2943 "9126": [0.64502, 1.155, 0, 0, 0.66667],
2944 "9127": [1e-05, 0.9, 0, 0, 0.88889],
2945 "9128": [0.65002, 1.15, 0, 0, 0.88889],
2946 "9129": [0.90001, 0, 0, 0, 0.88889],
2947 "9130": [0, 0.3, 0, 0, 0.88889],
2948 "9131": [1e-05, 0.9, 0, 0, 0.88889],
2949 "9132": [0.65002, 1.15, 0, 0, 0.88889],
2950 "9133": [0.90001, 0, 0, 0, 0.88889],
2951 "9143": [0.88502, 0.915, 0, 0, 1.05556],
2952 "10216": [1.25003, 1.75, 0, 0, 0.80556],
2953 "10217": [1.25003, 1.75, 0, 0, 0.80556],
2954 "57344": [-0.00499, 0.605, 0, 0, 1.05556],
2955 "57345": [-0.00499, 0.605, 0, 0, 1.05556],
2956 "57680": [0, 0.12, 0, 0, 0.45],
2957 "57681": [0, 0.12, 0, 0, 0.45],
2958 "57682": [0, 0.12, 0, 0, 0.45],
2959 "57683": [0, 0.12, 0, 0, 0.45]
2960 },
2961 "Typewriter-Regular": {
2962 "32": [0, 0, 0, 0, 0.525],
2963 "33": [0, 0.61111, 0, 0, 0.525],
2964 "34": [0, 0.61111, 0, 0, 0.525],
2965 "35": [0, 0.61111, 0, 0, 0.525],
2966 "36": [0.08333, 0.69444, 0, 0, 0.525],
2967 "37": [0.08333, 0.69444, 0, 0, 0.525],
2968 "38": [0, 0.61111, 0, 0, 0.525],
2969 "39": [0, 0.61111, 0, 0, 0.525],
2970 "40": [0.08333, 0.69444, 0, 0, 0.525],
2971 "41": [0.08333, 0.69444, 0, 0, 0.525],
2972 "42": [0, 0.52083, 0, 0, 0.525],
2973 "43": [-0.08056, 0.53055, 0, 0, 0.525],
2974 "44": [0.13889, 0.125, 0, 0, 0.525],
2975 "45": [-0.08056, 0.53055, 0, 0, 0.525],
2976 "46": [0, 0.125, 0, 0, 0.525],
2977 "47": [0.08333, 0.69444, 0, 0, 0.525],
2978 "48": [0, 0.61111, 0, 0, 0.525],
2979 "49": [0, 0.61111, 0, 0, 0.525],
2980 "50": [0, 0.61111, 0, 0, 0.525],
2981 "51": [0, 0.61111, 0, 0, 0.525],
2982 "52": [0, 0.61111, 0, 0, 0.525],
2983 "53": [0, 0.61111, 0, 0, 0.525],
2984 "54": [0, 0.61111, 0, 0, 0.525],
2985 "55": [0, 0.61111, 0, 0, 0.525],
2986 "56": [0, 0.61111, 0, 0, 0.525],
2987 "57": [0, 0.61111, 0, 0, 0.525],
2988 "58": [0, 0.43056, 0, 0, 0.525],
2989 "59": [0.13889, 0.43056, 0, 0, 0.525],
2990 "60": [-0.05556, 0.55556, 0, 0, 0.525],
2991 "61": [-0.19549, 0.41562, 0, 0, 0.525],
2992 "62": [-0.05556, 0.55556, 0, 0, 0.525],
2993 "63": [0, 0.61111, 0, 0, 0.525],
2994 "64": [0, 0.61111, 0, 0, 0.525],
2995 "65": [0, 0.61111, 0, 0, 0.525],
2996 "66": [0, 0.61111, 0, 0, 0.525],
2997 "67": [0, 0.61111, 0, 0, 0.525],
2998 "68": [0, 0.61111, 0, 0, 0.525],
2999 "69": [0, 0.61111, 0, 0, 0.525],
3000 "70": [0, 0.61111, 0, 0, 0.525],
3001 "71": [0, 0.61111, 0, 0, 0.525],
3002 "72": [0, 0.61111, 0, 0, 0.525],
3003 "73": [0, 0.61111, 0, 0, 0.525],
3004 "74": [0, 0.61111, 0, 0, 0.525],
3005 "75": [0, 0.61111, 0, 0, 0.525],
3006 "76": [0, 0.61111, 0, 0, 0.525],
3007 "77": [0, 0.61111, 0, 0, 0.525],
3008 "78": [0, 0.61111, 0, 0, 0.525],
3009 "79": [0, 0.61111, 0, 0, 0.525],
3010 "80": [0, 0.61111, 0, 0, 0.525],
3011 "81": [0.13889, 0.61111, 0, 0, 0.525],
3012 "82": [0, 0.61111, 0, 0, 0.525],
3013 "83": [0, 0.61111, 0, 0, 0.525],
3014 "84": [0, 0.61111, 0, 0, 0.525],
3015 "85": [0, 0.61111, 0, 0, 0.525],
3016 "86": [0, 0.61111, 0, 0, 0.525],
3017 "87": [0, 0.61111, 0, 0, 0.525],
3018 "88": [0, 0.61111, 0, 0, 0.525],
3019 "89": [0, 0.61111, 0, 0, 0.525],
3020 "90": [0, 0.61111, 0, 0, 0.525],
3021 "91": [0.08333, 0.69444, 0, 0, 0.525],
3022 "92": [0.08333, 0.69444, 0, 0, 0.525],
3023 "93": [0.08333, 0.69444, 0, 0, 0.525],
3024 "94": [0, 0.61111, 0, 0, 0.525],
3025 "95": [0.09514, 0, 0, 0, 0.525],
3026 "96": [0, 0.61111, 0, 0, 0.525],
3027 "97": [0, 0.43056, 0, 0, 0.525],
3028 "98": [0, 0.61111, 0, 0, 0.525],
3029 "99": [0, 0.43056, 0, 0, 0.525],
3030 "100": [0, 0.61111, 0, 0, 0.525],
3031 "101": [0, 0.43056, 0, 0, 0.525],
3032 "102": [0, 0.61111, 0, 0, 0.525],
3033 "103": [0.22222, 0.43056, 0, 0, 0.525],
3034 "104": [0, 0.61111, 0, 0, 0.525],
3035 "105": [0, 0.61111, 0, 0, 0.525],
3036 "106": [0.22222, 0.61111, 0, 0, 0.525],
3037 "107": [0, 0.61111, 0, 0, 0.525],
3038 "108": [0, 0.61111, 0, 0, 0.525],
3039 "109": [0, 0.43056, 0, 0, 0.525],
3040 "110": [0, 0.43056, 0, 0, 0.525],
3041 "111": [0, 0.43056, 0, 0, 0.525],
3042 "112": [0.22222, 0.43056, 0, 0, 0.525],
3043 "113": [0.22222, 0.43056, 0, 0, 0.525],
3044 "114": [0, 0.43056, 0, 0, 0.525],
3045 "115": [0, 0.43056, 0, 0, 0.525],
3046 "116": [0, 0.55358, 0, 0, 0.525],
3047 "117": [0, 0.43056, 0, 0, 0.525],
3048 "118": [0, 0.43056, 0, 0, 0.525],
3049 "119": [0, 0.43056, 0, 0, 0.525],
3050 "120": [0, 0.43056, 0, 0, 0.525],
3051 "121": [0.22222, 0.43056, 0, 0, 0.525],
3052 "122": [0, 0.43056, 0, 0, 0.525],
3053 "123": [0.08333, 0.69444, 0, 0, 0.525],
3054 "124": [0.08333, 0.69444, 0, 0, 0.525],
3055 "125": [0.08333, 0.69444, 0, 0, 0.525],
3056 "126": [0, 0.61111, 0, 0, 0.525],
3057 "127": [0, 0.61111, 0, 0, 0.525],
3058 "160": [0, 0, 0, 0, 0.525],
3059 "176": [0, 0.61111, 0, 0, 0.525],
3060 "184": [0.19445, 0, 0, 0, 0.525],
3061 "305": [0, 0.43056, 0, 0, 0.525],
3062 "567": [0.22222, 0.43056, 0, 0, 0.525],
3063 "711": [0, 0.56597, 0, 0, 0.525],
3064 "713": [0, 0.56555, 0, 0, 0.525],
3065 "714": [0, 0.61111, 0, 0, 0.525],
3066 "715": [0, 0.61111, 0, 0, 0.525],
3067 "728": [0, 0.61111, 0, 0, 0.525],
3068 "730": [0, 0.61111, 0, 0, 0.525],
3069 "770": [0, 0.61111, 0, 0, 0.525],
3070 "771": [0, 0.61111, 0, 0, 0.525],
3071 "776": [0, 0.61111, 0, 0, 0.525],
3072 "915": [0, 0.61111, 0, 0, 0.525],
3073 "916": [0, 0.61111, 0, 0, 0.525],
3074 "920": [0, 0.61111, 0, 0, 0.525],
3075 "923": [0, 0.61111, 0, 0, 0.525],
3076 "926": [0, 0.61111, 0, 0, 0.525],
3077 "928": [0, 0.61111, 0, 0, 0.525],
3078 "931": [0, 0.61111, 0, 0, 0.525],
3079 "933": [0, 0.61111, 0, 0, 0.525],
3080 "934": [0, 0.61111, 0, 0, 0.525],
3081 "936": [0, 0.61111, 0, 0, 0.525],
3082 "937": [0, 0.61111, 0, 0, 0.525],
3083 "8216": [0, 0.61111, 0, 0, 0.525],
3084 "8217": [0, 0.61111, 0, 0, 0.525],
3085 "8242": [0, 0.61111, 0, 0, 0.525],
3086 "9251": [0.11111, 0.21944, 0, 0, 0.525]
3087 }
3088};
3089
3090/**
3091 * This file contains metrics regarding fonts and individual symbols. The sigma
3092 * and xi variables, as well as the metricMap map contain data extracted from
3093 * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
3094 * `metrics` variable and the getCharacterMetrics function.
3095 */
3096// In TeX, there are actually three sets of dimensions, one for each of
3097// textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4:
3098// 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt). These are
3099// provided in the the arrays below, in that order.
3100//
3101// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively.
3102// This was determined by running the following script:
3103//
3104// latex -interaction=nonstopmode \
3105// '\documentclass{article}\usepackage{amsmath}\begin{document}' \
3106// '$a$ \expandafter\show\the\textfont2' \
3107// '\expandafter\show\the\scriptfont2' \
3108// '\expandafter\show\the\scriptscriptfont2' \
3109// '\stop'
3110//
3111// The metrics themselves were retreived using the following commands:
3112//
3113// tftopl cmsy10
3114// tftopl cmsy7
3115// tftopl cmsy5
3116//
3117// The output of each of these commands is quite lengthy. The only part we
3118// care about is the FONTDIMEN section. Each value is measured in EMs.
3119var sigmasAndXis = {
3120 slant: [0.250, 0.250, 0.250],
3121 // sigma1
3122 space: [0.000, 0.000, 0.000],
3123 // sigma2
3124 stretch: [0.000, 0.000, 0.000],
3125 // sigma3
3126 shrink: [0.000, 0.000, 0.000],
3127 // sigma4
3128 xHeight: [0.431, 0.431, 0.431],
3129 // sigma5
3130 quad: [1.000, 1.171, 1.472],
3131 // sigma6
3132 extraSpace: [0.000, 0.000, 0.000],
3133 // sigma7
3134 num1: [0.677, 0.732, 0.925],
3135 // sigma8
3136 num2: [0.394, 0.384, 0.387],
3137 // sigma9
3138 num3: [0.444, 0.471, 0.504],
3139 // sigma10
3140 denom1: [0.686, 0.752, 1.025],
3141 // sigma11
3142 denom2: [0.345, 0.344, 0.532],
3143 // sigma12
3144 sup1: [0.413, 0.503, 0.504],
3145 // sigma13
3146 sup2: [0.363, 0.431, 0.404],
3147 // sigma14
3148 sup3: [0.289, 0.286, 0.294],
3149 // sigma15
3150 sub1: [0.150, 0.143, 0.200],
3151 // sigma16
3152 sub2: [0.247, 0.286, 0.400],
3153 // sigma17
3154 supDrop: [0.386, 0.353, 0.494],
3155 // sigma18
3156 subDrop: [0.050, 0.071, 0.100],
3157 // sigma19
3158 delim1: [2.390, 1.700, 1.980],
3159 // sigma20
3160 delim2: [1.010, 1.157, 1.420],
3161 // sigma21
3162 axisHeight: [0.250, 0.250, 0.250],
3163 // sigma22
3164 // These font metrics are extracted from TeX by using tftopl on cmex10.tfm;
3165 // they correspond to the font parameters of the extension fonts (family 3).
3166 // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to
3167 // match cmex7, we'd use cmex7.tfm values for script and scriptscript
3168 // values.
3169 defaultRuleThickness: [0.04, 0.049, 0.049],
3170 // xi8; cmex7: 0.049
3171 bigOpSpacing1: [0.111, 0.111, 0.111],
3172 // xi9
3173 bigOpSpacing2: [0.166, 0.166, 0.166],
3174 // xi10
3175 bigOpSpacing3: [0.2, 0.2, 0.2],
3176 // xi11
3177 bigOpSpacing4: [0.6, 0.611, 0.611],
3178 // xi12; cmex7: 0.611
3179 bigOpSpacing5: [0.1, 0.143, 0.143],
3180 // xi13; cmex7: 0.143
3181 // The \sqrt rule width is taken from the height of the surd character.
3182 // Since we use the same font at all sizes, this thickness doesn't scale.
3183 sqrtRuleThickness: [0.04, 0.04, 0.04],
3184 // This value determines how large a pt is, for metrics which are defined
3185 // in terms of pts.
3186 // This value is also used in katex.less; if you change it make sure the
3187 // values match.
3188 ptPerEm: [10.0, 10.0, 10.0],
3189 // The space between adjacent `|` columns in an array definition. From
3190 // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm.
3191 doubleRuleSep: [0.2, 0.2, 0.2],
3192 // The width of separator lines in {array} environments. From
3193 // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm.
3194 arrayRuleWidth: [0.04, 0.04, 0.04],
3195 // Two values from LaTeX source2e:
3196 fboxsep: [0.3, 0.3, 0.3],
3197 // 3 pt / ptPerEm
3198 fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm
3199
3200}; // This map contains a mapping from font name and character code to character
3201// should have Latin-1 and Cyrillic characters, but may not depending on the
3202// operating system. The metrics do not account for extra height from the
3203// accents. In the case of Cyrillic characters which have both ascenders and
3204// descenders we prefer approximations with ascenders, primarily to prevent
3205// the fraction bar or root line from intersecting the glyph.
3206// TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
3207
3208var extraCharacterMap = {
3209 // Latin-1
3210 'Å': 'A',
3211 'Ð': 'D',
3212 'Þ': 'o',
3213 'å': 'a',
3214 'ð': 'd',
3215 'þ': 'o',
3216 // Cyrillic
3217 'А': 'A',
3218 'Б': 'B',
3219 'В': 'B',
3220 'Г': 'F',
3221 'Д': 'A',
3222 'Е': 'E',
3223 'Ж': 'K',
3224 'З': '3',
3225 'И': 'N',
3226 'Й': 'N',
3227 'К': 'K',
3228 'Л': 'N',
3229 'М': 'M',
3230 'Н': 'H',
3231 'О': 'O',
3232 'П': 'N',
3233 'Р': 'P',
3234 'С': 'C',
3235 'Т': 'T',
3236 'У': 'y',
3237 'Ф': 'O',
3238 'Х': 'X',
3239 'Ц': 'U',
3240 'Ч': 'h',
3241 'Ш': 'W',
3242 'Щ': 'W',
3243 'Ъ': 'B',
3244 'Ы': 'X',
3245 'Ь': 'B',
3246 'Э': '3',
3247 'Ю': 'X',
3248 'Я': 'R',
3249 'а': 'a',
3250 'б': 'b',
3251 'в': 'a',
3252 'г': 'r',
3253 'д': 'y',
3254 'е': 'e',
3255 'ж': 'm',
3256 'з': 'e',
3257 'и': 'n',
3258 'й': 'n',
3259 'к': 'n',
3260 'л': 'n',
3261 'м': 'm',
3262 'н': 'n',
3263 'о': 'o',
3264 'п': 'n',
3265 'р': 'p',
3266 'с': 'c',
3267 'т': 'o',
3268 'у': 'y',
3269 'ф': 'b',
3270 'х': 'x',
3271 'ц': 'n',
3272 'ч': 'n',
3273 'ш': 'w',
3274 'щ': 'w',
3275 'ъ': 'a',
3276 'ы': 'm',
3277 'ь': 'a',
3278 'э': 'e',
3279 'ю': 'm',
3280 'я': 'r'
3281};
3282
3283/**
3284 * This function adds new font metrics to default metricMap
3285 * It can also override existing metrics
3286 */
3287function setFontMetrics(fontName, metrics) {
3288 fontMetricsData[fontName] = metrics;
3289}
3290/**
3291 * This function is a convenience function for looking up information in the
3292 * metricMap table. It takes a character as a string, and a font.
3293 *
3294 * Note: the `width` property may be undefined if fontMetricsData.js wasn't
3295 * built using `Make extended_metrics`.
3296 */
3297
3298function getCharacterMetrics(character, font, mode) {
3299 if (!fontMetricsData[font]) {
3300 throw new Error("Font metrics not found for font: " + font + ".");
3301 }
3302
3303 var ch = character.charCodeAt(0);
3304 var metrics = fontMetricsData[font][ch];
3305
3306 if (!metrics && character[0] in extraCharacterMap) {
3307 ch = extraCharacterMap[character[0]].charCodeAt(0);
3308 metrics = fontMetricsData[font][ch];
3309 }
3310
3311 if (!metrics && mode === 'text') {
3312 // We don't typically have font metrics for Asian scripts.
3313 // But since we support them in text mode, we need to return
3314 // some sort of metrics.
3315 // So if the character is in a script we support but we
3316 // don't have metrics for it, just use the metrics for
3317 // the Latin capital letter M. This is close enough because
3318 // we (currently) only care about the height of the glpyh
3319 // not its width.
3320 if (supportedCodepoint(ch)) {
3321 metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M'
3322 }
3323 }
3324
3325 if (metrics) {
3326 return {
3327 depth: metrics[0],
3328 height: metrics[1],
3329 italic: metrics[2],
3330 skew: metrics[3],
3331 width: metrics[4]
3332 };
3333 }
3334}
3335var fontMetricsBySizeIndex = {};
3336/**
3337 * Get the font metrics for a given size.
3338 */
3339
3340function getGlobalMetrics(size) {
3341 var sizeIndex;
3342
3343 if (size >= 5) {
3344 sizeIndex = 0;
3345 } else if (size >= 3) {
3346 sizeIndex = 1;
3347 } else {
3348 sizeIndex = 2;
3349 }
3350
3351 if (!fontMetricsBySizeIndex[sizeIndex]) {
3352 var metrics = fontMetricsBySizeIndex[sizeIndex] = {
3353 cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18
3354 };
3355
3356 for (var key in sigmasAndXis) {
3357 if (sigmasAndXis.hasOwnProperty(key)) {
3358 metrics[key] = sigmasAndXis[key][sizeIndex];
3359 }
3360 }
3361 }
3362
3363 return fontMetricsBySizeIndex[sizeIndex];
3364}
3365
3366/**
3367 * This file contains information about the options that the Parser carries
3368 * around with it while parsing. Data is held in an `Options` object, and when
3369 * recursing, a new `Options` object can be created with the `.with*` and
3370 * `.reset` functions.
3371 */
3372var sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize].
3373// The size mappings are taken from TeX with \normalsize=10pt.
3374[1, 1, 1], // size1: [5, 5, 5] \tiny
3375[2, 1, 1], // size2: [6, 5, 5]
3376[3, 1, 1], // size3: [7, 5, 5] \scriptsize
3377[4, 2, 1], // size4: [8, 6, 5] \footnotesize
3378[5, 2, 1], // size5: [9, 6, 5] \small
3379[6, 3, 1], // size6: [10, 7, 5] \normalsize
3380[7, 4, 2], // size7: [12, 8, 6] \large
3381[8, 6, 3], // size8: [14.4, 10, 7] \Large
3382[9, 7, 6], // size9: [17.28, 12, 10] \LARGE
3383[10, 8, 7], // size10: [20.74, 14.4, 12] \huge
3384[11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE
3385];
3386var sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if
3387// you change size indexes, change that function.
33880.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488];
3389
3390var sizeAtStyle = function sizeAtStyle(size, style) {
3391 return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
3392}; // In these types, "" (empty string) means "no change".
3393
3394
3395/**
3396 * This is the main options class. It contains the current style, size, color,
3397 * and font.
3398 *
3399 * Options objects should not be modified. To create a new Options with
3400 * different properties, call a `.having*` method.
3401 */
3402class Options {
3403 // A font family applies to a group of fonts (i.e. SansSerif), while a font
3404 // represents a specific font (i.e. SansSerif Bold).
3405 // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
3406
3407 /**
3408 * The base size index.
3409 */
3410 constructor(data) {
3411 this.style = void 0;
3412 this.color = void 0;
3413 this.size = void 0;
3414 this.textSize = void 0;
3415 this.phantom = void 0;
3416 this.font = void 0;
3417 this.fontFamily = void 0;
3418 this.fontWeight = void 0;
3419 this.fontShape = void 0;
3420 this.sizeMultiplier = void 0;
3421 this.maxSize = void 0;
3422 this.minRuleThickness = void 0;
3423 this._fontMetrics = void 0;
3424 this.style = data.style;
3425 this.color = data.color;
3426 this.size = data.size || Options.BASESIZE;
3427 this.textSize = data.textSize || this.size;
3428 this.phantom = !!data.phantom;
3429 this.font = data.font || "";
3430 this.fontFamily = data.fontFamily || "";
3431 this.fontWeight = data.fontWeight || '';
3432 this.fontShape = data.fontShape || '';
3433 this.sizeMultiplier = sizeMultipliers[this.size - 1];
3434 this.maxSize = data.maxSize;
3435 this.minRuleThickness = data.minRuleThickness;
3436 this._fontMetrics = undefined;
3437 }
3438 /**
3439 * Returns a new options object with the same properties as "this". Properties
3440 * from "extension" will be copied to the new options object.
3441 */
3442
3443
3444 extend(extension) {
3445 var data = {
3446 style: this.style,
3447 size: this.size,
3448 textSize: this.textSize,
3449 color: this.color,
3450 phantom: this.phantom,
3451 font: this.font,
3452 fontFamily: this.fontFamily,
3453 fontWeight: this.fontWeight,
3454 fontShape: this.fontShape,
3455 maxSize: this.maxSize,
3456 minRuleThickness: this.minRuleThickness
3457 };
3458
3459 for (var key in extension) {
3460 if (extension.hasOwnProperty(key)) {
3461 data[key] = extension[key];
3462 }
3463 }
3464
3465 return new Options(data);
3466 }
3467 /**
3468 * Return an options object with the given style. If `this.style === style`,
3469 * returns `this`.
3470 */
3471
3472
3473 havingStyle(style) {
3474 if (this.style === style) {
3475 return this;
3476 } else {
3477 return this.extend({
3478 style: style,
3479 size: sizeAtStyle(this.textSize, style)
3480 });
3481 }
3482 }
3483 /**
3484 * Return an options object with a cramped version of the current style. If
3485 * the current style is cramped, returns `this`.
3486 */
3487
3488
3489 havingCrampedStyle() {
3490 return this.havingStyle(this.style.cramp());
3491 }
3492 /**
3493 * Return an options object with the given size and in at least `\textstyle`.
3494 * Returns `this` if appropriate.
3495 */
3496
3497
3498 havingSize(size) {
3499 if (this.size === size && this.textSize === size) {
3500 return this;
3501 } else {
3502 return this.extend({
3503 style: this.style.text(),
3504 size: size,
3505 textSize: size,
3506 sizeMultiplier: sizeMultipliers[size - 1]
3507 });
3508 }
3509 }
3510 /**
3511 * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted,
3512 * changes to at least `\textstyle`.
3513 */
3514
3515
3516 havingBaseStyle(style) {
3517 style = style || this.style.text();
3518 var wantSize = sizeAtStyle(Options.BASESIZE, style);
3519
3520 if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) {
3521 return this;
3522 } else {
3523 return this.extend({
3524 style: style,
3525 size: wantSize
3526 });
3527 }
3528 }
3529 /**
3530 * Remove the effect of sizing changes such as \Huge.
3531 * Keep the effect of the current style, such as \scriptstyle.
3532 */
3533
3534
3535 havingBaseSizing() {
3536 var size;
3537
3538 switch (this.style.id) {
3539 case 4:
3540 case 5:
3541 size = 3; // normalsize in scriptstyle
3542
3543 break;
3544
3545 case 6:
3546 case 7:
3547 size = 1; // normalsize in scriptscriptstyle
3548
3549 break;
3550
3551 default:
3552 size = 6;
3553 // normalsize in textstyle or displaystyle
3554 }
3555
3556 return this.extend({
3557 style: this.style.text(),
3558 size: size
3559 });
3560 }
3561 /**
3562 * Create a new options object with the given color.
3563 */
3564
3565
3566 withColor(color) {
3567 return this.extend({
3568 color: color
3569 });
3570 }
3571 /**
3572 * Create a new options object with "phantom" set to true.
3573 */
3574
3575
3576 withPhantom() {
3577 return this.extend({
3578 phantom: true
3579 });
3580 }
3581 /**
3582 * Creates a new options object with the given math font or old text font.
3583 * @type {[type]}
3584 */
3585
3586
3587 withFont(font) {
3588 return this.extend({
3589 font
3590 });
3591 }
3592 /**
3593 * Create a new options objects with the given fontFamily.
3594 */
3595
3596
3597 withTextFontFamily(fontFamily) {
3598 return this.extend({
3599 fontFamily,
3600 font: ""
3601 });
3602 }
3603 /**
3604 * Creates a new options object with the given font weight
3605 */
3606
3607
3608 withTextFontWeight(fontWeight) {
3609 return this.extend({
3610 fontWeight,
3611 font: ""
3612 });
3613 }
3614 /**
3615 * Creates a new options object with the given font weight
3616 */
3617
3618
3619 withTextFontShape(fontShape) {
3620 return this.extend({
3621 fontShape,
3622 font: ""
3623 });
3624 }
3625 /**
3626 * Return the CSS sizing classes required to switch from enclosing options
3627 * `oldOptions` to `this`. Returns an array of classes.
3628 */
3629
3630
3631 sizingClasses(oldOptions) {
3632 if (oldOptions.size !== this.size) {
3633 return ["sizing", "reset-size" + oldOptions.size, "size" + this.size];
3634 } else {
3635 return [];
3636 }
3637 }
3638 /**
3639 * Return the CSS sizing classes required to switch to the base size. Like
3640 * `this.havingSize(BASESIZE).sizingClasses(this)`.
3641 */
3642
3643
3644 baseSizingClasses() {
3645 if (this.size !== Options.BASESIZE) {
3646 return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE];
3647 } else {
3648 return [];
3649 }
3650 }
3651 /**
3652 * Return the font metrics for this size.
3653 */
3654
3655
3656 fontMetrics() {
3657 if (!this._fontMetrics) {
3658 this._fontMetrics = getGlobalMetrics(this.size);
3659 }
3660
3661 return this._fontMetrics;
3662 }
3663 /**
3664 * Gets the CSS color of the current options object
3665 */
3666
3667
3668 getColor() {
3669 if (this.phantom) {
3670 return "transparent";
3671 } else {
3672 return this.color;
3673 }
3674 }
3675
3676}
3677
3678Options.BASESIZE = 6;
3679
3680/**
3681 * This file does conversion between units. In particular, it provides
3682 * calculateSize to convert other units into ems.
3683 */
3684// Thus, multiplying a length by this number converts the length from units
3685// into pts. Dividing the result by ptPerEm gives the number of ems
3686// *assuming* a font size of ptPerEm (normal size, normal style).
3687
3688var ptPerUnit = {
3689 // https://en.wikibooks.org/wiki/LaTeX/Lengths and
3690 // https://tex.stackexchange.com/a/8263
3691 "pt": 1,
3692 // TeX point
3693 "mm": 7227 / 2540,
3694 // millimeter
3695 "cm": 7227 / 254,
3696 // centimeter
3697 "in": 72.27,
3698 // inch
3699 "bp": 803 / 800,
3700 // big (PostScript) points
3701 "pc": 12,
3702 // pica
3703 "dd": 1238 / 1157,
3704 // didot
3705 "cc": 14856 / 1157,
3706 // cicero (12 didot)
3707 "nd": 685 / 642,
3708 // new didot
3709 "nc": 1370 / 107,
3710 // new cicero (12 new didot)
3711 "sp": 1 / 65536,
3712 // scaled point (TeX's internal smallest unit)
3713 // https://tex.stackexchange.com/a/41371
3714 "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX
3715
3716}; // Dictionary of relative units, for fast validity testing.
3717
3718var relativeUnit = {
3719 "ex": true,
3720 "em": true,
3721 "mu": true
3722};
3723
3724/**
3725 * Determine whether the specified unit (either a string defining the unit
3726 * or a "size" parse node containing a unit field) is valid.
3727 */
3728var validUnit = function validUnit(unit) {
3729 if (typeof unit !== "string") {
3730 unit = unit.unit;
3731 }
3732
3733 return unit in ptPerUnit || unit in relativeUnit || unit === "ex";
3734};
3735/*
3736 * Convert a "size" parse node (with numeric "number" and string "unit" fields,
3737 * as parsed by functions.js argType "size") into a CSS em value for the
3738 * current style/scale. `options` gives the current options.
3739 */
3740
3741var calculateSize = function calculateSize(sizeValue, options) {
3742 var scale;
3743
3744 if (sizeValue.unit in ptPerUnit) {
3745 // Absolute units
3746 scale = ptPerUnit[sizeValue.unit] // Convert unit to pt
3747 / options.fontMetrics().ptPerEm // Convert pt to CSS em
3748 / options.sizeMultiplier; // Unscale to make absolute units
3749 } else if (sizeValue.unit === "mu") {
3750 // `mu` units scale with scriptstyle/scriptscriptstyle.
3751 scale = options.fontMetrics().cssEmPerMu;
3752 } else {
3753 // Other relative units always refer to the *textstyle* font
3754 // in the current size.
3755 var unitOptions;
3756
3757 if (options.style.isTight()) {
3758 // isTight() means current style is script/scriptscript.
3759 unitOptions = options.havingStyle(options.style.text());
3760 } else {
3761 unitOptions = options;
3762 } // TODO: In TeX these units are relative to the quad of the current
3763 // *text* font, e.g. cmr10. KaTeX instead uses values from the
3764 // comparably-sized *Computer Modern symbol* font. At 10pt, these
3765 // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641;
3766 // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$.
3767 // TeX \showlists shows a kern of 1.13889 * fontsize;
3768 // KaTeX shows a kern of 1.171 * fontsize.
3769
3770
3771 if (sizeValue.unit === "ex") {
3772 scale = unitOptions.fontMetrics().xHeight;
3773 } else if (sizeValue.unit === "em") {
3774 scale = unitOptions.fontMetrics().quad;
3775 } else {
3776 throw new ParseError("Invalid unit: '" + sizeValue.unit + "'");
3777 }
3778
3779 if (unitOptions !== options) {
3780 scale *= unitOptions.sizeMultiplier / options.sizeMultiplier;
3781 }
3782 }
3783
3784 return Math.min(sizeValue.number * scale, options.maxSize);
3785};
3786/**
3787 * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. See
3788 * https://github.com/KaTeX/KaTeX/pull/2460.
3789 */
3790
3791var makeEm = function makeEm(n) {
3792 return +n.toFixed(4) + "em";
3793};
3794
3795/**
3796 * These objects store the data about the DOM nodes we create, as well as some
3797 * extra data. They can then be transformed into real DOM nodes with the
3798 * `toNode` function or HTML markup using `toMarkup`. They are useful for both
3799 * storing extra properties on the nodes, as well as providing a way to easily
3800 * work with the DOM.
3801 *
3802 * Similar functions for working with MathML nodes exist in mathMLTree.js.
3803 *
3804 * TODO: refactor `span` and `anchor` into common superclass when
3805 * target environments support class inheritance
3806 */
3807
3808/**
3809 * Create an HTML className based on a list of classes. In addition to joining
3810 * with spaces, we also remove empty classes.
3811 */
3812var createClass = function createClass(classes) {
3813 return classes.filter(cls => cls).join(" ");
3814};
3815
3816var initNode = function initNode(classes, options, style) {
3817 this.classes = classes || [];
3818 this.attributes = {};
3819 this.height = 0;
3820 this.depth = 0;
3821 this.maxFontSize = 0;
3822 this.style = style || {};
3823
3824 if (options) {
3825 if (options.style.isTight()) {
3826 this.classes.push("mtight");
3827 }
3828
3829 var color = options.getColor();
3830
3831 if (color) {
3832 this.style.color = color;
3833 }
3834 }
3835};
3836/**
3837 * Convert into an HTML node
3838 */
3839
3840
3841var toNode = function toNode(tagName) {
3842 var node = document.createElement(tagName); // Apply the class
3843
3844 node.className = createClass(this.classes); // Apply inline styles
3845
3846 for (var style in this.style) {
3847 if (this.style.hasOwnProperty(style)) {
3848 // $FlowFixMe Flow doesn't seem to understand span.style's type.
3849 node.style[style] = this.style[style];
3850 }
3851 } // Apply attributes
3852
3853
3854 for (var attr in this.attributes) {
3855 if (this.attributes.hasOwnProperty(attr)) {
3856 node.setAttribute(attr, this.attributes[attr]);
3857 }
3858 } // Append the children, also as HTML nodes
3859
3860
3861 for (var i = 0; i < this.children.length; i++) {
3862 node.appendChild(this.children[i].toNode());
3863 }
3864
3865 return node;
3866};
3867/**
3868 * Convert into an HTML markup string
3869 */
3870
3871
3872var toMarkup = function toMarkup(tagName) {
3873 var markup = "<" + tagName; // Add the class
3874
3875 if (this.classes.length) {
3876 markup += " class=\"" + utils.escape(createClass(this.classes)) + "\"";
3877 }
3878
3879 var styles = ""; // Add the styles, after hyphenation
3880
3881 for (var style in this.style) {
3882 if (this.style.hasOwnProperty(style)) {
3883 styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
3884 }
3885 }
3886
3887 if (styles) {
3888 markup += " style=\"" + utils.escape(styles) + "\"";
3889 } // Add the attributes
3890
3891
3892 for (var attr in this.attributes) {
3893 if (this.attributes.hasOwnProperty(attr)) {
3894 markup += " " + attr + "=\"" + utils.escape(this.attributes[attr]) + "\"";
3895 }
3896 }
3897
3898 markup += ">"; // Add the markup of the children, also as markup
3899
3900 for (var i = 0; i < this.children.length; i++) {
3901 markup += this.children[i].toMarkup();
3902 }
3903
3904 markup += "</" + tagName + ">";
3905 return markup;
3906}; // Making the type below exact with all optional fields doesn't work due to
3907// - https://github.com/facebook/flow/issues/4582
3908// - https://github.com/facebook/flow/issues/5688
3909// However, since *all* fields are optional, $Shape<> works as suggested in 5688
3910// above.
3911// This type does not include all CSS properties. Additional properties should
3912// be added as needed.
3913
3914
3915/**
3916 * This node represents a span node, with a className, a list of children, and
3917 * an inline style. It also contains information about its height, depth, and
3918 * maxFontSize.
3919 *
3920 * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan
3921 * otherwise. This typesafety is important when HTML builders access a span's
3922 * children.
3923 */
3924class Span {
3925 constructor(classes, children, options, style) {
3926 this.children = void 0;
3927 this.attributes = void 0;
3928 this.classes = void 0;
3929 this.height = void 0;
3930 this.depth = void 0;
3931 this.width = void 0;
3932 this.maxFontSize = void 0;
3933 this.style = void 0;
3934 initNode.call(this, classes, options, style);
3935 this.children = children || [];
3936 }
3937 /**
3938 * Sets an arbitrary attribute on the span. Warning: use this wisely. Not
3939 * all browsers support attributes the same, and having too many custom
3940 * attributes is probably bad.
3941 */
3942
3943
3944 setAttribute(attribute, value) {
3945 this.attributes[attribute] = value;
3946 }
3947
3948 hasClass(className) {
3949 return utils.contains(this.classes, className);
3950 }
3951
3952 toNode() {
3953 return toNode.call(this, "span");
3954 }
3955
3956 toMarkup() {
3957 return toMarkup.call(this, "span");
3958 }
3959
3960}
3961/**
3962 * This node represents an anchor (<a>) element with a hyperlink. See `span`
3963 * for further details.
3964 */
3965
3966class Anchor {
3967 constructor(href, classes, children, options) {
3968 this.children = void 0;
3969 this.attributes = void 0;
3970 this.classes = void 0;
3971 this.height = void 0;
3972 this.depth = void 0;
3973 this.maxFontSize = void 0;
3974 this.style = void 0;
3975 initNode.call(this, classes, options);
3976 this.children = children || [];
3977 this.setAttribute('href', href);
3978 }
3979
3980 setAttribute(attribute, value) {
3981 this.attributes[attribute] = value;
3982 }
3983
3984 hasClass(className) {
3985 return utils.contains(this.classes, className);
3986 }
3987
3988 toNode() {
3989 return toNode.call(this, "a");
3990 }
3991
3992 toMarkup() {
3993 return toMarkup.call(this, "a");
3994 }
3995
3996}
3997/**
3998 * This node represents an image embed (<img>) element.
3999 */
4000
4001class Img {
4002 constructor(src, alt, style) {
4003 this.src = void 0;
4004 this.alt = void 0;
4005 this.classes = void 0;
4006 this.height = void 0;
4007 this.depth = void 0;
4008 this.maxFontSize = void 0;
4009 this.style = void 0;
4010 this.alt = alt;
4011 this.src = src;
4012 this.classes = ["mord"];
4013 this.style = style;
4014 }
4015
4016 hasClass(className) {
4017 return utils.contains(this.classes, className);
4018 }
4019
4020 toNode() {
4021 var node = document.createElement("img");
4022 node.src = this.src;
4023 node.alt = this.alt;
4024 node.className = "mord"; // Apply inline styles
4025
4026 for (var style in this.style) {
4027 if (this.style.hasOwnProperty(style)) {
4028 // $FlowFixMe
4029 node.style[style] = this.style[style];
4030 }
4031 }
4032
4033 return node;
4034 }
4035
4036 toMarkup() {
4037 var markup = "<img src='" + this.src + " 'alt='" + this.alt + "' "; // Add the styles, after hyphenation
4038
4039 var styles = "";
4040
4041 for (var style in this.style) {
4042 if (this.style.hasOwnProperty(style)) {
4043 styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
4044 }
4045 }
4046
4047 if (styles) {
4048 markup += " style=\"" + utils.escape(styles) + "\"";
4049 }
4050
4051 markup += "'/>";
4052 return markup;
4053 }
4054
4055}
4056var iCombinations = {
4057 'î': '\u0131\u0302',
4058 'ï': '\u0131\u0308',
4059 'í': '\u0131\u0301',
4060 // 'ī': '\u0131\u0304', // enable when we add Extended Latin
4061 'ì': '\u0131\u0300'
4062};
4063/**
4064 * A symbol node contains information about a single symbol. It either renders
4065 * to a single text node, or a span with a single text node in it, depending on
4066 * whether it has CSS classes, styles, or needs italic correction.
4067 */
4068
4069class SymbolNode {
4070 constructor(text, height, depth, italic, skew, width, classes, style) {
4071 this.text = void 0;
4072 this.height = void 0;
4073 this.depth = void 0;
4074 this.italic = void 0;
4075 this.skew = void 0;
4076 this.width = void 0;
4077 this.maxFontSize = void 0;
4078 this.classes = void 0;
4079 this.style = void 0;
4080 this.text = text;
4081 this.height = height || 0;
4082 this.depth = depth || 0;
4083 this.italic = italic || 0;
4084 this.skew = skew || 0;
4085 this.width = width || 0;
4086 this.classes = classes || [];
4087 this.style = style || {};
4088 this.maxFontSize = 0; // Mark text from non-Latin scripts with specific classes so that we
4089 // can specify which fonts to use. This allows us to render these
4090 // characters with a serif font in situations where the browser would
4091 // either default to a sans serif or render a placeholder character.
4092 // We use CSS class names like cjk_fallback, hangul_fallback and
4093 // brahmic_fallback. See ./unicodeScripts.js for the set of possible
4094 // script names
4095
4096 var script = scriptFromCodepoint(this.text.charCodeAt(0));
4097
4098 if (script) {
4099 this.classes.push(script + "_fallback");
4100 }
4101
4102 if (/[îïíì]/.test(this.text)) {
4103 // add ī when we add Extended Latin
4104 this.text = iCombinations[this.text];
4105 }
4106 }
4107
4108 hasClass(className) {
4109 return utils.contains(this.classes, className);
4110 }
4111 /**
4112 * Creates a text node or span from a symbol node. Note that a span is only
4113 * created if it is needed.
4114 */
4115
4116
4117 toNode() {
4118 var node = document.createTextNode(this.text);
4119 var span = null;
4120
4121 if (this.italic > 0) {
4122 span = document.createElement("span");
4123 span.style.marginRight = makeEm(this.italic);
4124 }
4125
4126 if (this.classes.length > 0) {
4127 span = span || document.createElement("span");
4128 span.className = createClass(this.classes);
4129 }
4130
4131 for (var style in this.style) {
4132 if (this.style.hasOwnProperty(style)) {
4133 span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type.
4134
4135 span.style[style] = this.style[style];
4136 }
4137 }
4138
4139 if (span) {
4140 span.appendChild(node);
4141 return span;
4142 } else {
4143 return node;
4144 }
4145 }
4146 /**
4147 * Creates markup for a symbol node.
4148 */
4149
4150
4151 toMarkup() {
4152 // TODO(alpert): More duplication than I'd like from
4153 // span.prototype.toMarkup and symbolNode.prototype.toNode...
4154 var needsSpan = false;
4155 var markup = "<span";
4156
4157 if (this.classes.length) {
4158 needsSpan = true;
4159 markup += " class=\"";
4160 markup += utils.escape(createClass(this.classes));
4161 markup += "\"";
4162 }
4163
4164 var styles = "";
4165
4166 if (this.italic > 0) {
4167 styles += "margin-right:" + this.italic + "em;";
4168 }
4169
4170 for (var style in this.style) {
4171 if (this.style.hasOwnProperty(style)) {
4172 styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
4173 }
4174 }
4175
4176 if (styles) {
4177 needsSpan = true;
4178 markup += " style=\"" + utils.escape(styles) + "\"";
4179 }
4180
4181 var escaped = utils.escape(this.text);
4182
4183 if (needsSpan) {
4184 markup += ">";
4185 markup += escaped;
4186 markup += "</span>";
4187 return markup;
4188 } else {
4189 return escaped;
4190 }
4191 }
4192
4193}
4194/**
4195 * SVG nodes are used to render stretchy wide elements.
4196 */
4197
4198class SvgNode {
4199 constructor(children, attributes) {
4200 this.children = void 0;
4201 this.attributes = void 0;
4202 this.children = children || [];
4203 this.attributes = attributes || {};
4204 }
4205
4206 toNode() {
4207 var svgNS = "http://www.w3.org/2000/svg";
4208 var node = document.createElementNS(svgNS, "svg"); // Apply attributes
4209
4210 for (var attr in this.attributes) {
4211 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
4212 node.setAttribute(attr, this.attributes[attr]);
4213 }
4214 }
4215
4216 for (var i = 0; i < this.children.length; i++) {
4217 node.appendChild(this.children[i].toNode());
4218 }
4219
4220 return node;
4221 }
4222
4223 toMarkup() {
4224 var markup = "<svg xmlns=\"http://www.w3.org/2000/svg\""; // Apply attributes
4225
4226 for (var attr in this.attributes) {
4227 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
4228 markup += " " + attr + "='" + this.attributes[attr] + "'";
4229 }
4230 }
4231
4232 markup += ">";
4233
4234 for (var i = 0; i < this.children.length; i++) {
4235 markup += this.children[i].toMarkup();
4236 }
4237
4238 markup += "</svg>";
4239 return markup;
4240 }
4241
4242}
4243class PathNode {
4244 constructor(pathName, alternate) {
4245 this.pathName = void 0;
4246 this.alternate = void 0;
4247 this.pathName = pathName;
4248 this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims
4249 }
4250
4251 toNode() {
4252 var svgNS = "http://www.w3.org/2000/svg";
4253 var node = document.createElementNS(svgNS, "path");
4254
4255 if (this.alternate) {
4256 node.setAttribute("d", this.alternate);
4257 } else {
4258 node.setAttribute("d", path[this.pathName]);
4259 }
4260
4261 return node;
4262 }
4263
4264 toMarkup() {
4265 if (this.alternate) {
4266 return "<path d='" + this.alternate + "'/>";
4267 } else {
4268 return "<path d='" + path[this.pathName] + "'/>";
4269 }
4270 }
4271
4272}
4273class LineNode {
4274 constructor(attributes) {
4275 this.attributes = void 0;
4276 this.attributes = attributes || {};
4277 }
4278
4279 toNode() {
4280 var svgNS = "http://www.w3.org/2000/svg";
4281 var node = document.createElementNS(svgNS, "line"); // Apply attributes
4282
4283 for (var attr in this.attributes) {
4284 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
4285 node.setAttribute(attr, this.attributes[attr]);
4286 }
4287 }
4288
4289 return node;
4290 }
4291
4292 toMarkup() {
4293 var markup = "<line";
4294
4295 for (var attr in this.attributes) {
4296 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
4297 markup += " " + attr + "='" + this.attributes[attr] + "'";
4298 }
4299 }
4300
4301 markup += "/>";
4302 return markup;
4303 }
4304
4305}
4306function assertSymbolDomNode(group) {
4307 if (group instanceof SymbolNode) {
4308 return group;
4309 } else {
4310 throw new Error("Expected symbolNode but got " + String(group) + ".");
4311 }
4312}
4313function assertSpan(group) {
4314 if (group instanceof Span) {
4315 return group;
4316 } else {
4317 throw new Error("Expected span<HtmlDomNode> but got " + String(group) + ".");
4318 }
4319}
4320
4321/**
4322 * This file holds a list of all no-argument functions and single-character
4323 * symbols (like 'a' or ';').
4324 *
4325 * For each of the symbols, there are three properties they can have:
4326 * - font (required): the font to be used for this symbol. Either "main" (the
4327 normal font), or "ams" (the ams fonts).
4328 * - group (required): the ParseNode group type the symbol should have (i.e.
4329 "textord", "mathord", etc).
4330 See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types
4331 * - replace: the character that this symbol or function should be
4332 * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
4333 * character in the main font).
4334 *
4335 * The outermost map in the table indicates what mode the symbols should be
4336 * accepted in (e.g. "math" or "text").
4337 */
4338// Some of these have a "-token" suffix since these are also used as `ParseNode`
4339// types for raw text tokens, and we want to avoid conflicts with higher-level
4340// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
4341// looking up the `symbols` map.
4342var ATOMS = {
4343 "bin": 1,
4344 "close": 1,
4345 "inner": 1,
4346 "open": 1,
4347 "punct": 1,
4348 "rel": 1
4349};
4350var NON_ATOMS = {
4351 "accent-token": 1,
4352 "mathord": 1,
4353 "op-token": 1,
4354 "spacing": 1,
4355 "textord": 1
4356};
4357var symbols = {
4358 "math": {},
4359 "text": {}
4360};
4361/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
4362
4363function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) {
4364 symbols[mode][name] = {
4365 font,
4366 group,
4367 replace
4368 };
4369
4370 if (acceptUnicodeChar && replace) {
4371 symbols[mode][replace] = symbols[mode][name];
4372 }
4373} // Some abbreviations for commonly used strings.
4374// This helps minify the code, and also spotting typos using jshint.
4375// modes:
4376
4377var math = "math";
4378var text = "text"; // fonts:
4379
4380var main = "main";
4381var ams = "ams"; // groups:
4382
4383var accent = "accent-token";
4384var bin = "bin";
4385var close = "close";
4386var inner = "inner";
4387var mathord = "mathord";
4388var op = "op-token";
4389var open = "open";
4390var punct = "punct";
4391var rel = "rel";
4392var spacing = "spacing";
4393var textord = "textord"; // Now comes the symbol table
4394// Relation Symbols
4395
4396defineSymbol(math, main, rel, "\u2261", "\\equiv", true);
4397defineSymbol(math, main, rel, "\u227a", "\\prec", true);
4398defineSymbol(math, main, rel, "\u227b", "\\succ", true);
4399defineSymbol(math, main, rel, "\u223c", "\\sim", true);
4400defineSymbol(math, main, rel, "\u22a5", "\\perp");
4401defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true);
4402defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true);
4403defineSymbol(math, main, rel, "\u2243", "\\simeq", true);
4404defineSymbol(math, main, rel, "\u2223", "\\mid", true);
4405defineSymbol(math, main, rel, "\u226a", "\\ll", true);
4406defineSymbol(math, main, rel, "\u226b", "\\gg", true);
4407defineSymbol(math, main, rel, "\u224d", "\\asymp", true);
4408defineSymbol(math, main, rel, "\u2225", "\\parallel");
4409defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true);
4410defineSymbol(math, main, rel, "\u2323", "\\smile", true);
4411defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true);
4412defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true);
4413defineSymbol(math, main, rel, "\u2250", "\\doteq", true);
4414defineSymbol(math, main, rel, "\u2322", "\\frown", true);
4415defineSymbol(math, main, rel, "\u220b", "\\ni", true);
4416defineSymbol(math, main, rel, "\u221d", "\\propto", true);
4417defineSymbol(math, main, rel, "\u22a2", "\\vdash", true);
4418defineSymbol(math, main, rel, "\u22a3", "\\dashv", true);
4419defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation
4420
4421defineSymbol(math, main, punct, "\u002e", "\\ldotp");
4422defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols
4423
4424defineSymbol(math, main, textord, "\u0023", "\\#");
4425defineSymbol(text, main, textord, "\u0023", "\\#");
4426defineSymbol(math, main, textord, "\u0026", "\\&");
4427defineSymbol(text, main, textord, "\u0026", "\\&");
4428defineSymbol(math, main, textord, "\u2135", "\\aleph", true);
4429defineSymbol(math, main, textord, "\u2200", "\\forall", true);
4430defineSymbol(math, main, textord, "\u210f", "\\hbar", true);
4431defineSymbol(math, main, textord, "\u2203", "\\exists", true);
4432defineSymbol(math, main, textord, "\u2207", "\\nabla", true);
4433defineSymbol(math, main, textord, "\u266d", "\\flat", true);
4434defineSymbol(math, main, textord, "\u2113", "\\ell", true);
4435defineSymbol(math, main, textord, "\u266e", "\\natural", true);
4436defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true);
4437defineSymbol(math, main, textord, "\u2118", "\\wp", true);
4438defineSymbol(math, main, textord, "\u266f", "\\sharp", true);
4439defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true);
4440defineSymbol(math, main, textord, "\u211c", "\\Re", true);
4441defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true);
4442defineSymbol(math, main, textord, "\u2111", "\\Im", true);
4443defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true);
4444defineSymbol(math, main, textord, "\u00a7", "\\S", true);
4445defineSymbol(text, main, textord, "\u00a7", "\\S");
4446defineSymbol(math, main, textord, "\u00b6", "\\P", true);
4447defineSymbol(text, main, textord, "\u00b6", "\\P"); // Math and Text
4448
4449defineSymbol(math, main, textord, "\u2020", "\\dag");
4450defineSymbol(text, main, textord, "\u2020", "\\dag");
4451defineSymbol(text, main, textord, "\u2020", "\\textdagger");
4452defineSymbol(math, main, textord, "\u2021", "\\ddag");
4453defineSymbol(text, main, textord, "\u2021", "\\ddag");
4454defineSymbol(text, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters
4455
4456defineSymbol(math, main, close, "\u23b1", "\\rmoustache", true);
4457defineSymbol(math, main, open, "\u23b0", "\\lmoustache", true);
4458defineSymbol(math, main, close, "\u27ef", "\\rgroup", true);
4459defineSymbol(math, main, open, "\u27ee", "\\lgroup", true); // Binary Operators
4460
4461defineSymbol(math, main, bin, "\u2213", "\\mp", true);
4462defineSymbol(math, main, bin, "\u2296", "\\ominus", true);
4463defineSymbol(math, main, bin, "\u228e", "\\uplus", true);
4464defineSymbol(math, main, bin, "\u2293", "\\sqcap", true);
4465defineSymbol(math, main, bin, "\u2217", "\\ast");
4466defineSymbol(math, main, bin, "\u2294", "\\sqcup", true);
4467defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true);
4468defineSymbol(math, main, bin, "\u2219", "\\bullet", true);
4469defineSymbol(math, main, bin, "\u2021", "\\ddagger");
4470defineSymbol(math, main, bin, "\u2240", "\\wr", true);
4471defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
4472defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath
4473// Arrow Symbols
4474
4475defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true);
4476defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true);
4477defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true);
4478defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true);
4479defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true);
4480defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true);
4481defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true);
4482defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true);
4483defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true);
4484defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true);
4485defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true);
4486defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true);
4487defineSymbol(math, main, rel, "\u2197", "\\nearrow", true);
4488defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true);
4489defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true);
4490defineSymbol(math, main, rel, "\u2198", "\\searrow", true);
4491defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true);
4492defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true);
4493defineSymbol(math, main, rel, "\u2199", "\\swarrow", true);
4494defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true);
4495defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true);
4496defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true);
4497defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations
4498
4499defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceeded by "@" each have a corresponding macro.
4500
4501defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant");
4502defineSymbol(math, ams, rel, "\ue011", "\\@nleqq");
4503defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true);
4504defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true);
4505defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq");
4506defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true);
4507defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true);
4508defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym.
4509
4510defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true);
4511defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true);
4512defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true);
4513defineSymbol(math, ams, rel, "\u2241", "\\nsim", true);
4514defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid");
4515defineSymbol(math, ams, rel, "\u2224", "\\nmid", true);
4516defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true);
4517defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true);
4518defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
4519defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true);
4520defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true);
4521defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq");
4522defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true);
4523defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq");
4524defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true);
4525defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant");
4526defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq");
4527defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true);
4528defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true);
4529defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq");
4530defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true);
4531defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true);
4532defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym.
4533
4534defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true);
4535defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true);
4536defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym.
4537
4538defineSymbol(math, ams, rel, "\u2246", "\\ncong", true);
4539defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel");
4540defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true);
4541defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true);
4542defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
4543defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true);
4544defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq");
4545defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true);
4546defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq");
4547defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true);
4548defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq");
4549defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true);
4550defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true);
4551defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true);
4552defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq");
4553defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
4554defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows
4555
4556defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true);
4557defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true);
4558defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true);
4559defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true);
4560defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true);
4561defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc
4562
4563defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
4564defineSymbol(math, ams, textord, "\u210f", "\\hslash");
4565defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
4566defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
4567defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
4568defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
4569defineSymbol(text, ams, textord, "\u00ae", "\\circledR");
4570defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true);
4571defineSymbol(math, ams, textord, "\u2204", "\\nexists");
4572defineSymbol(math, ams, textord, "\u2127", "\\mho");
4573defineSymbol(math, ams, textord, "\u2132", "\\Finv", true);
4574defineSymbol(math, ams, textord, "\u2141", "\\Game", true);
4575defineSymbol(math, ams, textord, "\u2035", "\\backprime");
4576defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
4577defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
4578defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
4579defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
4580defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
4581defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true);
4582defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 to \matheth. We map to AMS function \eth
4583
4584defineSymbol(math, ams, textord, "\u00f0", "\\eth", true);
4585defineSymbol(text, main, textord, "\u00f0", "\u00f0");
4586defineSymbol(math, ams, textord, "\u2571", "\\diagup");
4587defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
4588defineSymbol(math, ams, textord, "\u25a1", "\\square");
4589defineSymbol(math, ams, textord, "\u25a1", "\\Box");
4590defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen
4591
4592defineSymbol(math, ams, textord, "\u00a5", "\\yen", true);
4593defineSymbol(text, ams, textord, "\u00a5", "\\yen", true);
4594defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true);
4595defineSymbol(text, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew
4596
4597defineSymbol(math, ams, textord, "\u2136", "\\beth", true);
4598defineSymbol(math, ams, textord, "\u2138", "\\daleth", true);
4599defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek
4600
4601defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true);
4602defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters
4603
4604defineSymbol(math, ams, open, "\u250c", "\\@ulcorner", true);
4605defineSymbol(math, ams, close, "\u2510", "\\@urcorner", true);
4606defineSymbol(math, ams, open, "\u2514", "\\@llcorner", true);
4607defineSymbol(math, ams, close, "\u2518", "\\@lrcorner", true); // AMS Binary Relations
4608
4609defineSymbol(math, ams, rel, "\u2266", "\\leqq", true);
4610defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true);
4611defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true);
4612defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true);
4613defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true);
4614defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true);
4615defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
4616defineSymbol(math, ams, rel, "\u22d8", "\\lll", true);
4617defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true);
4618defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true);
4619defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true);
4620defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
4621defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true);
4622defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true);
4623defineSymbol(math, ams, rel, "\u223d", "\\backsim", true);
4624defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true);
4625defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true);
4626defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true);
4627defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true);
4628defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true);
4629defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true);
4630defineSymbol(math, ams, rel, "\u227e", "\\precsim", true);
4631defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true);
4632defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
4633defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
4634defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true);
4635defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true);
4636defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
4637defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
4638defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true);
4639defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true);
4640defineSymbol(math, ams, rel, "\u2267", "\\geqq", true);
4641defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true);
4642defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true);
4643defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true);
4644defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true);
4645defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
4646defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true);
4647defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true);
4648defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true);
4649defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true);
4650defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true);
4651defineSymbol(math, ams, rel, "\u2257", "\\circeq", true);
4652defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true);
4653defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
4654defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
4655defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true);
4656defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true);
4657defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true);
4658defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true);
4659defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true);
4660defineSymbol(math, ams, rel, "\u227f", "\\succsim", true);
4661defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true);
4662defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
4663defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
4664defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true);
4665defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
4666defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
4667defineSymbol(math, ams, rel, "\u226c", "\\between", true);
4668defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true);
4669defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
4670defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom.
4671// We kept the amssymb atom type, which is rel.
4672
4673defineSymbol(math, ams, rel, "\u2234", "\\therefore", true);
4674defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
4675defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom.
4676// We kept the amssymb atom type, which is rel.
4677
4678defineSymbol(math, ams, rel, "\u2235", "\\because", true);
4679defineSymbol(math, ams, rel, "\u22d8", "\\llless");
4680defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
4681defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
4682defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
4683defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true);
4684defineSymbol(math, main, rel, "\u22c8", "\\Join");
4685defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators
4686
4687defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true);
4688defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
4689defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true);
4690defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true);
4691defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true);
4692defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true);
4693defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true);
4694defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true);
4695defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true);
4696defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true);
4697defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true);
4698defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true);
4699defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true);
4700defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true);
4701defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true);
4702defineSymbol(math, ams, bin, "\u229b", "\\circledast", true);
4703defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
4704defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true);
4705defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
4706defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
4707defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows
4708// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
4709// We'll map it to AMS function \dashrightarrow. It produces the same atom.
4710
4711defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym.
4712
4713defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true);
4714defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true);
4715defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true);
4716defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true);
4717defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true);
4718defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true);
4719defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true);
4720defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true);
4721defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym.
4722
4723defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true);
4724defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true);
4725defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true);
4726defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true);
4727defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true);
4728defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font
4729
4730defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font
4731
4732defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true);
4733defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true);
4734defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true);
4735defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true);
4736defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true);
4737defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true);
4738defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true);
4739defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym.
4740
4741defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true);
4742defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true);
4743defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true);
4744defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true);
4745defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true);
4746defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true);
4747defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
4748defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true);
4749defineSymbol(math, ams, rel, "\u21be", "\\restriction");
4750defineSymbol(math, main, textord, "\u2018", "`");
4751defineSymbol(math, main, textord, "$", "\\$");
4752defineSymbol(text, main, textord, "$", "\\$");
4753defineSymbol(text, main, textord, "$", "\\textdollar");
4754defineSymbol(math, main, textord, "%", "\\%");
4755defineSymbol(text, main, textord, "%", "\\%");
4756defineSymbol(math, main, textord, "_", "\\_");
4757defineSymbol(text, main, textord, "_", "\\_");
4758defineSymbol(text, main, textord, "_", "\\textunderscore");
4759defineSymbol(math, main, textord, "\u2220", "\\angle", true);
4760defineSymbol(math, main, textord, "\u221e", "\\infty", true);
4761defineSymbol(math, main, textord, "\u2032", "\\prime");
4762defineSymbol(math, main, textord, "\u25b3", "\\triangle");
4763defineSymbol(math, main, textord, "\u0393", "\\Gamma", true);
4764defineSymbol(math, main, textord, "\u0394", "\\Delta", true);
4765defineSymbol(math, main, textord, "\u0398", "\\Theta", true);
4766defineSymbol(math, main, textord, "\u039b", "\\Lambda", true);
4767defineSymbol(math, main, textord, "\u039e", "\\Xi", true);
4768defineSymbol(math, main, textord, "\u03a0", "\\Pi", true);
4769defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true);
4770defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true);
4771defineSymbol(math, main, textord, "\u03a6", "\\Phi", true);
4772defineSymbol(math, main, textord, "\u03a8", "\\Psi", true);
4773defineSymbol(math, main, textord, "\u03a9", "\\Omega", true);
4774defineSymbol(math, main, textord, "A", "\u0391");
4775defineSymbol(math, main, textord, "B", "\u0392");
4776defineSymbol(math, main, textord, "E", "\u0395");
4777defineSymbol(math, main, textord, "Z", "\u0396");
4778defineSymbol(math, main, textord, "H", "\u0397");
4779defineSymbol(math, main, textord, "I", "\u0399");
4780defineSymbol(math, main, textord, "K", "\u039A");
4781defineSymbol(math, main, textord, "M", "\u039C");
4782defineSymbol(math, main, textord, "N", "\u039D");
4783defineSymbol(math, main, textord, "O", "\u039F");
4784defineSymbol(math, main, textord, "P", "\u03A1");
4785defineSymbol(math, main, textord, "T", "\u03A4");
4786defineSymbol(math, main, textord, "X", "\u03A7");
4787defineSymbol(math, main, textord, "\u00ac", "\\neg", true);
4788defineSymbol(math, main, textord, "\u00ac", "\\lnot");
4789defineSymbol(math, main, textord, "\u22a4", "\\top");
4790defineSymbol(math, main, textord, "\u22a5", "\\bot");
4791defineSymbol(math, main, textord, "\u2205", "\\emptyset");
4792defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
4793defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true);
4794defineSymbol(math, main, mathord, "\u03b2", "\\beta", true);
4795defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true);
4796defineSymbol(math, main, mathord, "\u03b4", "\\delta", true);
4797defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true);
4798defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true);
4799defineSymbol(math, main, mathord, "\u03b7", "\\eta", true);
4800defineSymbol(math, main, mathord, "\u03b8", "\\theta", true);
4801defineSymbol(math, main, mathord, "\u03b9", "\\iota", true);
4802defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true);
4803defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true);
4804defineSymbol(math, main, mathord, "\u03bc", "\\mu", true);
4805defineSymbol(math, main, mathord, "\u03bd", "\\nu", true);
4806defineSymbol(math, main, mathord, "\u03be", "\\xi", true);
4807defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true);
4808defineSymbol(math, main, mathord, "\u03c0", "\\pi", true);
4809defineSymbol(math, main, mathord, "\u03c1", "\\rho", true);
4810defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true);
4811defineSymbol(math, main, mathord, "\u03c4", "\\tau", true);
4812defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true);
4813defineSymbol(math, main, mathord, "\u03d5", "\\phi", true);
4814defineSymbol(math, main, mathord, "\u03c7", "\\chi", true);
4815defineSymbol(math, main, mathord, "\u03c8", "\\psi", true);
4816defineSymbol(math, main, mathord, "\u03c9", "\\omega", true);
4817defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true);
4818defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true);
4819defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true);
4820defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true);
4821defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true);
4822defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true);
4823defineSymbol(math, main, bin, "\u2217", "*", true);
4824defineSymbol(math, main, bin, "+", "+");
4825defineSymbol(math, main, bin, "\u2212", "-", true);
4826defineSymbol(math, main, bin, "\u22c5", "\\cdot", true);
4827defineSymbol(math, main, bin, "\u2218", "\\circ", true);
4828defineSymbol(math, main, bin, "\u00f7", "\\div", true);
4829defineSymbol(math, main, bin, "\u00b1", "\\pm", true);
4830defineSymbol(math, main, bin, "\u00d7", "\\times", true);
4831defineSymbol(math, main, bin, "\u2229", "\\cap", true);
4832defineSymbol(math, main, bin, "\u222a", "\\cup", true);
4833defineSymbol(math, main, bin, "\u2216", "\\setminus", true);
4834defineSymbol(math, main, bin, "\u2227", "\\land");
4835defineSymbol(math, main, bin, "\u2228", "\\lor");
4836defineSymbol(math, main, bin, "\u2227", "\\wedge", true);
4837defineSymbol(math, main, bin, "\u2228", "\\vee", true);
4838defineSymbol(math, main, textord, "\u221a", "\\surd");
4839defineSymbol(math, main, open, "\u27e8", "\\langle", true);
4840defineSymbol(math, main, open, "\u2223", "\\lvert");
4841defineSymbol(math, main, open, "\u2225", "\\lVert");
4842defineSymbol(math, main, close, "?", "?");
4843defineSymbol(math, main, close, "!", "!");
4844defineSymbol(math, main, close, "\u27e9", "\\rangle", true);
4845defineSymbol(math, main, close, "\u2223", "\\rvert");
4846defineSymbol(math, main, close, "\u2225", "\\rVert");
4847defineSymbol(math, main, rel, "=", "=");
4848defineSymbol(math, main, rel, ":", ":");
4849defineSymbol(math, main, rel, "\u2248", "\\approx", true);
4850defineSymbol(math, main, rel, "\u2245", "\\cong", true);
4851defineSymbol(math, main, rel, "\u2265", "\\ge");
4852defineSymbol(math, main, rel, "\u2265", "\\geq", true);
4853defineSymbol(math, main, rel, "\u2190", "\\gets");
4854defineSymbol(math, main, rel, ">", "\\gt", true);
4855defineSymbol(math, main, rel, "\u2208", "\\in", true);
4856defineSymbol(math, main, rel, "\ue020", "\\@not");
4857defineSymbol(math, main, rel, "\u2282", "\\subset", true);
4858defineSymbol(math, main, rel, "\u2283", "\\supset", true);
4859defineSymbol(math, main, rel, "\u2286", "\\subseteq", true);
4860defineSymbol(math, main, rel, "\u2287", "\\supseteq", true);
4861defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true);
4862defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true);
4863defineSymbol(math, main, rel, "\u22a8", "\\models");
4864defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true);
4865defineSymbol(math, main, rel, "\u2264", "\\le");
4866defineSymbol(math, main, rel, "\u2264", "\\leq", true);
4867defineSymbol(math, main, rel, "<", "\\lt", true);
4868defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true);
4869defineSymbol(math, main, rel, "\u2192", "\\to");
4870defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true);
4871defineSymbol(math, ams, rel, "\u2270", "\\nleq", true);
4872defineSymbol(math, main, spacing, "\u00a0", "\\ ");
4873defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{%
4874
4875defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace");
4876defineSymbol(text, main, spacing, "\u00a0", "\\ ");
4877defineSymbol(text, main, spacing, "\u00a0", " ");
4878defineSymbol(text, main, spacing, "\u00a0", "\\space");
4879defineSymbol(text, main, spacing, "\u00a0", "\\nobreakspace");
4880defineSymbol(math, main, spacing, null, "\\nobreak");
4881defineSymbol(math, main, spacing, null, "\\allowbreak");
4882defineSymbol(math, main, punct, ",", ",");
4883defineSymbol(math, main, punct, ";", ";");
4884defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
4885defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true);
4886defineSymbol(math, main, bin, "\u2299", "\\odot", true);
4887defineSymbol(math, main, bin, "\u2295", "\\oplus", true);
4888defineSymbol(math, main, bin, "\u2297", "\\otimes", true);
4889defineSymbol(math, main, textord, "\u2202", "\\partial", true);
4890defineSymbol(math, main, bin, "\u2298", "\\oslash", true);
4891defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true);
4892defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true);
4893defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
4894defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
4895defineSymbol(math, main, bin, "\u2020", "\\dagger");
4896defineSymbol(math, main, bin, "\u22c4", "\\diamond");
4897defineSymbol(math, main, bin, "\u22c6", "\\star");
4898defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
4899defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
4900defineSymbol(math, main, open, "{", "\\{");
4901defineSymbol(text, main, textord, "{", "\\{");
4902defineSymbol(text, main, textord, "{", "\\textbraceleft");
4903defineSymbol(math, main, close, "}", "\\}");
4904defineSymbol(text, main, textord, "}", "\\}");
4905defineSymbol(text, main, textord, "}", "\\textbraceright");
4906defineSymbol(math, main, open, "{", "\\lbrace");
4907defineSymbol(math, main, close, "}", "\\rbrace");
4908defineSymbol(math, main, open, "[", "\\lbrack", true);
4909defineSymbol(text, main, textord, "[", "\\lbrack", true);
4910defineSymbol(math, main, close, "]", "\\rbrack", true);
4911defineSymbol(text, main, textord, "]", "\\rbrack", true);
4912defineSymbol(math, main, open, "(", "\\lparen", true);
4913defineSymbol(math, main, close, ")", "\\rparen", true);
4914defineSymbol(text, main, textord, "<", "\\textless", true); // in T1 fontenc
4915
4916defineSymbol(text, main, textord, ">", "\\textgreater", true); // in T1 fontenc
4917
4918defineSymbol(math, main, open, "\u230a", "\\lfloor", true);
4919defineSymbol(math, main, close, "\u230b", "\\rfloor", true);
4920defineSymbol(math, main, open, "\u2308", "\\lceil", true);
4921defineSymbol(math, main, close, "\u2309", "\\rceil", true);
4922defineSymbol(math, main, textord, "\\", "\\backslash");
4923defineSymbol(math, main, textord, "\u2223", "|");
4924defineSymbol(math, main, textord, "\u2223", "\\vert");
4925defineSymbol(text, main, textord, "|", "\\textbar", true); // in T1 fontenc
4926
4927defineSymbol(math, main, textord, "\u2225", "\\|");
4928defineSymbol(math, main, textord, "\u2225", "\\Vert");
4929defineSymbol(text, main, textord, "\u2225", "\\textbardbl");
4930defineSymbol(text, main, textord, "~", "\\textasciitilde");
4931defineSymbol(text, main, textord, "\\", "\\textbackslash");
4932defineSymbol(text, main, textord, "^", "\\textasciicircum");
4933defineSymbol(math, main, rel, "\u2191", "\\uparrow", true);
4934defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true);
4935defineSymbol(math, main, rel, "\u2193", "\\downarrow", true);
4936defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true);
4937defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true);
4938defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true);
4939defineSymbol(math, main, op, "\u2210", "\\coprod");
4940defineSymbol(math, main, op, "\u22c1", "\\bigvee");
4941defineSymbol(math, main, op, "\u22c0", "\\bigwedge");
4942defineSymbol(math, main, op, "\u2a04", "\\biguplus");
4943defineSymbol(math, main, op, "\u22c2", "\\bigcap");
4944defineSymbol(math, main, op, "\u22c3", "\\bigcup");
4945defineSymbol(math, main, op, "\u222b", "\\int");
4946defineSymbol(math, main, op, "\u222b", "\\intop");
4947defineSymbol(math, main, op, "\u222c", "\\iint");
4948defineSymbol(math, main, op, "\u222d", "\\iiint");
4949defineSymbol(math, main, op, "\u220f", "\\prod");
4950defineSymbol(math, main, op, "\u2211", "\\sum");
4951defineSymbol(math, main, op, "\u2a02", "\\bigotimes");
4952defineSymbol(math, main, op, "\u2a01", "\\bigoplus");
4953defineSymbol(math, main, op, "\u2a00", "\\bigodot");
4954defineSymbol(math, main, op, "\u222e", "\\oint");
4955defineSymbol(math, main, op, "\u222f", "\\oiint");
4956defineSymbol(math, main, op, "\u2230", "\\oiiint");
4957defineSymbol(math, main, op, "\u2a06", "\\bigsqcup");
4958defineSymbol(math, main, op, "\u222b", "\\smallint");
4959defineSymbol(text, main, inner, "\u2026", "\\textellipsis");
4960defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
4961defineSymbol(text, main, inner, "\u2026", "\\ldots", true);
4962defineSymbol(math, main, inner, "\u2026", "\\ldots", true);
4963defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true);
4964defineSymbol(math, main, inner, "\u22f1", "\\ddots", true);
4965defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
4966
4967defineSymbol(math, main, accent, "\u02ca", "\\acute");
4968defineSymbol(math, main, accent, "\u02cb", "\\grave");
4969defineSymbol(math, main, accent, "\u00a8", "\\ddot");
4970defineSymbol(math, main, accent, "\u007e", "\\tilde");
4971defineSymbol(math, main, accent, "\u02c9", "\\bar");
4972defineSymbol(math, main, accent, "\u02d8", "\\breve");
4973defineSymbol(math, main, accent, "\u02c7", "\\check");
4974defineSymbol(math, main, accent, "\u005e", "\\hat");
4975defineSymbol(math, main, accent, "\u20d7", "\\vec");
4976defineSymbol(math, main, accent, "\u02d9", "\\dot");
4977defineSymbol(math, main, accent, "\u02da", "\\mathring"); // \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA
4978
4979defineSymbol(math, main, mathord, "\ue131", "\\@imath");
4980defineSymbol(math, main, mathord, "\ue237", "\\@jmath");
4981defineSymbol(math, main, textord, "\u0131", "\u0131");
4982defineSymbol(math, main, textord, "\u0237", "\u0237");
4983defineSymbol(text, main, textord, "\u0131", "\\i", true);
4984defineSymbol(text, main, textord, "\u0237", "\\j", true);
4985defineSymbol(text, main, textord, "\u00df", "\\ss", true);
4986defineSymbol(text, main, textord, "\u00e6", "\\ae", true);
4987defineSymbol(text, main, textord, "\u0153", "\\oe", true);
4988defineSymbol(text, main, textord, "\u00f8", "\\o", true);
4989defineSymbol(text, main, textord, "\u00c6", "\\AE", true);
4990defineSymbol(text, main, textord, "\u0152", "\\OE", true);
4991defineSymbol(text, main, textord, "\u00d8", "\\O", true);
4992defineSymbol(text, main, accent, "\u02ca", "\\'"); // acute
4993
4994defineSymbol(text, main, accent, "\u02cb", "\\`"); // grave
4995
4996defineSymbol(text, main, accent, "\u02c6", "\\^"); // circumflex
4997
4998defineSymbol(text, main, accent, "\u02dc", "\\~"); // tilde
4999
5000defineSymbol(text, main, accent, "\u02c9", "\\="); // macron
5001
5002defineSymbol(text, main, accent, "\u02d8", "\\u"); // breve
5003
5004defineSymbol(text, main, accent, "\u02d9", "\\."); // dot above
5005
5006defineSymbol(text, main, accent, "\u00b8", "\\c"); // cedilla
5007
5008defineSymbol(text, main, accent, "\u02da", "\\r"); // ring above
5009
5010defineSymbol(text, main, accent, "\u02c7", "\\v"); // caron
5011
5012defineSymbol(text, main, accent, "\u00a8", '\\"'); // diaresis
5013
5014defineSymbol(text, main, accent, "\u02dd", "\\H"); // double acute
5015
5016defineSymbol(text, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph
5017// These ligatures are detected and created in Parser.js's `formLigatures`.
5018
5019var ligatures = {
5020 "--": true,
5021 "---": true,
5022 "``": true,
5023 "''": true
5024};
5025defineSymbol(text, main, textord, "\u2013", "--", true);
5026defineSymbol(text, main, textord, "\u2013", "\\textendash");
5027defineSymbol(text, main, textord, "\u2014", "---", true);
5028defineSymbol(text, main, textord, "\u2014", "\\textemdash");
5029defineSymbol(text, main, textord, "\u2018", "`", true);
5030defineSymbol(text, main, textord, "\u2018", "\\textquoteleft");
5031defineSymbol(text, main, textord, "\u2019", "'", true);
5032defineSymbol(text, main, textord, "\u2019", "\\textquoteright");
5033defineSymbol(text, main, textord, "\u201c", "``", true);
5034defineSymbol(text, main, textord, "\u201c", "\\textquotedblleft");
5035defineSymbol(text, main, textord, "\u201d", "''", true);
5036defineSymbol(text, main, textord, "\u201d", "\\textquotedblright"); // \degree from gensymb package
5037
5038defineSymbol(math, main, textord, "\u00b0", "\\degree", true);
5039defineSymbol(text, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package
5040
5041defineSymbol(text, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math
5042// mode, but among our fonts, only Main-Regular defines this character "163".
5043
5044defineSymbol(math, main, textord, "\u00a3", "\\pounds");
5045defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true);
5046defineSymbol(text, main, textord, "\u00a3", "\\pounds");
5047defineSymbol(text, main, textord, "\u00a3", "\\textsterling", true);
5048defineSymbol(math, ams, textord, "\u2720", "\\maltese");
5049defineSymbol(text, ams, textord, "\u2720", "\\maltese"); // There are lots of symbols which are the same, so we add them in afterwards.
5050// All of these are textords in math mode
5051
5052var mathTextSymbols = "0123456789/@.\"";
5053
5054for (var i = 0; i < mathTextSymbols.length; i++) {
5055 var ch = mathTextSymbols.charAt(i);
5056 defineSymbol(math, main, textord, ch, ch);
5057} // All of these are textords in text mode
5058
5059
5060var textSymbols = "0123456789!@*()-=+\";:?/.,";
5061
5062for (var _i = 0; _i < textSymbols.length; _i++) {
5063 var _ch = textSymbols.charAt(_i);
5064
5065 defineSymbol(text, main, textord, _ch, _ch);
5066} // All of these are textords in text mode, and mathords in math mode
5067
5068
5069var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
5070
5071for (var _i2 = 0; _i2 < letters.length; _i2++) {
5072 var _ch2 = letters.charAt(_i2);
5073
5074 defineSymbol(math, main, mathord, _ch2, _ch2);
5075 defineSymbol(text, main, textord, _ch2, _ch2);
5076} // Blackboard bold and script letters in Unicode range
5077
5078
5079defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold
5080
5081defineSymbol(text, ams, textord, "C", "\u2102");
5082defineSymbol(math, ams, textord, "H", "\u210D");
5083defineSymbol(text, ams, textord, "H", "\u210D");
5084defineSymbol(math, ams, textord, "N", "\u2115");
5085defineSymbol(text, ams, textord, "N", "\u2115");
5086defineSymbol(math, ams, textord, "P", "\u2119");
5087defineSymbol(text, ams, textord, "P", "\u2119");
5088defineSymbol(math, ams, textord, "Q", "\u211A");
5089defineSymbol(text, ams, textord, "Q", "\u211A");
5090defineSymbol(math, ams, textord, "R", "\u211D");
5091defineSymbol(text, ams, textord, "R", "\u211D");
5092defineSymbol(math, ams, textord, "Z", "\u2124");
5093defineSymbol(text, ams, textord, "Z", "\u2124");
5094defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant
5095
5096defineSymbol(text, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters.
5097// We support some letters in the Unicode range U+1D400 to U+1D7FF,
5098// Mathematical Alphanumeric Symbols.
5099// Some editors do not deal well with wide characters. So don't write the
5100// string into this file. Instead, create the string from the surrogate pair.
5101
5102var wideChar = "";
5103
5104for (var _i3 = 0; _i3 < letters.length; _i3++) {
5105 var _ch3 = letters.charAt(_i3); // The hex numbers in the next line are a surrogate pair.
5106 // 0xD835 is the high surrogate for all letters in the range we support.
5107 // 0xDC00 is the low surrogate for bold A.
5108
5109
5110 wideChar = String.fromCharCode(0xD835, 0xDC00 + _i3); // A-Z a-z bold
5111
5112 defineSymbol(math, main, mathord, _ch3, wideChar);
5113 defineSymbol(text, main, textord, _ch3, wideChar);
5114 wideChar = String.fromCharCode(0xD835, 0xDC34 + _i3); // A-Z a-z italic
5115
5116 defineSymbol(math, main, mathord, _ch3, wideChar);
5117 defineSymbol(text, main, textord, _ch3, wideChar);
5118 wideChar = String.fromCharCode(0xD835, 0xDC68 + _i3); // A-Z a-z bold italic
5119
5120 defineSymbol(math, main, mathord, _ch3, wideChar);
5121 defineSymbol(text, main, textord, _ch3, wideChar);
5122 wideChar = String.fromCharCode(0xD835, 0xDD04 + _i3); // A-Z a-z Fractur
5123
5124 defineSymbol(math, main, mathord, _ch3, wideChar);
5125 defineSymbol(text, main, textord, _ch3, wideChar);
5126 wideChar = String.fromCharCode(0xD835, 0xDDA0 + _i3); // A-Z a-z sans-serif
5127
5128 defineSymbol(math, main, mathord, _ch3, wideChar);
5129 defineSymbol(text, main, textord, _ch3, wideChar);
5130 wideChar = String.fromCharCode(0xD835, 0xDDD4 + _i3); // A-Z a-z sans bold
5131
5132 defineSymbol(math, main, mathord, _ch3, wideChar);
5133 defineSymbol(text, main, textord, _ch3, wideChar);
5134 wideChar = String.fromCharCode(0xD835, 0xDE08 + _i3); // A-Z a-z sans italic
5135
5136 defineSymbol(math, main, mathord, _ch3, wideChar);
5137 defineSymbol(text, main, textord, _ch3, wideChar);
5138 wideChar = String.fromCharCode(0xD835, 0xDE70 + _i3); // A-Z a-z monospace
5139
5140 defineSymbol(math, main, mathord, _ch3, wideChar);
5141 defineSymbol(text, main, textord, _ch3, wideChar);
5142
5143 if (_i3 < 26) {
5144 // KaTeX fonts have only capital letters for blackboard bold and script.
5145 // See exception for k below.
5146 wideChar = String.fromCharCode(0xD835, 0xDD38 + _i3); // A-Z double struck
5147
5148 defineSymbol(math, main, mathord, _ch3, wideChar);
5149 defineSymbol(text, main, textord, _ch3, wideChar);
5150 wideChar = String.fromCharCode(0xD835, 0xDC9C + _i3); // A-Z script
5151
5152 defineSymbol(math, main, mathord, _ch3, wideChar);
5153 defineSymbol(text, main, textord, _ch3, wideChar);
5154 } // TODO: Add bold script when it is supported by a KaTeX font.
5155
5156} // "k" is the only double struck lower case letter in the KaTeX fonts.
5157
5158
5159wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck
5160
5161defineSymbol(math, main, mathord, "k", wideChar);
5162defineSymbol(text, main, textord, "k", wideChar); // Next, some wide character numerals
5163
5164for (var _i4 = 0; _i4 < 10; _i4++) {
5165 var _ch4 = _i4.toString();
5166
5167 wideChar = String.fromCharCode(0xD835, 0xDFCE + _i4); // 0-9 bold
5168
5169 defineSymbol(math, main, mathord, _ch4, wideChar);
5170 defineSymbol(text, main, textord, _ch4, wideChar);
5171 wideChar = String.fromCharCode(0xD835, 0xDFE2 + _i4); // 0-9 sans serif
5172
5173 defineSymbol(math, main, mathord, _ch4, wideChar);
5174 defineSymbol(text, main, textord, _ch4, wideChar);
5175 wideChar = String.fromCharCode(0xD835, 0xDFEC + _i4); // 0-9 bold sans
5176
5177 defineSymbol(math, main, mathord, _ch4, wideChar);
5178 defineSymbol(text, main, textord, _ch4, wideChar);
5179 wideChar = String.fromCharCode(0xD835, 0xDFF6 + _i4); // 0-9 monospace
5180
5181 defineSymbol(math, main, mathord, _ch4, wideChar);
5182 defineSymbol(text, main, textord, _ch4, wideChar);
5183} // We add these Latin-1 letters as symbols for backwards-compatibility,
5184// but they are not actually in the font, nor are they supported by the
5185// Unicode accent mechanism, so they fall back to Times font and look ugly.
5186// TODO(edemaine): Fix this.
5187
5188
5189var extraLatin = "\u00d0\u00de\u00fe";
5190
5191for (var _i5 = 0; _i5 < extraLatin.length; _i5++) {
5192 var _ch5 = extraLatin.charAt(_i5);
5193
5194 defineSymbol(math, main, mathord, _ch5, _ch5);
5195 defineSymbol(text, main, textord, _ch5, _ch5);
5196}
5197
5198/**
5199 * This file provides support for Unicode range U+1D400 to U+1D7FF,
5200 * Mathematical Alphanumeric Symbols.
5201 *
5202 * Function wideCharacterFont takes a wide character as input and returns
5203 * the font information necessary to render it properly.
5204 */
5205/**
5206 * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
5207 * That document sorts characters into groups by font type, say bold or italic.
5208 *
5209 * In the arrays below, each subarray consists three elements:
5210 * * The CSS class of that group when in math mode.
5211 * * The CSS class of that group when in text mode.
5212 * * The font name, so that KaTeX can get font metrics.
5213 */
5214
5215var wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright
5216["mathbf", "textbf", "Main-Bold"], // a-z bold upright
5217["mathnormal", "textit", "Math-Italic"], // A-Z italic
5218["mathnormal", "textit", "Math-Italic"], // a-z italic
5219["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic
5220["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic
5221// Map fancy A-Z letters to script, not calligraphic.
5222// This aligns with unicode-math and math fonts (except Cambria Math).
5223["mathscr", "textscr", "Script-Regular"], // A-Z script
5224["", "", ""], // a-z script. No font
5225["", "", ""], // A-Z bold script. No font
5226["", "", ""], // a-z bold script. No font
5227["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur
5228["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur
5229["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck
5230["mathbb", "textbb", "AMS-Regular"], // k double-struck
5231["", "", ""], // A-Z bold Fraktur No font metrics
5232["", "", ""], // a-z bold Fraktur. No font.
5233["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif
5234["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif
5235["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif
5236["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif
5237["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif
5238["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif
5239["", "", ""], // A-Z bold italic sans. No font
5240["", "", ""], // a-z bold italic sans. No font
5241["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace
5242["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace
5243];
5244var wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold
5245["", "", ""], // 0-9 double-struck. No KaTeX font.
5246["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif
5247["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif
5248["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace
5249];
5250var wideCharacterFont = function wideCharacterFont(wideChar, mode) {
5251 // IE doesn't support codePointAt(). So work with the surrogate pair.
5252 var H = wideChar.charCodeAt(0); // high surrogate
5253
5254 var L = wideChar.charCodeAt(1); // low surrogate
5255
5256 var codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
5257 var j = mode === "math" ? 0 : 1; // column index for CSS class.
5258
5259 if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
5260 // wideLatinLetterData contains exactly 26 chars on each row.
5261 // So we can calculate the relevant row. No traverse necessary.
5262 var i = Math.floor((codePoint - 0x1D400) / 26);
5263 return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]];
5264 } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
5265 // Numerals, ten per row.
5266 var _i = Math.floor((codePoint - 0x1D7CE) / 10);
5267
5268 return [wideNumeralData[_i][2], wideNumeralData[_i][j]];
5269 } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
5270 // dotless i or j
5271 return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]];
5272 } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
5273 // Greek letters. Not supported, yet.
5274 return ["", ""];
5275 } else {
5276 // We don't support any wide characters outside 1D400–1D7FF.
5277 throw new ParseError("Unsupported character: " + wideChar);
5278 }
5279};
5280
5281/* eslint no-console:0 */
5282
5283/**
5284 * Looks up the given symbol in fontMetrics, after applying any symbol
5285 * replacements defined in symbol.js
5286 */
5287var lookupSymbol = function lookupSymbol(value, // TODO(#963): Use a union type for this.
5288fontName, mode) {
5289 // Replace the value with its replaced value from symbol.js
5290 if (symbols[mode][value] && symbols[mode][value].replace) {
5291 value = symbols[mode][value].replace;
5292 }
5293
5294 return {
5295 value: value,
5296 metrics: getCharacterMetrics(value, fontName, mode)
5297 };
5298};
5299/**
5300 * Makes a symbolNode after translation via the list of symbols in symbols.js.
5301 * Correctly pulls out metrics for the character, and optionally takes a list of
5302 * classes to be attached to the node.
5303 *
5304 * TODO: make argument order closer to makeSpan
5305 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
5306 * should if present come first in `classes`.
5307 * TODO(#953): Make `options` mandatory and always pass it in.
5308 */
5309
5310
5311var makeSymbol = function makeSymbol(value, fontName, mode, options, classes) {
5312 var lookup = lookupSymbol(value, fontName, mode);
5313 var metrics = lookup.metrics;
5314 value = lookup.value;
5315 var symbolNode;
5316
5317 if (metrics) {
5318 var italic = metrics.italic;
5319
5320 if (mode === "text" || options && options.font === "mathit") {
5321 italic = 0;
5322 }
5323
5324 symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes);
5325 } else {
5326 // TODO(emily): Figure out a good way to only print this in development
5327 typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'"));
5328 symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes);
5329 }
5330
5331 if (options) {
5332 symbolNode.maxFontSize = options.sizeMultiplier;
5333
5334 if (options.style.isTight()) {
5335 symbolNode.classes.push("mtight");
5336 }
5337
5338 var color = options.getColor();
5339
5340 if (color) {
5341 symbolNode.style.color = color;
5342 }
5343 }
5344
5345 return symbolNode;
5346};
5347/**
5348 * Makes a symbol in Main-Regular or AMS-Regular.
5349 * Used for rel, bin, open, close, inner, and punct.
5350 */
5351
5352
5353var mathsym = function mathsym(value, mode, options, classes) {
5354 if (classes === void 0) {
5355 classes = [];
5356 }
5357
5358 // Decide what font to render the symbol in by its entry in the symbols
5359 // table.
5360 // Have a special case for when the value = \ because the \ is used as a
5361 // textord in unsupported command errors but cannot be parsed as a regular
5362 // text ordinal and is therefore not present as a symbol in the symbols
5363 // table for text, as well as a special case for boldsymbol because it
5364 // can be used for bold + and -
5365 if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) {
5366 return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"]));
5367 } else if (value === "\\" || symbols[mode][value].font === "main") {
5368 return makeSymbol(value, "Main-Regular", mode, options, classes);
5369 } else {
5370 return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
5371 }
5372};
5373/**
5374 * Determines which of the two font names (Main-Bold and Math-BoldItalic) and
5375 * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol",
5376 * depending on the symbol. Use this function instead of fontMap for font
5377 * "boldsymbol".
5378 */
5379
5380
5381var boldsymbol = function boldsymbol(value, mode, options, classes, type) {
5382 if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
5383 return {
5384 fontName: "Math-BoldItalic",
5385 fontClass: "boldsymbol"
5386 };
5387 } else {
5388 // Some glyphs do not exist in Math-BoldItalic so we need to use
5389 // Main-Bold instead.
5390 return {
5391 fontName: "Main-Bold",
5392 fontClass: "mathbf"
5393 };
5394 }
5395};
5396/**
5397 * Makes either a mathord or textord in the correct font and color.
5398 */
5399
5400
5401var makeOrd = function makeOrd(group, options, type) {
5402 var mode = group.mode;
5403 var text = group.text;
5404 var classes = ["mord"]; // Math mode or Old font (i.e. \rm)
5405
5406 var isFont = mode === "math" || mode === "text" && options.font;
5407 var fontOrFamily = isFont ? options.font : options.fontFamily;
5408
5409 if (text.charCodeAt(0) === 0xD835) {
5410 // surrogate pairs get special treatment
5411 var [wideFontName, wideFontClass] = wideCharacterFont(text, mode);
5412 return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
5413 } else if (fontOrFamily) {
5414 var fontName;
5415 var fontClasses;
5416
5417 if (fontOrFamily === "boldsymbol") {
5418 var fontData = boldsymbol(text, mode, options, classes, type);
5419 fontName = fontData.fontName;
5420 fontClasses = [fontData.fontClass];
5421 } else if (isFont) {
5422 fontName = fontMap[fontOrFamily].fontName;
5423 fontClasses = [fontOrFamily];
5424 } else {
5425 fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape);
5426 fontClasses = [fontOrFamily, options.fontWeight, options.fontShape];
5427 }
5428
5429 if (lookupSymbol(text, fontName, mode).metrics) {
5430 return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
5431 } else if (ligatures.hasOwnProperty(text) && fontName.substr(0, 10) === "Typewriter") {
5432 // Deconstruct ligatures in monospace fonts (\texttt, \tt).
5433 var parts = [];
5434
5435 for (var i = 0; i < text.length; i++) {
5436 parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses)));
5437 }
5438
5439 return makeFragment(parts);
5440 }
5441 } // Makes a symbol in the default font for mathords and textords.
5442
5443
5444 if (type === "mathord") {
5445 return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"]));
5446 } else if (type === "textord") {
5447 var font = symbols[mode][text] && symbols[mode][text].font;
5448
5449 if (font === "ams") {
5450 var _fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape);
5451
5452 return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape));
5453 } else if (font === "main" || !font) {
5454 var _fontName2 = retrieveTextFontName("textrm", options.fontWeight, options.fontShape);
5455
5456 return makeSymbol(text, _fontName2, mode, options, classes.concat(options.fontWeight, options.fontShape));
5457 } else {
5458 // fonts added by plugins
5459 var _fontName3 = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class
5460
5461
5462 return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, options.fontWeight, options.fontShape));
5463 }
5464 } else {
5465 throw new Error("unexpected type: " + type + " in makeOrd");
5466 }
5467};
5468/**
5469 * Returns true if subsequent symbolNodes have the same classes, skew, maxFont,
5470 * and styles.
5471 */
5472
5473
5474var canCombine = (prev, next) => {
5475 if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) {
5476 return false;
5477 } // If prev and next both are just "mbin"s or "mord"s we don't combine them
5478 // so that the proper spacing can be preserved.
5479
5480
5481 if (prev.classes.length === 1) {
5482 var cls = prev.classes[0];
5483
5484 if (cls === "mbin" || cls === "mord") {
5485 return false;
5486 }
5487 }
5488
5489 for (var style in prev.style) {
5490 if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) {
5491 return false;
5492 }
5493 }
5494
5495 for (var _style in next.style) {
5496 if (next.style.hasOwnProperty(_style) && prev.style[_style] !== next.style[_style]) {
5497 return false;
5498 }
5499 }
5500
5501 return true;
5502};
5503/**
5504 * Combine consecutive domTree.symbolNodes into a single symbolNode.
5505 * Note: this function mutates the argument.
5506 */
5507
5508
5509var tryCombineChars = chars => {
5510 for (var i = 0; i < chars.length - 1; i++) {
5511 var prev = chars[i];
5512 var next = chars[i + 1];
5513
5514 if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) {
5515 prev.text += next.text;
5516 prev.height = Math.max(prev.height, next.height);
5517 prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use
5518 // it to add padding to the right of the span created from
5519 // the combined characters.
5520
5521 prev.italic = next.italic;
5522 chars.splice(i + 1, 1);
5523 i--;
5524 }
5525 }
5526
5527 return chars;
5528};
5529/**
5530 * Calculate the height, depth, and maxFontSize of an element based on its
5531 * children.
5532 */
5533
5534
5535var sizeElementFromChildren = function sizeElementFromChildren(elem) {
5536 var height = 0;
5537 var depth = 0;
5538 var maxFontSize = 0;
5539
5540 for (var i = 0; i < elem.children.length; i++) {
5541 var child = elem.children[i];
5542
5543 if (child.height > height) {
5544 height = child.height;
5545 }
5546
5547 if (child.depth > depth) {
5548 depth = child.depth;
5549 }
5550
5551 if (child.maxFontSize > maxFontSize) {
5552 maxFontSize = child.maxFontSize;
5553 }
5554 }
5555
5556 elem.height = height;
5557 elem.depth = depth;
5558 elem.maxFontSize = maxFontSize;
5559};
5560/**
5561 * Makes a span with the given list of classes, list of children, and options.
5562 *
5563 * TODO(#953): Ensure that `options` is always provided (currently some call
5564 * sites don't pass it) and make the type below mandatory.
5565 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
5566 * should if present come first in `classes`.
5567 */
5568
5569
5570var makeSpan$2 = function makeSpan(classes, children, options, style) {
5571 var span = new Span(classes, children, options, style);
5572 sizeElementFromChildren(span);
5573 return span;
5574}; // SVG one is simpler -- doesn't require height, depth, max-font setting.
5575// This is also a separate method for typesafety.
5576
5577
5578var makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style);
5579
5580var makeLineSpan = function makeLineSpan(className, options, thickness) {
5581 var line = makeSpan$2([className], [], options);
5582 line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
5583 line.style.borderBottomWidth = makeEm(line.height);
5584 line.maxFontSize = 1.0;
5585 return line;
5586};
5587/**
5588 * Makes an anchor with the given href, list of classes, list of children,
5589 * and options.
5590 */
5591
5592
5593var makeAnchor = function makeAnchor(href, classes, children, options) {
5594 var anchor = new Anchor(href, classes, children, options);
5595 sizeElementFromChildren(anchor);
5596 return anchor;
5597};
5598/**
5599 * Makes a document fragment with the given list of children.
5600 */
5601
5602
5603var makeFragment = function makeFragment(children) {
5604 var fragment = new DocumentFragment(children);
5605 sizeElementFromChildren(fragment);
5606 return fragment;
5607};
5608/**
5609 * Wraps group in a span if it's a document fragment, allowing to apply classes
5610 * and styles
5611 */
5612
5613
5614var wrapFragment = function wrapFragment(group, options) {
5615 if (group instanceof DocumentFragment) {
5616 return makeSpan$2([], [group], options);
5617 }
5618
5619 return group;
5620}; // These are exact object types to catch typos in the names of the optional fields.
5621
5622
5623// Computes the updated `children` list and the overall depth.
5624//
5625// This helper function for makeVList makes it easier to enforce type safety by
5626// allowing early exits (returns) in the logic.
5627var getVListChildrenAndDepth = function getVListChildrenAndDepth(params) {
5628 if (params.positionType === "individualShift") {
5629 var oldChildren = params.children;
5630 var children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be
5631 // shifted to the correct specified shift
5632
5633 var _depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
5634
5635 var currPos = _depth;
5636
5637 for (var i = 1; i < oldChildren.length; i++) {
5638 var diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth;
5639 var size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth);
5640 currPos = currPos + diff;
5641 children.push({
5642 type: "kern",
5643 size
5644 });
5645 children.push(oldChildren[i]);
5646 }
5647
5648 return {
5649 children,
5650 depth: _depth
5651 };
5652 }
5653
5654 var depth;
5655
5656 if (params.positionType === "top") {
5657 // We always start at the bottom, so calculate the bottom by adding up
5658 // all the sizes
5659 var bottom = params.positionData;
5660
5661 for (var _i = 0; _i < params.children.length; _i++) {
5662 var child = params.children[_i];
5663 bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth;
5664 }
5665
5666 depth = bottom;
5667 } else if (params.positionType === "bottom") {
5668 depth = -params.positionData;
5669 } else {
5670 var firstChild = params.children[0];
5671
5672 if (firstChild.type !== "elem") {
5673 throw new Error('First child must have type "elem".');
5674 }
5675
5676 if (params.positionType === "shift") {
5677 depth = -firstChild.elem.depth - params.positionData;
5678 } else if (params.positionType === "firstBaseline") {
5679 depth = -firstChild.elem.depth;
5680 } else {
5681 throw new Error("Invalid positionType " + params.positionType + ".");
5682 }
5683 }
5684
5685 return {
5686 children: params.children,
5687 depth
5688 };
5689};
5690/**
5691 * Makes a vertical list by stacking elements and kerns on top of each other.
5692 * Allows for many different ways of specifying the positioning method.
5693 *
5694 * See VListParam documentation above.
5695 */
5696
5697
5698var makeVList = function makeVList(params, options) {
5699 var {
5700 children,
5701 depth
5702 } = getVListChildrenAndDepth(params); // Create a strut that is taller than any list item. The strut is added to
5703 // each item, where it will determine the item's baseline. Since it has
5704 // `overflow:hidden`, the strut's top edge will sit on the item's line box's
5705 // top edge and the strut's bottom edge will sit on the item's baseline,
5706 // with no additional line-height spacing. This allows the item baseline to
5707 // be positioned precisely without worrying about font ascent and
5708 // line-height.
5709
5710 var pstrutSize = 0;
5711
5712 for (var i = 0; i < children.length; i++) {
5713 var child = children[i];
5714
5715 if (child.type === "elem") {
5716 var elem = child.elem;
5717 pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height);
5718 }
5719 }
5720
5721 pstrutSize += 2;
5722 var pstrut = makeSpan$2(["pstrut"], []);
5723 pstrut.style.height = makeEm(pstrutSize); // Create a new list of actual children at the correct offsets
5724
5725 var realChildren = [];
5726 var minPos = depth;
5727 var maxPos = depth;
5728 var currPos = depth;
5729
5730 for (var _i2 = 0; _i2 < children.length; _i2++) {
5731 var _child = children[_i2];
5732
5733 if (_child.type === "kern") {
5734 currPos += _child.size;
5735 } else {
5736 var _elem = _child.elem;
5737 var classes = _child.wrapperClasses || [];
5738 var style = _child.wrapperStyle || {};
5739 var childWrap = makeSpan$2(classes, [pstrut, _elem], undefined, style);
5740 childWrap.style.top = makeEm(-pstrutSize - currPos - _elem.depth);
5741
5742 if (_child.marginLeft) {
5743 childWrap.style.marginLeft = _child.marginLeft;
5744 }
5745
5746 if (_child.marginRight) {
5747 childWrap.style.marginRight = _child.marginRight;
5748 }
5749
5750 realChildren.push(childWrap);
5751 currPos += _elem.height + _elem.depth;
5752 }
5753
5754 minPos = Math.min(minPos, currPos);
5755 maxPos = Math.max(maxPos, currPos);
5756 } // The vlist contents go in a table-cell with `vertical-align:bottom`.
5757 // This cell's bottom edge will determine the containing table's baseline
5758 // without overly expanding the containing line-box.
5759
5760
5761 var vlist = makeSpan$2(["vlist"], realChildren);
5762 vlist.style.height = makeEm(maxPos); // A second row is used if necessary to represent the vlist's depth.
5763
5764 var rows;
5765
5766 if (minPos < 0) {
5767 // We will define depth in an empty span with display: table-cell.
5768 // It should render with the height that we define. But Chrome, in
5769 // contenteditable mode only, treats that span as if it contains some
5770 // text content. And that min-height over-rides our desired height.
5771 // So we put another empty span inside the depth strut span.
5772 var emptySpan = makeSpan$2([], []);
5773 var depthStrut = makeSpan$2(["vlist"], [emptySpan]);
5774 depthStrut.style.height = makeEm(-minPos); // Safari wants the first row to have inline content; otherwise it
5775 // puts the bottom of the *second* row on the baseline.
5776
5777 var topStrut = makeSpan$2(["vlist-s"], [new SymbolNode("\u200b")]);
5778 rows = [makeSpan$2(["vlist-r"], [vlist, topStrut]), makeSpan$2(["vlist-r"], [depthStrut])];
5779 } else {
5780 rows = [makeSpan$2(["vlist-r"], [vlist])];
5781 }
5782
5783 var vtable = makeSpan$2(["vlist-t"], rows);
5784
5785 if (rows.length === 2) {
5786 vtable.classes.push("vlist-t2");
5787 }
5788
5789 vtable.height = maxPos;
5790 vtable.depth = -minPos;
5791 return vtable;
5792}; // Glue is a concept from TeX which is a flexible space between elements in
5793// either a vertical or horizontal list. In KaTeX, at least for now, it's
5794// static space between elements in a horizontal layout.
5795
5796
5797var makeGlue = (measurement, options) => {
5798 // Make an empty span for the space
5799 var rule = makeSpan$2(["mspace"], [], options);
5800 var size = calculateSize(measurement, options);
5801 rule.style.marginRight = makeEm(size);
5802 return rule;
5803}; // Takes font options, and returns the appropriate fontLookup name
5804
5805
5806var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) {
5807 var baseFontName = "";
5808
5809 switch (fontFamily) {
5810 case "amsrm":
5811 baseFontName = "AMS";
5812 break;
5813
5814 case "textrm":
5815 baseFontName = "Main";
5816 break;
5817
5818 case "textsf":
5819 baseFontName = "SansSerif";
5820 break;
5821
5822 case "texttt":
5823 baseFontName = "Typewriter";
5824 break;
5825
5826 default:
5827 baseFontName = fontFamily;
5828 // use fonts added by a plugin
5829 }
5830
5831 var fontStylesName;
5832
5833 if (fontWeight === "textbf" && fontShape === "textit") {
5834 fontStylesName = "BoldItalic";
5835 } else if (fontWeight === "textbf") {
5836 fontStylesName = "Bold";
5837 } else if (fontWeight === "textit") {
5838 fontStylesName = "Italic";
5839 } else {
5840 fontStylesName = "Regular";
5841 }
5842
5843 return baseFontName + "-" + fontStylesName;
5844};
5845/**
5846 * Maps TeX font commands to objects containing:
5847 * - variant: string used for "mathvariant" attribute in buildMathML.js
5848 * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
5849 */
5850// A map between tex font commands an MathML mathvariant attribute values
5851
5852
5853var fontMap = {
5854 // styles
5855 "mathbf": {
5856 variant: "bold",
5857 fontName: "Main-Bold"
5858 },
5859 "mathrm": {
5860 variant: "normal",
5861 fontName: "Main-Regular"
5862 },
5863 "textit": {
5864 variant: "italic",
5865 fontName: "Main-Italic"
5866 },
5867 "mathit": {
5868 variant: "italic",
5869 fontName: "Main-Italic"
5870 },
5871 "mathnormal": {
5872 variant: "italic",
5873 fontName: "Math-Italic"
5874 },
5875 // "boldsymbol" is missing because they require the use of multiple fonts:
5876 // Math-BoldItalic and Main-Bold. This is handled by a special case in
5877 // makeOrd which ends up calling boldsymbol.
5878 // families
5879 "mathbb": {
5880 variant: "double-struck",
5881 fontName: "AMS-Regular"
5882 },
5883 "mathcal": {
5884 variant: "script",
5885 fontName: "Caligraphic-Regular"
5886 },
5887 "mathfrak": {
5888 variant: "fraktur",
5889 fontName: "Fraktur-Regular"
5890 },
5891 "mathscr": {
5892 variant: "script",
5893 fontName: "Script-Regular"
5894 },
5895 "mathsf": {
5896 variant: "sans-serif",
5897 fontName: "SansSerif-Regular"
5898 },
5899 "mathtt": {
5900 variant: "monospace",
5901 fontName: "Typewriter-Regular"
5902 }
5903};
5904var svgData = {
5905 // path, width, height
5906 vec: ["vec", 0.471, 0.714],
5907 // values from the font glyph
5908 oiintSize1: ["oiintSize1", 0.957, 0.499],
5909 // oval to overlay the integrand
5910 oiintSize2: ["oiintSize2", 1.472, 0.659],
5911 oiiintSize1: ["oiiintSize1", 1.304, 0.499],
5912 oiiintSize2: ["oiiintSize2", 1.98, 0.659]
5913};
5914
5915var staticSvg = function staticSvg(value, options) {
5916 // Create a span with inline SVG for the element.
5917 var [pathName, width, height] = svgData[value];
5918 var path = new PathNode(pathName);
5919 var svgNode = new SvgNode([path], {
5920 "width": makeEm(width),
5921 "height": makeEm(height),
5922 // Override CSS rule `.katex svg { width: 100% }`
5923 "style": "width:" + makeEm(width),
5924 "viewBox": "0 0 " + 1000 * width + " " + 1000 * height,
5925 "preserveAspectRatio": "xMinYMin"
5926 });
5927 var span = makeSvgSpan(["overlay"], [svgNode], options);
5928 span.height = height;
5929 span.style.height = makeEm(height);
5930 span.style.width = makeEm(width);
5931 return span;
5932};
5933
5934var buildCommon = {
5935 fontMap,
5936 makeSymbol,
5937 mathsym,
5938 makeSpan: makeSpan$2,
5939 makeSvgSpan,
5940 makeLineSpan,
5941 makeAnchor,
5942 makeFragment,
5943 wrapFragment,
5944 makeVList,
5945 makeOrd,
5946 makeGlue,
5947 staticSvg,
5948 svgData,
5949 tryCombineChars
5950};
5951
5952/**
5953 * Describes spaces between different classes of atoms.
5954 */
5955var thinspace = {
5956 number: 3,
5957 unit: "mu"
5958};
5959var mediumspace = {
5960 number: 4,
5961 unit: "mu"
5962};
5963var thickspace = {
5964 number: 5,
5965 unit: "mu"
5966}; // Making the type below exact with all optional fields doesn't work due to
5967// - https://github.com/facebook/flow/issues/4582
5968// - https://github.com/facebook/flow/issues/5688
5969// However, since *all* fields are optional, $Shape<> works as suggested in 5688
5970// above.
5971
5972// Spacing relationships for display and text styles
5973var spacings = {
5974 mord: {
5975 mop: thinspace,
5976 mbin: mediumspace,
5977 mrel: thickspace,
5978 minner: thinspace
5979 },
5980 mop: {
5981 mord: thinspace,
5982 mop: thinspace,
5983 mrel: thickspace,
5984 minner: thinspace
5985 },
5986 mbin: {
5987 mord: mediumspace,
5988 mop: mediumspace,
5989 mopen: mediumspace,
5990 minner: mediumspace
5991 },
5992 mrel: {
5993 mord: thickspace,
5994 mop: thickspace,
5995 mopen: thickspace,
5996 minner: thickspace
5997 },
5998 mopen: {},
5999 mclose: {
6000 mop: thinspace,
6001 mbin: mediumspace,
6002 mrel: thickspace,
6003 minner: thinspace
6004 },
6005 mpunct: {
6006 mord: thinspace,
6007 mop: thinspace,
6008 mrel: thickspace,
6009 mopen: thinspace,
6010 mclose: thinspace,
6011 mpunct: thinspace,
6012 minner: thinspace
6013 },
6014 minner: {
6015 mord: thinspace,
6016 mop: thinspace,
6017 mbin: mediumspace,
6018 mrel: thickspace,
6019 mopen: thinspace,
6020 mpunct: thinspace,
6021 minner: thinspace
6022 }
6023}; // Spacing relationships for script and scriptscript styles
6024
6025var tightSpacings = {
6026 mord: {
6027 mop: thinspace
6028 },
6029 mop: {
6030 mord: thinspace,
6031 mop: thinspace
6032 },
6033 mbin: {},
6034 mrel: {},
6035 mopen: {},
6036 mclose: {
6037 mop: thinspace
6038 },
6039 mpunct: {},
6040 minner: {
6041 mop: thinspace
6042 }
6043};
6044
6045/** Context provided to function handlers for error messages. */
6046// Note: reverse the order of the return type union will cause a flow error.
6047// See https://github.com/facebook/flow/issues/3663.
6048// More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types)
6049// whose presence impacts super/subscripting. In this case, ParseNode<"supsub">
6050// delegates its HTML building to the HtmlBuilder corresponding to these nodes.
6051
6052/**
6053 * Final function spec for use at parse time.
6054 * This is almost identical to `FunctionPropSpec`, except it
6055 * 1. includes the function handler, and
6056 * 2. requires all arguments except argTypes.
6057 * It is generated by `defineFunction()` below.
6058 */
6059
6060/**
6061 * All registered functions.
6062 * `functions.js` just exports this same dictionary again and makes it public.
6063 * `Parser.js` requires this dictionary.
6064 */
6065var _functions = {};
6066/**
6067 * All HTML builders. Should be only used in the `define*` and the `build*ML`
6068 * functions.
6069 */
6070
6071var _htmlGroupBuilders = {};
6072/**
6073 * All MathML builders. Should be only used in the `define*` and the `build*ML`
6074 * functions.
6075 */
6076
6077var _mathmlGroupBuilders = {};
6078function defineFunction(_ref) {
6079 var {
6080 type,
6081 names,
6082 props,
6083 handler,
6084 htmlBuilder,
6085 mathmlBuilder
6086 } = _ref;
6087 // Set default values of functions
6088 var data = {
6089 type,
6090 numArgs: props.numArgs,
6091 argTypes: props.argTypes,
6092 allowedInArgument: !!props.allowedInArgument,
6093 allowedInText: !!props.allowedInText,
6094 allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath,
6095 numOptionalArgs: props.numOptionalArgs || 0,
6096 infix: !!props.infix,
6097 primitive: !!props.primitive,
6098 handler: handler
6099 };
6100
6101 for (var i = 0; i < names.length; ++i) {
6102 _functions[names[i]] = data;
6103 }
6104
6105 if (type) {
6106 if (htmlBuilder) {
6107 _htmlGroupBuilders[type] = htmlBuilder;
6108 }
6109
6110 if (mathmlBuilder) {
6111 _mathmlGroupBuilders[type] = mathmlBuilder;
6112 }
6113 }
6114}
6115/**
6116 * Use this to register only the HTML and MathML builders for a function (e.g.
6117 * if the function's ParseNode is generated in Parser.js rather than via a
6118 * stand-alone handler provided to `defineFunction`).
6119 */
6120
6121function defineFunctionBuilders(_ref2) {
6122 var {
6123 type,
6124 htmlBuilder,
6125 mathmlBuilder
6126 } = _ref2;
6127 defineFunction({
6128 type,
6129 names: [],
6130 props: {
6131 numArgs: 0
6132 },
6133
6134 handler() {
6135 throw new Error('Should never be called.');
6136 },
6137
6138 htmlBuilder,
6139 mathmlBuilder
6140 });
6141}
6142var normalizeArgument = function normalizeArgument(arg) {
6143 return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg;
6144}; // Since the corresponding buildHTML/buildMathML function expects a
6145// list of elements, we normalize for different kinds of arguments
6146
6147var ordargument = function ordargument(arg) {
6148 return arg.type === "ordgroup" ? arg.body : [arg];
6149};
6150
6151/**
6152 * This file does the main work of building a domTree structure from a parse
6153 * tree. The entry point is the `buildHTML` function, which takes a parse tree.
6154 * Then, the buildExpression, buildGroup, and various groupBuilders functions
6155 * are called, to produce a final HTML tree.
6156 */
6157var makeSpan$1 = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
6158// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
6159// and the text before Rule 19.
6160
6161var binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"];
6162var binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"];
6163var styleMap$1 = {
6164 "display": Style$1.DISPLAY,
6165 "text": Style$1.TEXT,
6166 "script": Style$1.SCRIPT,
6167 "scriptscript": Style$1.SCRIPTSCRIPT
6168};
6169var DomEnum = {
6170 mord: "mord",
6171 mop: "mop",
6172 mbin: "mbin",
6173 mrel: "mrel",
6174 mopen: "mopen",
6175 mclose: "mclose",
6176 mpunct: "mpunct",
6177 minner: "minner"
6178};
6179
6180/**
6181 * Take a list of nodes, build them in order, and return a list of the built
6182 * nodes. documentFragments are flattened into their contents, so the
6183 * returned list contains no fragments. `isRealGroup` is true if `expression`
6184 * is a real group (no atoms will be added on either side), as opposed to
6185 * a partial group (e.g. one created by \color). `surrounding` is an array
6186 * consisting type of nodes that will be added to the left and right.
6187 */
6188var buildExpression$1 = function buildExpression(expression, options, isRealGroup, surrounding) {
6189 if (surrounding === void 0) {
6190 surrounding = [null, null];
6191 }
6192
6193 // Parse expressions into `groups`.
6194 var groups = [];
6195
6196 for (var i = 0; i < expression.length; i++) {
6197 var output = buildGroup$1(expression[i], options);
6198
6199 if (output instanceof DocumentFragment) {
6200 var children = output.children;
6201 groups.push(...children);
6202 } else {
6203 groups.push(output);
6204 }
6205 } // Combine consecutive domTree.symbolNodes into a single symbolNode.
6206
6207
6208 buildCommon.tryCombineChars(groups); // If `expression` is a partial group, let the parent handle spacings
6209 // to avoid processing groups multiple times.
6210
6211 if (!isRealGroup) {
6212 return groups;
6213 }
6214
6215 var glueOptions = options;
6216
6217 if (expression.length === 1) {
6218 var node = expression[0];
6219
6220 if (node.type === "sizing") {
6221 glueOptions = options.havingSize(node.size);
6222 } else if (node.type === "styling") {
6223 glueOptions = options.havingStyle(styleMap$1[node.style]);
6224 }
6225 } // Dummy spans for determining spacings between surrounding atoms.
6226 // If `expression` has no atoms on the left or right, class "leftmost"
6227 // or "rightmost", respectively, is used to indicate it.
6228
6229
6230 var dummyPrev = makeSpan$1([surrounding[0] || "leftmost"], [], options);
6231 var dummyNext = makeSpan$1([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element
6232 // of its `classes` array. A later cleanup should ensure this, for
6233 // instance by changing the signature of `makeSpan`.
6234 // Before determining what spaces to insert, perform bin cancellation.
6235 // Binary operators change to ordinary symbols in some contexts.
6236
6237 var isRoot = isRealGroup === "root";
6238 traverseNonSpaceNodes(groups, (node, prev) => {
6239 var prevType = prev.classes[0];
6240 var type = node.classes[0];
6241
6242 if (prevType === "mbin" && utils.contains(binRightCanceller, type)) {
6243 prev.classes[0] = "mord";
6244 } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) {
6245 node.classes[0] = "mord";
6246 }
6247 }, {
6248 node: dummyPrev
6249 }, dummyNext, isRoot);
6250 traverseNonSpaceNodes(groups, (node, prev) => {
6251 var prevType = getTypeOfDomTree(prev);
6252 var type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style.
6253
6254 var space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null;
6255
6256 if (space) {
6257 // Insert glue (spacing) after the `prev`.
6258 return buildCommon.makeGlue(space, glueOptions);
6259 }
6260 }, {
6261 node: dummyPrev
6262 }, dummyNext, isRoot);
6263 return groups;
6264}; // Depth-first traverse non-space `nodes`, calling `callback` with the current and
6265// previous node as arguments, optionally returning a node to insert after the
6266// previous node. `prev` is an object with the previous node and `insertAfter`
6267// function to insert after it. `next` is a node that will be added to the right.
6268// Used for bin cancellation and inserting spacings.
6269
6270var traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, prev, next, isRoot) {
6271 if (next) {
6272 // temporarily append the right node, if exists
6273 nodes.push(next);
6274 }
6275
6276 var i = 0;
6277
6278 for (; i < nodes.length; i++) {
6279 var node = nodes[i];
6280 var partialGroup = checkPartialGroup(node);
6281
6282 if (partialGroup) {
6283 // Recursive DFS
6284 // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array
6285 traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot);
6286 continue;
6287 } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit
6288 // spacing should go between atoms of different classes
6289
6290
6291 var nonspace = !node.hasClass("mspace");
6292
6293 if (nonspace) {
6294 var result = callback(node, prev.node);
6295
6296 if (result) {
6297 if (prev.insertAfter) {
6298 prev.insertAfter(result);
6299 } else {
6300 // insert at front
6301 nodes.unshift(result);
6302 i++;
6303 }
6304 }
6305 }
6306
6307 if (nonspace) {
6308 prev.node = node;
6309 } else if (isRoot && node.hasClass("newline")) {
6310 prev.node = makeSpan$1(["leftmost"]); // treat like beginning of line
6311 }
6312
6313 prev.insertAfter = (index => n => {
6314 nodes.splice(index + 1, 0, n);
6315 i++;
6316 })(i);
6317 }
6318
6319 if (next) {
6320 nodes.pop();
6321 }
6322}; // Check if given node is a partial group, i.e., does not affect spacing around.
6323
6324
6325var checkPartialGroup = function checkPartialGroup(node) {
6326 if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) {
6327 return node;
6328 }
6329
6330 return null;
6331}; // Return the outermost node of a domTree.
6332
6333
6334var getOutermostNode = function getOutermostNode(node, side) {
6335 var partialGroup = checkPartialGroup(node);
6336
6337 if (partialGroup) {
6338 var children = partialGroup.children;
6339
6340 if (children.length) {
6341 if (side === "right") {
6342 return getOutermostNode(children[children.length - 1], "right");
6343 } else if (side === "left") {
6344 return getOutermostNode(children[0], "left");
6345 }
6346 }
6347 }
6348
6349 return node;
6350}; // Return math atom class (mclass) of a domTree.
6351// If `side` is given, it will get the type of the outermost node at given side.
6352
6353
6354var getTypeOfDomTree = function getTypeOfDomTree(node, side) {
6355 if (!node) {
6356 return null;
6357 }
6358
6359 if (side) {
6360 node = getOutermostNode(node, side);
6361 } // This makes a lot of assumptions as to where the type of atom
6362 // appears. We should do a better job of enforcing this.
6363
6364
6365 return DomEnum[node.classes[0]] || null;
6366};
6367var makeNullDelimiter = function makeNullDelimiter(options, classes) {
6368 var moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses());
6369 return makeSpan$1(classes.concat(moreClasses));
6370};
6371/**
6372 * buildGroup is the function that takes a group and calls the correct groupType
6373 * function for it. It also handles the interaction of size and style changes
6374 * between parents and children.
6375 */
6376
6377var buildGroup$1 = function buildGroup(group, options, baseOptions) {
6378 if (!group) {
6379 return makeSpan$1();
6380 }
6381
6382 if (_htmlGroupBuilders[group.type]) {
6383 // Call the groupBuilders function
6384 // $FlowFixMe
6385 var groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account
6386 // for that size difference.
6387
6388 if (baseOptions && options.size !== baseOptions.size) {
6389 groupNode = makeSpan$1(options.sizingClasses(baseOptions), [groupNode], options);
6390 var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
6391 groupNode.height *= multiplier;
6392 groupNode.depth *= multiplier;
6393 }
6394
6395 return groupNode;
6396 } else {
6397 throw new ParseError("Got group of unknown type: '" + group.type + "'");
6398 }
6399};
6400/**
6401 * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`)
6402 * into an unbreakable HTML node of class .base, with proper struts to
6403 * guarantee correct vertical extent. `buildHTML` calls this repeatedly to
6404 * make up the entire expression as a sequence of unbreakable units.
6405 */
6406
6407function buildHTMLUnbreakable(children, options) {
6408 // Compute height and depth of this chunk.
6409 var body = makeSpan$1(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at
6410 // the height of the expression, and the bottom of the HTML element
6411 // falls at the depth of the expression.
6412
6413 var strut = makeSpan$1(["strut"]);
6414 strut.style.height = makeEm(body.height + body.depth);
6415
6416 if (body.depth) {
6417 strut.style.verticalAlign = makeEm(-body.depth);
6418 }
6419
6420 body.children.unshift(strut);
6421 return body;
6422}
6423/**
6424 * Take an entire parse tree, and build it into an appropriate set of HTML
6425 * nodes.
6426 */
6427
6428
6429function buildHTML(tree, options) {
6430 // Strip off outer tag wrapper for processing below.
6431 var tag = null;
6432
6433 if (tree.length === 1 && tree[0].type === "tag") {
6434 tag = tree[0].tag;
6435 tree = tree[0].body;
6436 } // Build the expression contained in the tree
6437
6438
6439 var expression = buildExpression$1(tree, options, "root");
6440 var eqnNum;
6441
6442 if (expression.length === 2 && expression[1].hasClass("tag")) {
6443 // An environment with automatic equation numbers, e.g. {gather}.
6444 eqnNum = expression.pop();
6445 }
6446
6447 var children = []; // Create one base node for each chunk between potential line breaks.
6448 // The TeXBook [p.173] says "A formula will be broken only after a
6449 // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary
6450 // operation symbol like $+$ or $-$ or $\times$, where the relation or
6451 // binary operation is on the ``outer level'' of the formula (i.e., not
6452 // enclosed in {...} and not part of an \over construction)."
6453
6454 var parts = [];
6455
6456 for (var i = 0; i < expression.length; i++) {
6457 parts.push(expression[i]);
6458
6459 if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) {
6460 // Put any post-operator glue on same line as operator.
6461 // Watch for \nobreak along the way, and stop at \newline.
6462 var nobreak = false;
6463
6464 while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) {
6465 i++;
6466 parts.push(expression[i]);
6467
6468 if (expression[i].hasClass("nobreak")) {
6469 nobreak = true;
6470 }
6471 } // Don't allow break if \nobreak among the post-operator glue.
6472
6473
6474 if (!nobreak) {
6475 children.push(buildHTMLUnbreakable(parts, options));
6476 parts = [];
6477 }
6478 } else if (expression[i].hasClass("newline")) {
6479 // Write the line except the newline
6480 parts.pop();
6481
6482 if (parts.length > 0) {
6483 children.push(buildHTMLUnbreakable(parts, options));
6484 parts = [];
6485 } // Put the newline at the top level
6486
6487
6488 children.push(expression[i]);
6489 }
6490 }
6491
6492 if (parts.length > 0) {
6493 children.push(buildHTMLUnbreakable(parts, options));
6494 } // Now, if there was a tag, build it too and append it as a final child.
6495
6496
6497 var tagChild;
6498
6499 if (tag) {
6500 tagChild = buildHTMLUnbreakable(buildExpression$1(tag, options, true));
6501 tagChild.classes = ["tag"];
6502 children.push(tagChild);
6503 } else if (eqnNum) {
6504 children.push(eqnNum);
6505 }
6506
6507 var htmlNode = makeSpan$1(["katex-html"], children);
6508 htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children
6509 // (the height of the enclosing htmlNode) for proper vertical alignment.
6510
6511 if (tagChild) {
6512 var strut = tagChild.children[0];
6513 strut.style.height = makeEm(htmlNode.height + htmlNode.depth);
6514
6515 if (htmlNode.depth) {
6516 strut.style.verticalAlign = makeEm(-htmlNode.depth);
6517 }
6518 }
6519
6520 return htmlNode;
6521}
6522
6523/**
6524 * These objects store data about MathML nodes. This is the MathML equivalent
6525 * of the types in domTree.js. Since MathML handles its own rendering, and
6526 * since we're mainly using MathML to improve accessibility, we don't manage
6527 * any of the styling state that the plain DOM nodes do.
6528 *
6529 * The `toNode` and `toMarkup` functions work simlarly to how they do in
6530 * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
6531 */
6532function newDocumentFragment(children) {
6533 return new DocumentFragment(children);
6534}
6535/**
6536 * This node represents a general purpose MathML node of any type. The
6537 * constructor requires the type of node to create (for example, `"mo"` or
6538 * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
6539 */
6540
6541class MathNode {
6542 constructor(type, children, classes) {
6543 this.type = void 0;
6544 this.attributes = void 0;
6545 this.children = void 0;
6546 this.classes = void 0;
6547 this.type = type;
6548 this.attributes = {};
6549 this.children = children || [];
6550 this.classes = classes || [];
6551 }
6552 /**
6553 * Sets an attribute on a MathML node. MathML depends on attributes to convey a
6554 * semantic content, so this is used heavily.
6555 */
6556
6557
6558 setAttribute(name, value) {
6559 this.attributes[name] = value;
6560 }
6561 /**
6562 * Gets an attribute on a MathML node.
6563 */
6564
6565
6566 getAttribute(name) {
6567 return this.attributes[name];
6568 }
6569 /**
6570 * Converts the math node into a MathML-namespaced DOM element.
6571 */
6572
6573
6574 toNode() {
6575 var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type);
6576
6577 for (var attr in this.attributes) {
6578 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
6579 node.setAttribute(attr, this.attributes[attr]);
6580 }
6581 }
6582
6583 if (this.classes.length > 0) {
6584 node.className = createClass(this.classes);
6585 }
6586
6587 for (var i = 0; i < this.children.length; i++) {
6588 node.appendChild(this.children[i].toNode());
6589 }
6590
6591 return node;
6592 }
6593 /**
6594 * Converts the math node into an HTML markup string.
6595 */
6596
6597
6598 toMarkup() {
6599 var markup = "<" + this.type; // Add the attributes
6600
6601 for (var attr in this.attributes) {
6602 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
6603 markup += " " + attr + "=\"";
6604 markup += utils.escape(this.attributes[attr]);
6605 markup += "\"";
6606 }
6607 }
6608
6609 if (this.classes.length > 0) {
6610 markup += " class =\"" + utils.escape(createClass(this.classes)) + "\"";
6611 }
6612
6613 markup += ">";
6614
6615 for (var i = 0; i < this.children.length; i++) {
6616 markup += this.children[i].toMarkup();
6617 }
6618
6619 markup += "</" + this.type + ">";
6620 return markup;
6621 }
6622 /**
6623 * Converts the math node into a string, similar to innerText, but escaped.
6624 */
6625
6626
6627 toText() {
6628 return this.children.map(child => child.toText()).join("");
6629 }
6630
6631}
6632/**
6633 * This node represents a piece of text.
6634 */
6635
6636class TextNode {
6637 constructor(text) {
6638 this.text = void 0;
6639 this.text = text;
6640 }
6641 /**
6642 * Converts the text node into a DOM text node.
6643 */
6644
6645
6646 toNode() {
6647 return document.createTextNode(this.text);
6648 }
6649 /**
6650 * Converts the text node into escaped HTML markup
6651 * (representing the text itself).
6652 */
6653
6654
6655 toMarkup() {
6656 return utils.escape(this.toText());
6657 }
6658 /**
6659 * Converts the text node into a string
6660 * (representing the text iteself).
6661 */
6662
6663
6664 toText() {
6665 return this.text;
6666 }
6667
6668}
6669/**
6670 * This node represents a space, but may render as <mspace.../> or as text,
6671 * depending on the width.
6672 */
6673
6674class SpaceNode {
6675 /**
6676 * Create a Space node with width given in CSS ems.
6677 */
6678 constructor(width) {
6679 this.width = void 0;
6680 this.character = void 0;
6681 this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
6682 // for a table of space-like characters. We use Unicode
6683 // representations instead of &LongNames; as it's not clear how to
6684 // make the latter via document.createTextNode.
6685
6686 if (width >= 0.05555 && width <= 0.05556) {
6687 this.character = "\u200a"; //  
6688 } else if (width >= 0.1666 && width <= 0.1667) {
6689 this.character = "\u2009"; //  
6690 } else if (width >= 0.2222 && width <= 0.2223) {
6691 this.character = "\u2005"; //  
6692 } else if (width >= 0.2777 && width <= 0.2778) {
6693 this.character = "\u2005\u200a"; //   
6694 } else if (width >= -0.05556 && width <= -0.05555) {
6695 this.character = "\u200a\u2063"; // ​
6696 } else if (width >= -0.1667 && width <= -0.1666) {
6697 this.character = "\u2009\u2063"; // ​
6698 } else if (width >= -0.2223 && width <= -0.2222) {
6699 this.character = "\u205f\u2063"; // ​
6700 } else if (width >= -0.2778 && width <= -0.2777) {
6701 this.character = "\u2005\u2063"; // ​
6702 } else {
6703 this.character = null;
6704 }
6705 }
6706 /**
6707 * Converts the math node into a MathML-namespaced DOM element.
6708 */
6709
6710
6711 toNode() {
6712 if (this.character) {
6713 return document.createTextNode(this.character);
6714 } else {
6715 var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace");
6716 node.setAttribute("width", makeEm(this.width));
6717 return node;
6718 }
6719 }
6720 /**
6721 * Converts the math node into an HTML markup string.
6722 */
6723
6724
6725 toMarkup() {
6726 if (this.character) {
6727 return "<mtext>" + this.character + "</mtext>";
6728 } else {
6729 return "<mspace width=\"" + makeEm(this.width) + "\"/>";
6730 }
6731 }
6732 /**
6733 * Converts the math node into a string, similar to innerText.
6734 */
6735
6736
6737 toText() {
6738 if (this.character) {
6739 return this.character;
6740 } else {
6741 return " ";
6742 }
6743 }
6744
6745}
6746
6747var mathMLTree = {
6748 MathNode,
6749 TextNode,
6750 SpaceNode,
6751 newDocumentFragment
6752};
6753
6754/**
6755 * This file converts a parse tree into a cooresponding MathML tree. The main
6756 * entry point is the `buildMathML` function, which takes a parse tree from the
6757 * parser.
6758 */
6759
6760/**
6761 * Takes a symbol and converts it into a MathML text node after performing
6762 * optional replacement from symbols.js.
6763 */
6764var makeText = function makeText(text, mode, options) {
6765 if (symbols[mode][text] && symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.substr(4, 2) === "tt" || options.font && options.font.substr(4, 2) === "tt"))) {
6766 text = symbols[mode][text].replace;
6767 }
6768
6769 return new mathMLTree.TextNode(text);
6770};
6771/**
6772 * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
6773 * unless the array has length 1. Always returns a single node.
6774 */
6775
6776var makeRow = function makeRow(body) {
6777 if (body.length === 1) {
6778 return body[0];
6779 } else {
6780 return new mathMLTree.MathNode("mrow", body);
6781 }
6782};
6783/**
6784 * Returns the math variant as a string or null if none is required.
6785 */
6786
6787var getVariant = function getVariant(group, options) {
6788 // Handle \text... font specifiers as best we can.
6789 // MathML has a limited list of allowable mathvariant specifiers; see
6790 // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
6791 if (options.fontFamily === "texttt") {
6792 return "monospace";
6793 } else if (options.fontFamily === "textsf") {
6794 if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6795 return "sans-serif-bold-italic";
6796 } else if (options.fontShape === "textit") {
6797 return "sans-serif-italic";
6798 } else if (options.fontWeight === "textbf") {
6799 return "bold-sans-serif";
6800 } else {
6801 return "sans-serif";
6802 }
6803 } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6804 return "bold-italic";
6805 } else if (options.fontShape === "textit") {
6806 return "italic";
6807 } else if (options.fontWeight === "textbf") {
6808 return "bold";
6809 }
6810
6811 var font = options.font;
6812
6813 if (!font || font === "mathnormal") {
6814 return null;
6815 }
6816
6817 var mode = group.mode;
6818
6819 if (font === "mathit") {
6820 return "italic";
6821 } else if (font === "boldsymbol") {
6822 return group.type === "textord" ? "bold" : "bold-italic";
6823 } else if (font === "mathbf") {
6824 return "bold";
6825 } else if (font === "mathbb") {
6826 return "double-struck";
6827 } else if (font === "mathfrak") {
6828 return "fraktur";
6829 } else if (font === "mathscr" || font === "mathcal") {
6830 // MathML makes no distinction between script and caligrahpic
6831 return "script";
6832 } else if (font === "mathsf") {
6833 return "sans-serif";
6834 } else if (font === "mathtt") {
6835 return "monospace";
6836 }
6837
6838 var text = group.text;
6839
6840 if (utils.contains(["\\imath", "\\jmath"], text)) {
6841 return null;
6842 }
6843
6844 if (symbols[mode][text] && symbols[mode][text].replace) {
6845 text = symbols[mode][text].replace;
6846 }
6847
6848 var fontName = buildCommon.fontMap[font].fontName;
6849
6850 if (getCharacterMetrics(text, fontName, mode)) {
6851 return buildCommon.fontMap[font].variant;
6852 }
6853
6854 return null;
6855};
6856/**
6857 * Takes a list of nodes, builds them, and returns a list of the generated
6858 * MathML nodes. Also combine consecutive <mtext> outputs into a single
6859 * <mtext> tag.
6860 */
6861
6862var buildExpression = function buildExpression(expression, options, isOrdgroup) {
6863 if (expression.length === 1) {
6864 var group = buildGroup(expression[0], options);
6865
6866 if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
6867 // When TeX writers want to suppress spacing on an operator,
6868 // they often put the operator by itself inside braces.
6869 group.setAttribute("lspace", "0em");
6870 group.setAttribute("rspace", "0em");
6871 }
6872
6873 return [group];
6874 }
6875
6876 var groups = [];
6877 var lastGroup;
6878
6879 for (var i = 0; i < expression.length; i++) {
6880 var _group = buildGroup(expression[i], options);
6881
6882 if (_group instanceof MathNode && lastGroup instanceof MathNode) {
6883 // Concatenate adjacent <mtext>s
6884 if (_group.type === 'mtext' && lastGroup.type === 'mtext' && _group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) {
6885 lastGroup.children.push(..._group.children);
6886 continue; // Concatenate adjacent <mn>s
6887 } else if (_group.type === 'mn' && lastGroup.type === 'mn') {
6888 lastGroup.children.push(..._group.children);
6889 continue; // Concatenate <mn>...</mn> followed by <mi>.</mi>
6890 } else if (_group.type === 'mi' && _group.children.length === 1 && lastGroup.type === 'mn') {
6891 var child = _group.children[0];
6892
6893 if (child instanceof TextNode && child.text === '.') {
6894 lastGroup.children.push(..._group.children);
6895 continue;
6896 }
6897 } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) {
6898 var lastChild = lastGroup.children[0];
6899
6900 if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (_group.type === 'mo' || _group.type === 'mi' || _group.type === 'mn')) {
6901 var _child = _group.children[0];
6902
6903 if (_child instanceof TextNode && _child.text.length > 0) {
6904 // Overlay with combining character long solidus
6905 _child.text = _child.text.slice(0, 1) + "\u0338" + _child.text.slice(1);
6906 groups.pop();
6907 }
6908 }
6909 }
6910 }
6911
6912 groups.push(_group);
6913 lastGroup = _group;
6914 }
6915
6916 return groups;
6917};
6918/**
6919 * Equivalent to buildExpression, but wraps the elements in an <mrow>
6920 * if there's more than one. Returns a single node instead of an array.
6921 */
6922
6923var buildExpressionRow = function buildExpressionRow(expression, options, isOrdgroup) {
6924 return makeRow(buildExpression(expression, options, isOrdgroup));
6925};
6926/**
6927 * Takes a group from the parser and calls the appropriate groupBuilders function
6928 * on it to produce a MathML node.
6929 */
6930
6931var buildGroup = function buildGroup(group, options) {
6932 if (!group) {
6933 return new mathMLTree.MathNode("mrow");
6934 }
6935
6936 if (_mathmlGroupBuilders[group.type]) {
6937 // Call the groupBuilders function
6938 // $FlowFixMe
6939 var result = _mathmlGroupBuilders[group.type](group, options); // $FlowFixMe
6940
6941 return result;
6942 } else {
6943 throw new ParseError("Got group of unknown type: '" + group.type + "'");
6944 }
6945};
6946/**
6947 * Takes a full parse tree and settings and builds a MathML representation of
6948 * it. In particular, we put the elements from building the parse tree into a
6949 * <semantics> tag so we can also include that TeX source as an annotation.
6950 *
6951 * Note that we actually return a domTree element with a `<math>` inside it so
6952 * we can do appropriate styling.
6953 */
6954
6955function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) {
6956 var expression = buildExpression(tree, options); // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes
6957 // and add spacing nodes. This is necessary only adjacent to math operators
6958 // like \sin or \lim or to subsup elements that contain math operators.
6959 // MathML takes care of the other spacing issues.
6960 // Wrap up the expression in an mrow so it is presented in the semantics
6961 // tag correctly, unless it's a single <mrow> or <mtable>.
6962
6963 var wrapper;
6964
6965 if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) {
6966 wrapper = expression[0];
6967 } else {
6968 wrapper = new mathMLTree.MathNode("mrow", expression);
6969 } // Build a TeX annotation of the source
6970
6971
6972 var annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]);
6973 annotation.setAttribute("encoding", "application/x-tex");
6974 var semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]);
6975 var math = new mathMLTree.MathNode("math", [semantics]);
6976 math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
6977
6978 if (isDisplayMode) {
6979 math.setAttribute("display", "block");
6980 } // You can't style <math> nodes, so we wrap the node in a span.
6981 // NOTE: The span class is not typed to have <math> nodes as children, and
6982 // we don't want to make the children type more generic since the children
6983 // of span are expected to have more fields in `buildHtml` contexts.
6984
6985
6986 var wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe
6987
6988 return buildCommon.makeSpan([wrapperClass], [math]);
6989}
6990
6991var optionsFromSettings = function optionsFromSettings(settings) {
6992 return new Options({
6993 style: settings.displayMode ? Style$1.DISPLAY : Style$1.TEXT,
6994 maxSize: settings.maxSize,
6995 minRuleThickness: settings.minRuleThickness
6996 });
6997};
6998
6999var displayWrap = function displayWrap(node, settings) {
7000 if (settings.displayMode) {
7001 var classes = ["katex-display"];
7002
7003 if (settings.leqno) {
7004 classes.push("leqno");
7005 }
7006
7007 if (settings.fleqn) {
7008 classes.push("fleqn");
7009 }
7010
7011 node = buildCommon.makeSpan(classes, [node]);
7012 }
7013
7014 return node;
7015};
7016
7017var buildTree = function buildTree(tree, expression, settings) {
7018 var options = optionsFromSettings(settings);
7019 var katexNode;
7020
7021 if (settings.output === "mathml") {
7022 return buildMathML(tree, expression, options, settings.displayMode, true);
7023 } else if (settings.output === "html") {
7024 var htmlNode = buildHTML(tree, options);
7025 katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
7026 } else {
7027 var mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false);
7028
7029 var _htmlNode = buildHTML(tree, options);
7030
7031 katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, _htmlNode]);
7032 }
7033
7034 return displayWrap(katexNode, settings);
7035};
7036var buildHTMLTree = function buildHTMLTree(tree, expression, settings) {
7037 var options = optionsFromSettings(settings);
7038 var htmlNode = buildHTML(tree, options);
7039 var katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
7040 return displayWrap(katexNode, settings);
7041};
7042
7043/**
7044 * This file provides support to buildMathML.js and buildHTML.js
7045 * for stretchy wide elements rendered from SVG files
7046 * and other CSS trickery.
7047 */
7048var stretchyCodePoint = {
7049 widehat: "^",
7050 widecheck: "ˇ",
7051 widetilde: "~",
7052 utilde: "~",
7053 overleftarrow: "\u2190",
7054 underleftarrow: "\u2190",
7055 xleftarrow: "\u2190",
7056 overrightarrow: "\u2192",
7057 underrightarrow: "\u2192",
7058 xrightarrow: "\u2192",
7059 underbrace: "\u23df",
7060 overbrace: "\u23de",
7061 overgroup: "\u23e0",
7062 undergroup: "\u23e1",
7063 overleftrightarrow: "\u2194",
7064 underleftrightarrow: "\u2194",
7065 xleftrightarrow: "\u2194",
7066 Overrightarrow: "\u21d2",
7067 xRightarrow: "\u21d2",
7068 overleftharpoon: "\u21bc",
7069 xleftharpoonup: "\u21bc",
7070 overrightharpoon: "\u21c0",
7071 xrightharpoonup: "\u21c0",
7072 xLeftarrow: "\u21d0",
7073 xLeftrightarrow: "\u21d4",
7074 xhookleftarrow: "\u21a9",
7075 xhookrightarrow: "\u21aa",
7076 xmapsto: "\u21a6",
7077 xrightharpoondown: "\u21c1",
7078 xleftharpoondown: "\u21bd",
7079 xrightleftharpoons: "\u21cc",
7080 xleftrightharpoons: "\u21cb",
7081 xtwoheadleftarrow: "\u219e",
7082 xtwoheadrightarrow: "\u21a0",
7083 xlongequal: "=",
7084 xtofrom: "\u21c4",
7085 xrightleftarrows: "\u21c4",
7086 xrightequilibrium: "\u21cc",
7087 // Not a perfect match.
7088 xleftequilibrium: "\u21cb",
7089 // None better available.
7090 "\\cdrightarrow": "\u2192",
7091 "\\cdleftarrow": "\u2190",
7092 "\\cdlongequal": "="
7093};
7094
7095var mathMLnode = function mathMLnode(label) {
7096 var node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label.replace(/^\\/, '')])]);
7097 node.setAttribute("stretchy", "true");
7098 return node;
7099}; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts.
7100// Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>)
7101// Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>)
7102// Licensed under the SIL Open Font License, Version 1.1.
7103// See \nhttp://scripts.sil.org/OFL
7104// Very Long SVGs
7105// Many of the KaTeX stretchy wide elements use a long SVG image and an
7106// overflow: hidden tactic to achieve a stretchy image while avoiding
7107// distortion of arrowheads or brace corners.
7108// The SVG typically contains a very long (400 em) arrow.
7109// The SVG is in a container span that has overflow: hidden, so the span
7110// acts like a window that exposes only part of the SVG.
7111// The SVG always has a longer, thinner aspect ratio than the container span.
7112// After the SVG fills 100% of the height of the container span,
7113// there is a long arrow shaft left over. That left-over shaft is not shown.
7114// Instead, it is sliced off because the span's CSS has overflow: hidden.
7115// Thus, the reader sees an arrow that matches the subject matter width
7116// without distortion.
7117// Some functions, such as \cancel, need to vary their aspect ratio. These
7118// functions do not get the overflow SVG treatment.
7119// Second Brush Stroke
7120// Low resolution monitors struggle to display images in fine detail.
7121// So browsers apply anti-aliasing. A long straight arrow shaft therefore
7122// will sometimes appear as if it has a blurred edge.
7123// To mitigate this, these SVG files contain a second "brush-stroke" on the
7124// arrow shafts. That is, a second long thin rectangular SVG path has been
7125// written directly on top of each arrow shaft. This reinforcement causes
7126// some of the screen pixels to display as black instead of the anti-aliased
7127// gray pixel that a single path would generate. So we get arrow shafts
7128// whose edges appear to be sharper.
7129// In the katexImagesData object just below, the dimensions all
7130// correspond to path geometry inside the relevant SVG.
7131// For example, \overrightarrow uses the same arrowhead as glyph U+2192
7132// from the KaTeX Main font. The scaling factor is 1000.
7133// That is, inside the font, that arrowhead is 522 units tall, which
7134// corresponds to 0.522 em inside the document.
7135
7136
7137var katexImagesData = {
7138 // path(s), minWidth, height, align
7139 overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
7140 overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
7141 underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
7142 underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
7143 xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"],
7144 "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"],
7145 // CD minwwidth2.5pc
7146 xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"],
7147 "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"],
7148 Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"],
7149 xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"],
7150 xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"],
7151 overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"],
7152 xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"],
7153 xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"],
7154 overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
7155 xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
7156 xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"],
7157 xlongequal: [["longequal"], 0.888, 334, "xMinYMin"],
7158 "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"],
7159 xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"],
7160 xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"],
7161 overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
7162 overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548],
7163 underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548],
7164 underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
7165 xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522],
7166 xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560],
7167 xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716],
7168 xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716],
7169 xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522],
7170 xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522],
7171 overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
7172 underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
7173 overgroup: [["leftgroup", "rightgroup"], 0.888, 342],
7174 undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342],
7175 xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522],
7176 xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528],
7177 // The next three arrows are from the mhchem package.
7178 // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the
7179 // document as \xrightarrow or \xrightleftharpoons. Those have
7180 // min-length = 1.75em, so we set min-length on these next three to match.
7181 xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901],
7182 xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716],
7183 xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716]
7184};
7185
7186var groupLength = function groupLength(arg) {
7187 if (arg.type === "ordgroup") {
7188 return arg.body.length;
7189 } else {
7190 return 1;
7191 }
7192};
7193
7194var svgSpan = function svgSpan(group, options) {
7195 // Create a span with inline SVG for the element.
7196 function buildSvgSpan_() {
7197 var viewBoxWidth = 400000; // default
7198
7199 var label = group.label.substr(1);
7200
7201 if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) {
7202 // Each type in the `if` statement corresponds to one of the ParseNode
7203 // types below. This narrowing is required to access `grp.base`.
7204 // $FlowFixMe
7205 var grp = group; // There are four SVG images available for each function.
7206 // Choose a taller image when there are more characters.
7207
7208 var numChars = groupLength(grp.base);
7209 var viewBoxHeight;
7210 var pathName;
7211
7212 var _height;
7213
7214 if (numChars > 5) {
7215 if (label === "widehat" || label === "widecheck") {
7216 viewBoxHeight = 420;
7217 viewBoxWidth = 2364;
7218 _height = 0.42;
7219 pathName = label + "4";
7220 } else {
7221 viewBoxHeight = 312;
7222 viewBoxWidth = 2340;
7223 _height = 0.34;
7224 pathName = "tilde4";
7225 }
7226 } else {
7227 var imgIndex = [1, 1, 2, 2, 3, 3][numChars];
7228
7229 if (label === "widehat" || label === "widecheck") {
7230 viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex];
7231 viewBoxHeight = [0, 239, 300, 360, 420][imgIndex];
7232 _height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex];
7233 pathName = label + imgIndex;
7234 } else {
7235 viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex];
7236 viewBoxHeight = [0, 260, 286, 306, 312][imgIndex];
7237 _height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex];
7238 pathName = "tilde" + imgIndex;
7239 }
7240 }
7241
7242 var path = new PathNode(pathName);
7243 var svgNode = new SvgNode([path], {
7244 "width": "100%",
7245 "height": makeEm(_height),
7246 "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight,
7247 "preserveAspectRatio": "none"
7248 });
7249 return {
7250 span: buildCommon.makeSvgSpan([], [svgNode], options),
7251 minWidth: 0,
7252 height: _height
7253 };
7254 } else {
7255 var spans = [];
7256 var data = katexImagesData[label];
7257 var [paths, _minWidth, _viewBoxHeight] = data;
7258
7259 var _height2 = _viewBoxHeight / 1000;
7260
7261 var numSvgChildren = paths.length;
7262 var widthClasses;
7263 var aligns;
7264
7265 if (numSvgChildren === 1) {
7266 // $FlowFixMe: All these cases must be of the 4-tuple type.
7267 var align1 = data[3];
7268 widthClasses = ["hide-tail"];
7269 aligns = [align1];
7270 } else if (numSvgChildren === 2) {
7271 widthClasses = ["halfarrow-left", "halfarrow-right"];
7272 aligns = ["xMinYMin", "xMaxYMin"];
7273 } else if (numSvgChildren === 3) {
7274 widthClasses = ["brace-left", "brace-center", "brace-right"];
7275 aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"];
7276 } else {
7277 throw new Error("Correct katexImagesData or update code here to support\n " + numSvgChildren + " children.");
7278 }
7279
7280 for (var i = 0; i < numSvgChildren; i++) {
7281 var _path = new PathNode(paths[i]);
7282
7283 var _svgNode = new SvgNode([_path], {
7284 "width": "400em",
7285 "height": makeEm(_height2),
7286 "viewBox": "0 0 " + viewBoxWidth + " " + _viewBoxHeight,
7287 "preserveAspectRatio": aligns[i] + " slice"
7288 });
7289
7290 var _span = buildCommon.makeSvgSpan([widthClasses[i]], [_svgNode], options);
7291
7292 if (numSvgChildren === 1) {
7293 return {
7294 span: _span,
7295 minWidth: _minWidth,
7296 height: _height2
7297 };
7298 } else {
7299 _span.style.height = makeEm(_height2);
7300 spans.push(_span);
7301 }
7302 }
7303
7304 return {
7305 span: buildCommon.makeSpan(["stretchy"], spans, options),
7306 minWidth: _minWidth,
7307 height: _height2
7308 };
7309 }
7310 } // buildSvgSpan_()
7311
7312
7313 var {
7314 span,
7315 minWidth,
7316 height
7317 } = buildSvgSpan_(); // Note that we are returning span.depth = 0.
7318 // Any adjustments relative to the baseline must be done in buildHTML.
7319
7320 span.height = height;
7321 span.style.height = makeEm(height);
7322
7323 if (minWidth > 0) {
7324 span.style.minWidth = makeEm(minWidth);
7325 }
7326
7327 return span;
7328};
7329
7330var encloseSpan = function encloseSpan(inner, label, topPad, bottomPad, options) {
7331 // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl
7332 var img;
7333 var totalHeight = inner.height + inner.depth + topPad + bottomPad;
7334
7335 if (/fbox|color|angl/.test(label)) {
7336 img = buildCommon.makeSpan(["stretchy", label], [], options);
7337
7338 if (label === "fbox") {
7339 var color = options.color && options.getColor();
7340
7341 if (color) {
7342 img.style.borderColor = color;
7343 }
7344 }
7345 } else {
7346 // \cancel, \bcancel, or \xcancel
7347 // Since \cancel's SVG is inline and it omits the viewBox attribute,
7348 // its stroke-width will not vary with span area.
7349 var lines = [];
7350
7351 if (/^[bx]cancel$/.test(label)) {
7352 lines.push(new LineNode({
7353 "x1": "0",
7354 "y1": "0",
7355 "x2": "100%",
7356 "y2": "100%",
7357 "stroke-width": "0.046em"
7358 }));
7359 }
7360
7361 if (/^x?cancel$/.test(label)) {
7362 lines.push(new LineNode({
7363 "x1": "0",
7364 "y1": "100%",
7365 "x2": "100%",
7366 "y2": "0",
7367 "stroke-width": "0.046em"
7368 }));
7369 }
7370
7371 var svgNode = new SvgNode(lines, {
7372 "width": "100%",
7373 "height": makeEm(totalHeight)
7374 });
7375 img = buildCommon.makeSvgSpan([], [svgNode], options);
7376 }
7377
7378 img.height = totalHeight;
7379 img.style.height = makeEm(totalHeight);
7380 return img;
7381};
7382
7383var stretchy = {
7384 encloseSpan,
7385 mathMLnode,
7386 svgSpan
7387};
7388
7389/**
7390 * Asserts that the node is of the given type and returns it with stricter
7391 * typing. Throws if the node's type does not match.
7392 */
7393function assertNodeType(node, type) {
7394 if (!node || node.type !== type) {
7395 throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node)));
7396 } // $FlowFixMe, >=0.125
7397
7398
7399 return node;
7400}
7401/**
7402 * Returns the node more strictly typed iff it is of the given type. Otherwise,
7403 * returns null.
7404 */
7405
7406function assertSymbolNodeType(node) {
7407 var typedNode = checkSymbolNodeType(node);
7408
7409 if (!typedNode) {
7410 throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node)));
7411 }
7412
7413 return typedNode;
7414}
7415/**
7416 * Returns the node more strictly typed iff it is of the given type. Otherwise,
7417 * returns null.
7418 */
7419
7420function checkSymbolNodeType(node) {
7421 if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) {
7422 // $FlowFixMe
7423 return node;
7424 }
7425
7426 return null;
7427}
7428
7429// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but
7430// also "supsub" since an accent can affect super/subscripting.
7431var htmlBuilder$a = (grp, options) => {
7432 // Accents are handled in the TeXbook pg. 443, rule 12.
7433 var base;
7434 var group;
7435 var supSubGroup;
7436
7437 if (grp && grp.type === "supsub") {
7438 // If our base is a character box, and we have superscripts and
7439 // subscripts, the supsub will defer to us. In particular, we want
7440 // to attach the superscripts and subscripts to the inner body (so
7441 // that the position of the superscripts and subscripts won't be
7442 // affected by the height of the accent). We accomplish this by
7443 // sticking the base of the accent into the base of the supsub, and
7444 // rendering that, while keeping track of where the accent is.
7445 // The real accent group is the base of the supsub group
7446 group = assertNodeType(grp.base, "accent"); // The character box is the base of the accent group
7447
7448 base = group.base; // Stick the character box into the base of the supsub group
7449
7450 grp.base = base; // Rerender the supsub group with its new base, and store that
7451 // result.
7452
7453 supSubGroup = assertSpan(buildGroup$1(grp, options)); // reset original base
7454
7455 grp.base = group;
7456 } else {
7457 group = assertNodeType(grp, "accent");
7458 base = group.base;
7459 } // Build the base group
7460
7461
7462 var body = buildGroup$1(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character?
7463
7464 var mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the
7465 // nucleus is not a single character, let s = 0; otherwise set s to the
7466 // kern amount for the nucleus followed by the \skewchar of its font."
7467 // Note that our skew metrics are just the kern between each character
7468 // and the skewchar.
7469
7470 var skew = 0;
7471
7472 if (mustShift) {
7473 // If the base is a character box, then we want the skew of the
7474 // innermost character. To do that, we find the innermost character:
7475 var baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it
7476
7477 var baseGroup = buildGroup$1(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol.
7478
7479 skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we
7480 // removed with getBaseElem might contain things like \color which
7481 // we can't get rid of.
7482 // TODO(emily): Find a better way to get the skew
7483 }
7484
7485 var accentBelow = group.label === "\\c"; // calculate the amount of space between the body and the accent
7486
7487 var clearance = accentBelow ? body.height + body.depth : Math.min(body.height, options.fontMetrics().xHeight); // Build the accent
7488
7489 var accentBody;
7490
7491 if (!group.isStretchy) {
7492 var accent;
7493 var width;
7494
7495 if (group.label === "\\vec") {
7496 // Before version 0.9, \vec used the combining font glyph U+20D7.
7497 // But browsers, especially Safari, are not consistent in how they
7498 // render combining characters when not preceded by a character.
7499 // So now we use an SVG.
7500 // If Safari reforms, we should consider reverting to the glyph.
7501 accent = buildCommon.staticSvg("vec", options);
7502 width = buildCommon.svgData.vec[1];
7503 } else {
7504 accent = buildCommon.makeOrd({
7505 mode: group.mode,
7506 text: group.label
7507 }, options, "textord");
7508 accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to
7509 // shift the accent over to a place we don't want.
7510
7511 accent.italic = 0;
7512 width = accent.width;
7513
7514 if (accentBelow) {
7515 clearance += accent.depth;
7516 }
7517 }
7518
7519 accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be
7520 // at least the width of the accent, and overlap directly onto the
7521 // character without any vertical offset.
7522
7523 var accentFull = group.label === "\\textcircled";
7524
7525 if (accentFull) {
7526 accentBody.classes.push('accent-full');
7527 clearance = body.height;
7528 } // Shift the accent over by the skew.
7529
7530
7531 var left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }`
7532 // so that the accent doesn't contribute to the bounding box.
7533 // We need to shift the character by its width (effectively half
7534 // its width) to compensate.
7535
7536 if (!accentFull) {
7537 left -= width / 2;
7538 }
7539
7540 accentBody.style.left = makeEm(left); // \textcircled uses the \bigcirc glyph, so it needs some
7541 // vertical adjustment to match LaTeX.
7542
7543 if (group.label === "\\textcircled") {
7544 accentBody.style.top = ".2em";
7545 }
7546
7547 accentBody = buildCommon.makeVList({
7548 positionType: "firstBaseline",
7549 children: [{
7550 type: "elem",
7551 elem: body
7552 }, {
7553 type: "kern",
7554 size: -clearance
7555 }, {
7556 type: "elem",
7557 elem: accentBody
7558 }]
7559 }, options);
7560 } else {
7561 accentBody = stretchy.svgSpan(group, options);
7562 accentBody = buildCommon.makeVList({
7563 positionType: "firstBaseline",
7564 children: [{
7565 type: "elem",
7566 elem: body
7567 }, {
7568 type: "elem",
7569 elem: accentBody,
7570 wrapperClasses: ["svg-align"],
7571 wrapperStyle: skew > 0 ? {
7572 width: "calc(100% - " + makeEm(2 * skew) + ")",
7573 marginLeft: makeEm(2 * skew)
7574 } : undefined
7575 }]
7576 }, options);
7577 }
7578
7579 var accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options);
7580
7581 if (supSubGroup) {
7582 // Here, we replace the "base" child of the supsub with our newly
7583 // generated accent.
7584 supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the
7585 // accent, we manually recalculate height.
7586
7587 supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not.
7588
7589 supSubGroup.classes[0] = "mord";
7590 return supSubGroup;
7591 } else {
7592 return accentWrap;
7593 }
7594};
7595
7596var mathmlBuilder$9 = (group, options) => {
7597 var accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]);
7598 var node = new mathMLTree.MathNode("mover", [buildGroup(group.base, options), accentNode]);
7599 node.setAttribute("accent", "true");
7600 return node;
7601};
7602
7603var NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|")); // Accents
7604
7605defineFunction({
7606 type: "accent",
7607 names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"],
7608 props: {
7609 numArgs: 1
7610 },
7611 handler: (context, args) => {
7612 var base = normalizeArgument(args[0]);
7613 var isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName);
7614 var isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck";
7615 return {
7616 type: "accent",
7617 mode: context.parser.mode,
7618 label: context.funcName,
7619 isStretchy: isStretchy,
7620 isShifty: isShifty,
7621 base: base
7622 };
7623 },
7624 htmlBuilder: htmlBuilder$a,
7625 mathmlBuilder: mathmlBuilder$9
7626}); // Text-mode accents
7627
7628defineFunction({
7629 type: "accent",
7630 names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"],
7631 props: {
7632 numArgs: 1,
7633 allowedInText: true,
7634 allowedInMath: true,
7635 // unless in strict mode
7636 argTypes: ["primitive"]
7637 },
7638 handler: (context, args) => {
7639 var base = args[0];
7640 var mode = context.parser.mode;
7641
7642 if (mode === "math") {
7643 context.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + context.funcName + " works only in text mode");
7644 mode = "text";
7645 }
7646
7647 return {
7648 type: "accent",
7649 mode: mode,
7650 label: context.funcName,
7651 isStretchy: false,
7652 isShifty: true,
7653 base: base
7654 };
7655 },
7656 htmlBuilder: htmlBuilder$a,
7657 mathmlBuilder: mathmlBuilder$9
7658});
7659
7660// Horizontal overlap functions
7661defineFunction({
7662 type: "accentUnder",
7663 names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"],
7664 props: {
7665 numArgs: 1
7666 },
7667 handler: (_ref, args) => {
7668 var {
7669 parser,
7670 funcName
7671 } = _ref;
7672 var base = args[0];
7673 return {
7674 type: "accentUnder",
7675 mode: parser.mode,
7676 label: funcName,
7677 base: base
7678 };
7679 },
7680 htmlBuilder: (group, options) => {
7681 // Treat under accents much like underlines.
7682 var innerGroup = buildGroup$1(group.base, options);
7683 var accentBody = stretchy.svgSpan(group, options);
7684 var kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns
7685
7686 var vlist = buildCommon.makeVList({
7687 positionType: "top",
7688 positionData: innerGroup.height,
7689 children: [{
7690 type: "elem",
7691 elem: accentBody,
7692 wrapperClasses: ["svg-align"]
7693 }, {
7694 type: "kern",
7695 size: kern
7696 }, {
7697 type: "elem",
7698 elem: innerGroup
7699 }]
7700 }, options);
7701 return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options);
7702 },
7703 mathmlBuilder: (group, options) => {
7704 var accentNode = stretchy.mathMLnode(group.label);
7705 var node = new mathMLTree.MathNode("munder", [buildGroup(group.base, options), accentNode]);
7706 node.setAttribute("accentunder", "true");
7707 return node;
7708 }
7709});
7710
7711// Helper function
7712var paddedNode = group => {
7713 var node = new mathMLTree.MathNode("mpadded", group ? [group] : []);
7714 node.setAttribute("width", "+0.6em");
7715 node.setAttribute("lspace", "0.3em");
7716 return node;
7717}; // Stretchy arrows with an optional argument
7718
7719
7720defineFunction({
7721 type: "xArrow",
7722 names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", // The next 3 functions are here to support the mhchem extension.
7723 // Direct use of these functions is discouraged and may break someday.
7724 "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", // The next 3 functions are here only to support the {CD} environment.
7725 "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"],
7726 props: {
7727 numArgs: 1,
7728 numOptionalArgs: 1
7729 },
7730
7731 handler(_ref, args, optArgs) {
7732 var {
7733 parser,
7734 funcName
7735 } = _ref;
7736 return {
7737 type: "xArrow",
7738 mode: parser.mode,
7739 label: funcName,
7740 body: args[0],
7741 below: optArgs[0]
7742 };
7743 },
7744
7745 // Flow is unable to correctly infer the type of `group`, even though it's
7746 // unamibiguously determined from the passed-in `type` above.
7747 htmlBuilder(group, options) {
7748 var style = options.style; // Build the argument groups in the appropriate style.
7749 // Ref: amsmath.dtx: \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
7750 // Some groups can return document fragments. Handle those by wrapping
7751 // them in a span.
7752
7753 var newOptions = options.havingStyle(style.sup());
7754 var upperGroup = buildCommon.wrapFragment(buildGroup$1(group.body, newOptions, options), options);
7755 var arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd";
7756 upperGroup.classes.push(arrowPrefix + "-arrow-pad");
7757 var lowerGroup;
7758
7759 if (group.below) {
7760 // Build the lower group
7761 newOptions = options.havingStyle(style.sub());
7762 lowerGroup = buildCommon.wrapFragment(buildGroup$1(group.below, newOptions, options), options);
7763 lowerGroup.classes.push(arrowPrefix + "-arrow-pad");
7764 }
7765
7766 var arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0.
7767 // The point we want on the math axis is at 0.5 * arrowBody.height.
7768
7769 var arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi
7770
7771 var upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu
7772
7773 if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") {
7774 upperShift -= upperGroup.depth; // shift up if depth encroaches
7775 } // Generate the vlist
7776
7777
7778 var vlist;
7779
7780 if (lowerGroup) {
7781 var lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111;
7782 vlist = buildCommon.makeVList({
7783 positionType: "individualShift",
7784 children: [{
7785 type: "elem",
7786 elem: upperGroup,
7787 shift: upperShift
7788 }, {
7789 type: "elem",
7790 elem: arrowBody,
7791 shift: arrowShift
7792 }, {
7793 type: "elem",
7794 elem: lowerGroup,
7795 shift: lowerShift
7796 }]
7797 }, options);
7798 } else {
7799 vlist = buildCommon.makeVList({
7800 positionType: "individualShift",
7801 children: [{
7802 type: "elem",
7803 elem: upperGroup,
7804 shift: upperShift
7805 }, {
7806 type: "elem",
7807 elem: arrowBody,
7808 shift: arrowShift
7809 }]
7810 }, options);
7811 } // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
7812
7813
7814 vlist.children[0].children[0].children[1].classes.push("svg-align");
7815 return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options);
7816 },
7817
7818 mathmlBuilder(group, options) {
7819 var arrowNode = stretchy.mathMLnode(group.label);
7820 arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em");
7821 var node;
7822
7823 if (group.body) {
7824 var upperNode = paddedNode(buildGroup(group.body, options));
7825
7826 if (group.below) {
7827 var lowerNode = paddedNode(buildGroup(group.below, options));
7828 node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]);
7829 } else {
7830 node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]);
7831 }
7832 } else if (group.below) {
7833 var _lowerNode = paddedNode(buildGroup(group.below, options));
7834
7835 node = new mathMLTree.MathNode("munder", [arrowNode, _lowerNode]);
7836 } else {
7837 // This should never happen.
7838 // Parser.js throws an error if there is no argument.
7839 node = paddedNode();
7840 node = new mathMLTree.MathNode("mover", [arrowNode, node]);
7841 }
7842
7843 return node;
7844 }
7845
7846});
7847
7848var cdArrowFunctionName = {
7849 ">": "\\\\cdrightarrow",
7850 "<": "\\\\cdleftarrow",
7851 "=": "\\\\cdlongequal",
7852 "A": "\\uparrow",
7853 "V": "\\downarrow",
7854 "|": "\\Vert",
7855 ".": "no arrow"
7856};
7857
7858var newCell = () => {
7859 // Create an empty cell, to be filled below with parse nodes.
7860 // The parseTree from this module must be constructed like the
7861 // one created by parseArray(), so an empty CD cell must
7862 // be a ParseNode<"styling">. And CD is always displaystyle.
7863 // So these values are fixed and flow can do implicit typing.
7864 return {
7865 type: "styling",
7866 body: [],
7867 mode: "math",
7868 style: "display"
7869 };
7870};
7871
7872var isStartOfArrow = node => {
7873 return node.type === "textord" && node.text === "@";
7874};
7875
7876var isLabelEnd = (node, endChar) => {
7877 return (node.type === "mathord" || node.type === "atom") && node.text === endChar;
7878};
7879
7880function cdArrow(arrowChar, labels, parser) {
7881 // Return a parse tree of an arrow and its labels.
7882 // This acts in a way similar to a macro expansion.
7883 var funcName = cdArrowFunctionName[arrowChar];
7884
7885 switch (funcName) {
7886 case "\\\\cdrightarrow":
7887 case "\\\\cdleftarrow":
7888 return parser.callFunction(funcName, [labels[0]], [labels[1]]);
7889
7890 case "\\uparrow":
7891 case "\\downarrow":
7892 {
7893 var leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []);
7894 var bareArrow = {
7895 type: "atom",
7896 text: funcName,
7897 mode: "math",
7898 family: "rel"
7899 };
7900 var sizedArrow = parser.callFunction("\\Big", [bareArrow], []);
7901 var rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []);
7902 var arrowGroup = {
7903 type: "ordgroup",
7904 mode: "math",
7905 body: [leftLabel, sizedArrow, rightLabel]
7906 };
7907 return parser.callFunction("\\\\cdparent", [arrowGroup], []);
7908 }
7909
7910 case "\\\\cdlongequal":
7911 return parser.callFunction("\\\\cdlongequal", [], []);
7912
7913 case "\\Vert":
7914 {
7915 var arrow = {
7916 type: "textord",
7917 text: "\\Vert",
7918 mode: "math"
7919 };
7920 return parser.callFunction("\\Big", [arrow], []);
7921 }
7922
7923 default:
7924 return {
7925 type: "textord",
7926 text: " ",
7927 mode: "math"
7928 };
7929 }
7930}
7931
7932function parseCD(parser) {
7933 // Get the array's parse nodes with \\ temporarily mapped to \cr.
7934 var parsedRows = [];
7935 parser.gullet.beginGroup();
7936 parser.gullet.macros.set("\\cr", "\\\\\\relax");
7937 parser.gullet.beginGroup();
7938
7939 while (true) {
7940 // eslint-disable-line no-constant-condition
7941 // Get the parse nodes for the next row.
7942 parsedRows.push(parser.parseExpression(false, "\\\\"));
7943 parser.gullet.endGroup();
7944 parser.gullet.beginGroup();
7945 var next = parser.fetch().text;
7946
7947 if (next === "&" || next === "\\\\") {
7948 parser.consume();
7949 } else if (next === "\\end") {
7950 if (parsedRows[parsedRows.length - 1].length === 0) {
7951 parsedRows.pop(); // final row ended in \\
7952 }
7953
7954 break;
7955 } else {
7956 throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken);
7957 }
7958 }
7959
7960 var row = [];
7961 var body = [row]; // Loop thru the parse nodes. Collect them into cells and arrows.
7962
7963 for (var i = 0; i < parsedRows.length; i++) {
7964 // Start a new row.
7965 var rowNodes = parsedRows[i]; // Create the first cell.
7966
7967 var cell = newCell();
7968
7969 for (var j = 0; j < rowNodes.length; j++) {
7970 if (!isStartOfArrow(rowNodes[j])) {
7971 // If a parseNode is not an arrow, it goes into a cell.
7972 cell.body.push(rowNodes[j]);
7973 } else {
7974 // Parse node j is an "@", the start of an arrow.
7975 // Before starting on the arrow, push the cell into `row`.
7976 row.push(cell); // Now collect parseNodes into an arrow.
7977 // The character after "@" defines the arrow type.
7978
7979 j += 1;
7980 var arrowChar = assertSymbolNodeType(rowNodes[j]).text; // Create two empty label nodes. We may or may not use them.
7981
7982 var labels = new Array(2);
7983 labels[0] = {
7984 type: "ordgroup",
7985 mode: "math",
7986 body: []
7987 };
7988 labels[1] = {
7989 type: "ordgroup",
7990 mode: "math",
7991 body: []
7992 }; // Process the arrow.
7993
7994 if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) {
7995 // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take
7996 // two optional labels. E.g. the right-point arrow syntax is
7997 // really: @>{optional label}>{optional label}>
7998 // Collect parseNodes into labels.
7999 for (var labelNum = 0; labelNum < 2; labelNum++) {
8000 var inLabel = true;
8001
8002 for (var k = j + 1; k < rowNodes.length; k++) {
8003 if (isLabelEnd(rowNodes[k], arrowChar)) {
8004 inLabel = false;
8005 j = k;
8006 break;
8007 }
8008
8009 if (isStartOfArrow(rowNodes[k])) {
8010 throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]);
8011 }
8012
8013 labels[labelNum].body.push(rowNodes[k]);
8014 }
8015
8016 if (inLabel) {
8017 // isLabelEnd never returned a true.
8018 throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]);
8019 }
8020 }
8021 } else {
8022 throw new ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]);
8023 } // Now join the arrow to its labels.
8024
8025
8026 var arrow = cdArrow(arrowChar, labels, parser); // Wrap the arrow in ParseNode<"styling">.
8027 // This is done to match parseArray() behavior.
8028
8029 var wrappedArrow = {
8030 type: "styling",
8031 body: [arrow],
8032 mode: "math",
8033 style: "display" // CD is always displaystyle.
8034
8035 };
8036 row.push(wrappedArrow); // In CD's syntax, cells are implicit. That is, everything that
8037 // is not an arrow gets collected into a cell. So create an empty
8038 // cell now. It will collect upcoming parseNodes.
8039
8040 cell = newCell();
8041 }
8042 }
8043
8044 if (i % 2 === 0) {
8045 // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell
8046 // The last cell is not yet pushed into `row`, so:
8047 row.push(cell);
8048 } else {
8049 // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow
8050 // Remove the empty cell that was placed at the beginning of `row`.
8051 row.shift();
8052 }
8053
8054 row = [];
8055 body.push(row);
8056 } // End row group
8057
8058
8059 parser.gullet.endGroup(); // End array group defining \\
8060
8061 parser.gullet.endGroup(); // define column separation.
8062
8063 var cols = new Array(body[0].length).fill({
8064 type: "align",
8065 align: "c",
8066 pregap: 0.25,
8067 // CD package sets \enskip between columns.
8068 postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em.
8069
8070 });
8071 return {
8072 type: "array",
8073 mode: "math",
8074 body,
8075 arraystretch: 1,
8076 addJot: true,
8077 rowGaps: [null],
8078 cols,
8079 colSeparationType: "CD",
8080 hLinesBeforeRow: new Array(body.length + 1).fill([])
8081 };
8082} // The functions below are not available for general use.
8083// They are here only for internal use by the {CD} environment in placing labels
8084// next to vertical arrows.
8085// We don't need any such functions for horizontal arrows because we can reuse
8086// the functionality that already exists for extensible arrows.
8087
8088defineFunction({
8089 type: "cdlabel",
8090 names: ["\\\\cdleft", "\\\\cdright"],
8091 props: {
8092 numArgs: 1
8093 },
8094
8095 handler(_ref, args) {
8096 var {
8097 parser,
8098 funcName
8099 } = _ref;
8100 return {
8101 type: "cdlabel",
8102 mode: parser.mode,
8103 side: funcName.slice(4),
8104 label: args[0]
8105 };
8106 },
8107
8108 htmlBuilder(group, options) {
8109 var newOptions = options.havingStyle(options.style.sup());
8110 var label = buildCommon.wrapFragment(buildGroup$1(group.label, newOptions, options), options);
8111 label.classes.push("cd-label-" + group.side);
8112 label.style.bottom = makeEm(0.8 - label.depth); // Zero out label height & depth, so vertical align of arrow is set
8113 // by the arrow height, not by the label.
8114
8115 label.height = 0;
8116 label.depth = 0;
8117 return label;
8118 },
8119
8120 mathmlBuilder(group, options) {
8121 var label = new mathMLTree.MathNode("mrow", [buildGroup(group.label, options)]);
8122 label = new mathMLTree.MathNode("mpadded", [label]);
8123 label.setAttribute("width", "0");
8124
8125 if (group.side === "left") {
8126 label.setAttribute("lspace", "-1width");
8127 } // We have to guess at vertical alignment. We know the arrow is 1.8em tall,
8128 // But we don't know the height or depth of the label.
8129
8130
8131 label.setAttribute("voffset", "0.7em");
8132 label = new mathMLTree.MathNode("mstyle", [label]);
8133 label.setAttribute("displaystyle", "false");
8134 label.setAttribute("scriptlevel", "1");
8135 return label;
8136 }
8137
8138});
8139defineFunction({
8140 type: "cdlabelparent",
8141 names: ["\\\\cdparent"],
8142 props: {
8143 numArgs: 1
8144 },
8145
8146 handler(_ref2, args) {
8147 var {
8148 parser
8149 } = _ref2;
8150 return {
8151 type: "cdlabelparent",
8152 mode: parser.mode,
8153 fragment: args[0]
8154 };
8155 },
8156
8157 htmlBuilder(group, options) {
8158 // Wrap the vertical arrow and its labels.
8159 // The parent gets position: relative. The child gets position: absolute.
8160 // So CSS can locate the label correctly.
8161 var parent = buildCommon.wrapFragment(buildGroup$1(group.fragment, options), options);
8162 parent.classes.push("cd-vert-arrow");
8163 return parent;
8164 },
8165
8166 mathmlBuilder(group, options) {
8167 return new mathMLTree.MathNode("mrow", [buildGroup(group.fragment, options)]);
8168 }
8169
8170});
8171
8172// {123} and converts into symbol with code 123. It is used by the *macro*
8173// \char defined in macros.js.
8174
8175defineFunction({
8176 type: "textord",
8177 names: ["\\@char"],
8178 props: {
8179 numArgs: 1,
8180 allowedInText: true
8181 },
8182
8183 handler(_ref, args) {
8184 var {
8185 parser
8186 } = _ref;
8187 var arg = assertNodeType(args[0], "ordgroup");
8188 var group = arg.body;
8189 var number = "";
8190
8191 for (var i = 0; i < group.length; i++) {
8192 var node = assertNodeType(group[i], "textord");
8193 number += node.text;
8194 }
8195
8196 var code = parseInt(number);
8197 var text;
8198
8199 if (isNaN(code)) {
8200 throw new ParseError("\\@char has non-numeric argument " + number); // If we drop IE support, the following code could be replaced with
8201 // text = String.fromCodePoint(code)
8202 } else if (code < 0 || code >= 0x10ffff) {
8203 throw new ParseError("\\@char with invalid code point " + number);
8204 } else if (code <= 0xffff) {
8205 text = String.fromCharCode(code);
8206 } else {
8207 // Astral code point; split into surrogate halves
8208 code -= 0x10000;
8209 text = String.fromCharCode((code >> 10) + 0xd800, (code & 0x3ff) + 0xdc00);
8210 }
8211
8212 return {
8213 type: "textord",
8214 mode: parser.mode,
8215 text: text
8216 };
8217 }
8218
8219});
8220
8221var htmlBuilder$9 = (group, options) => {
8222 var elements = buildExpression$1(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains.
8223 // To accomplish this, we wrap the results in a fragment, so the inner
8224 // elements will be able to directly interact with their neighbors. For
8225 // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
8226
8227 return buildCommon.makeFragment(elements);
8228};
8229
8230var mathmlBuilder$8 = (group, options) => {
8231 var inner = buildExpression(group.body, options.withColor(group.color));
8232 var node = new mathMLTree.MathNode("mstyle", inner);
8233 node.setAttribute("mathcolor", group.color);
8234 return node;
8235};
8236
8237defineFunction({
8238 type: "color",
8239 names: ["\\textcolor"],
8240 props: {
8241 numArgs: 2,
8242 allowedInText: true,
8243 argTypes: ["color", "original"]
8244 },
8245
8246 handler(_ref, args) {
8247 var {
8248 parser
8249 } = _ref;
8250 var color = assertNodeType(args[0], "color-token").color;
8251 var body = args[1];
8252 return {
8253 type: "color",
8254 mode: parser.mode,
8255 color,
8256 body: ordargument(body)
8257 };
8258 },
8259
8260 htmlBuilder: htmlBuilder$9,
8261 mathmlBuilder: mathmlBuilder$8
8262});
8263defineFunction({
8264 type: "color",
8265 names: ["\\color"],
8266 props: {
8267 numArgs: 1,
8268 allowedInText: true,
8269 argTypes: ["color"]
8270 },
8271
8272 handler(_ref2, args) {
8273 var {
8274 parser,
8275 breakOnTokenText
8276 } = _ref2;
8277 var color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current
8278 // color, mimicking the behavior of color.sty.
8279 // This is currently used just to correctly color a \right
8280 // that follows a \color command.
8281
8282 parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored.
8283
8284 var body = parser.parseExpression(true, breakOnTokenText);
8285 return {
8286 type: "color",
8287 mode: parser.mode,
8288 color,
8289 body
8290 };
8291 },
8292
8293 htmlBuilder: htmlBuilder$9,
8294 mathmlBuilder: mathmlBuilder$8
8295});
8296
8297// Row breaks within tabular environments, and line breaks at top level
8298
8299defineFunction({
8300 type: "cr",
8301 names: ["\\\\"],
8302 props: {
8303 numArgs: 0,
8304 numOptionalArgs: 1,
8305 argTypes: ["size"],
8306 allowedInText: true
8307 },
8308
8309 handler(_ref, args, optArgs) {
8310 var {
8311 parser
8312 } = _ref;
8313 var size = optArgs[0];
8314 var newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode");
8315 return {
8316 type: "cr",
8317 mode: parser.mode,
8318 newLine,
8319 size: size && assertNodeType(size, "size").value
8320 };
8321 },
8322
8323 // The following builders are called only at the top level,
8324 // not within tabular/array environments.
8325 htmlBuilder(group, options) {
8326 var span = buildCommon.makeSpan(["mspace"], [], options);
8327
8328 if (group.newLine) {
8329 span.classes.push("newline");
8330
8331 if (group.size) {
8332 span.style.marginTop = makeEm(calculateSize(group.size, options));
8333 }
8334 }
8335
8336 return span;
8337 },
8338
8339 mathmlBuilder(group, options) {
8340 var node = new mathMLTree.MathNode("mspace");
8341
8342 if (group.newLine) {
8343 node.setAttribute("linebreak", "newline");
8344
8345 if (group.size) {
8346 node.setAttribute("height", makeEm(calculateSize(group.size, options)));
8347 }
8348 }
8349
8350 return node;
8351 }
8352
8353});
8354
8355var globalMap = {
8356 "\\global": "\\global",
8357 "\\long": "\\\\globallong",
8358 "\\\\globallong": "\\\\globallong",
8359 "\\def": "\\gdef",
8360 "\\gdef": "\\gdef",
8361 "\\edef": "\\xdef",
8362 "\\xdef": "\\xdef",
8363 "\\let": "\\\\globallet",
8364 "\\futurelet": "\\\\globalfuture"
8365};
8366
8367var checkControlSequence = tok => {
8368 var name = tok.text;
8369
8370 if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
8371 throw new ParseError("Expected a control sequence", tok);
8372 }
8373
8374 return name;
8375};
8376
8377var getRHS = parser => {
8378 var tok = parser.gullet.popToken();
8379
8380 if (tok.text === "=") {
8381 // consume optional equals
8382 tok = parser.gullet.popToken();
8383
8384 if (tok.text === " ") {
8385 // consume one optional space
8386 tok = parser.gullet.popToken();
8387 }
8388 }
8389
8390 return tok;
8391};
8392
8393var letCommand = (parser, name, tok, global) => {
8394 var macro = parser.gullet.macros.get(tok.text);
8395
8396 if (macro == null) {
8397 // don't expand it later even if a macro with the same name is defined
8398 // e.g., \let\foo=\frac \def\frac{\relax} \frac12
8399 tok.noexpand = true;
8400 macro = {
8401 tokens: [tok],
8402 numArgs: 0,
8403 // reproduce the same behavior in expansion
8404 unexpandable: !parser.gullet.isExpandable(tok.text)
8405 };
8406 }
8407
8408 parser.gullet.macros.set(name, macro, global);
8409}; // <assignment> -> <non-macro assignment>|<macro assignment>
8410// <non-macro assignment> -> <simple assignment>|\global<non-macro assignment>
8411// <macro assignment> -> <definition>|<prefix><macro assignment>
8412// <prefix> -> \global|\long|\outer
8413
8414
8415defineFunction({
8416 type: "internal",
8417 names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly
8418 ],
8419 props: {
8420 numArgs: 0,
8421 allowedInText: true
8422 },
8423
8424 handler(_ref) {
8425 var {
8426 parser,
8427 funcName
8428 } = _ref;
8429 parser.consumeSpaces();
8430 var token = parser.fetch();
8431
8432 if (globalMap[token.text]) {
8433 // KaTeX doesn't have \par, so ignore \long
8434 if (funcName === "\\global" || funcName === "\\\\globallong") {
8435 token.text = globalMap[token.text];
8436 }
8437
8438 return assertNodeType(parser.parseFunction(), "internal");
8439 }
8440
8441 throw new ParseError("Invalid token after macro prefix", token);
8442 }
8443
8444}); // Basic support for macro definitions: \def, \gdef, \edef, \xdef
8445// <definition> -> <def><control sequence><definition text>
8446// <def> -> \def|\gdef|\edef|\xdef
8447// <definition text> -> <parameter text><left brace><balanced text><right brace>
8448
8449defineFunction({
8450 type: "internal",
8451 names: ["\\def", "\\gdef", "\\edef", "\\xdef"],
8452 props: {
8453 numArgs: 0,
8454 allowedInText: true,
8455 primitive: true
8456 },
8457
8458 handler(_ref2) {
8459 var {
8460 parser,
8461 funcName
8462 } = _ref2;
8463 var tok = parser.gullet.popToken();
8464 var name = tok.text;
8465
8466 if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
8467 throw new ParseError("Expected a control sequence", tok);
8468 }
8469
8470 var numArgs = 0;
8471 var insert;
8472 var delimiters = [[]]; // <parameter text> contains no braces
8473
8474 while (parser.gullet.future().text !== "{") {
8475 tok = parser.gullet.popToken();
8476
8477 if (tok.text === "#") {
8478 // If the very last character of the <parameter text> is #, so that
8479 // this # is immediately followed by {, TeX will behave as if the {
8480 // had been inserted at the right end of both the parameter text
8481 // and the replacement text.
8482 if (parser.gullet.future().text === "{") {
8483 insert = parser.gullet.future();
8484 delimiters[numArgs].push("{");
8485 break;
8486 } // A parameter, the first appearance of # must be followed by 1,
8487 // the next by 2, and so on; up to nine #’s are allowed
8488
8489
8490 tok = parser.gullet.popToken();
8491
8492 if (!/^[1-9]$/.test(tok.text)) {
8493 throw new ParseError("Invalid argument number \"" + tok.text + "\"");
8494 }
8495
8496 if (parseInt(tok.text) !== numArgs + 1) {
8497 throw new ParseError("Argument number \"" + tok.text + "\" out of order");
8498 }
8499
8500 numArgs++;
8501 delimiters.push([]);
8502 } else if (tok.text === "EOF") {
8503 throw new ParseError("Expected a macro definition");
8504 } else {
8505 delimiters[numArgs].push(tok.text);
8506 }
8507 } // replacement text, enclosed in '{' and '}' and properly nested
8508
8509
8510 var {
8511 tokens
8512 } = parser.gullet.consumeArg();
8513
8514 if (insert) {
8515 tokens.unshift(insert);
8516 }
8517
8518 if (funcName === "\\edef" || funcName === "\\xdef") {
8519 tokens = parser.gullet.expandTokens(tokens);
8520 tokens.reverse(); // to fit in with stack order
8521 } // Final arg is the expansion of the macro
8522
8523
8524 parser.gullet.macros.set(name, {
8525 tokens,
8526 numArgs,
8527 delimiters
8528 }, funcName === globalMap[funcName]);
8529 return {
8530 type: "internal",
8531 mode: parser.mode
8532 };
8533 }
8534
8535}); // <simple assignment> -> <let assignment>
8536// <let assignment> -> \futurelet<control sequence><token><token>
8537// | \let<control sequence><equals><one optional space><token>
8538// <equals> -> <optional spaces>|<optional spaces>=
8539
8540defineFunction({
8541 type: "internal",
8542 names: ["\\let", "\\\\globallet" // can’t be entered directly
8543 ],
8544 props: {
8545 numArgs: 0,
8546 allowedInText: true,
8547 primitive: true
8548 },
8549
8550 handler(_ref3) {
8551 var {
8552 parser,
8553 funcName
8554 } = _ref3;
8555 var name = checkControlSequence(parser.gullet.popToken());
8556 parser.gullet.consumeSpaces();
8557 var tok = getRHS(parser);
8558 letCommand(parser, name, tok, funcName === "\\\\globallet");
8559 return {
8560 type: "internal",
8561 mode: parser.mode
8562 };
8563 }
8564
8565}); // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf
8566
8567defineFunction({
8568 type: "internal",
8569 names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly
8570 ],
8571 props: {
8572 numArgs: 0,
8573 allowedInText: true,
8574 primitive: true
8575 },
8576
8577 handler(_ref4) {
8578 var {
8579 parser,
8580 funcName
8581 } = _ref4;
8582 var name = checkControlSequence(parser.gullet.popToken());
8583 var middle = parser.gullet.popToken();
8584 var tok = parser.gullet.popToken();
8585 letCommand(parser, name, tok, funcName === "\\\\globalfuture");
8586 parser.gullet.pushToken(tok);
8587 parser.gullet.pushToken(middle);
8588 return {
8589 type: "internal",
8590 mode: parser.mode
8591 };
8592 }
8593
8594});
8595
8596/**
8597 * This file deals with creating delimiters of various sizes. The TeXbook
8598 * discusses these routines on page 441-442, in the "Another subroutine sets box
8599 * x to a specified variable delimiter" paragraph.
8600 *
8601 * There are three main routines here. `makeSmallDelim` makes a delimiter in the
8602 * normal font, but in either text, script, or scriptscript style.
8603 * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
8604 * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
8605 * smaller pieces that are stacked on top of one another.
8606 *
8607 * The functions take a parameter `center`, which determines if the delimiter
8608 * should be centered around the axis.
8609 *
8610 * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
8611 * one of the given sizes. This is used for things like `\bigl`.
8612 * `customSizedDelim` makes a delimiter with a given total height+depth. It is
8613 * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
8614 * delimiter which surrounds an expression of a given height an depth. It is
8615 * used in `\left` and `\right`.
8616 */
8617
8618/**
8619 * Get the metrics for a given symbol and font, after transformation (i.e.
8620 * after following replacement from symbols.js)
8621 */
8622var getMetrics = function getMetrics(symbol, font, mode) {
8623 var replace = symbols.math[symbol] && symbols.math[symbol].replace;
8624 var metrics = getCharacterMetrics(replace || symbol, font, mode);
8625
8626 if (!metrics) {
8627 throw new Error("Unsupported symbol " + symbol + " and font size " + font + ".");
8628 }
8629
8630 return metrics;
8631};
8632/**
8633 * Puts a delimiter span in a given style, and adds appropriate height, depth,
8634 * and maxFontSizes.
8635 */
8636
8637
8638var styleWrap = function styleWrap(delim, toStyle, options, classes) {
8639 var newOptions = options.havingBaseStyle(toStyle);
8640 var span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options);
8641 var delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier;
8642 span.height *= delimSizeMultiplier;
8643 span.depth *= delimSizeMultiplier;
8644 span.maxFontSize = newOptions.sizeMultiplier;
8645 return span;
8646};
8647
8648var centerSpan = function centerSpan(span, options, style) {
8649 var newOptions = options.havingBaseStyle(style);
8650 var shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight;
8651 span.classes.push("delimcenter");
8652 span.style.top = makeEm(shift);
8653 span.height -= shift;
8654 span.depth += shift;
8655};
8656/**
8657 * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
8658 * font, but is restyled to either be in textstyle, scriptstyle, or
8659 * scriptscriptstyle.
8660 */
8661
8662
8663var makeSmallDelim = function makeSmallDelim(delim, style, center, options, mode, classes) {
8664 var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
8665 var span = styleWrap(text, style, options, classes);
8666
8667 if (center) {
8668 centerSpan(span, options, style);
8669 }
8670
8671 return span;
8672};
8673/**
8674 * Builds a symbol in the given font size (note size is an integer)
8675 */
8676
8677
8678var mathrmSize = function mathrmSize(value, size, mode, options) {
8679 return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options);
8680};
8681/**
8682 * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
8683 * Size3, or Size4 fonts. It is always rendered in textstyle.
8684 */
8685
8686
8687var makeLargeDelim = function makeLargeDelim(delim, size, center, options, mode, classes) {
8688 var inner = mathrmSize(delim, size, mode, options);
8689 var span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), Style$1.TEXT, options, classes);
8690
8691 if (center) {
8692 centerSpan(span, options, Style$1.TEXT);
8693 }
8694
8695 return span;
8696};
8697/**
8698 * Make a span from a font glyph with the given offset and in the given font.
8699 * This is used in makeStackedDelim to make the stacking pieces for the delimiter.
8700 */
8701
8702
8703var makeGlyphSpan = function makeGlyphSpan(symbol, font, mode) {
8704 var sizeClass; // Apply the correct CSS class to choose the right font.
8705
8706 if (font === "Size1-Regular") {
8707 sizeClass = "delim-size1";
8708 } else
8709 /* if (font === "Size4-Regular") */
8710 {
8711 sizeClass = "delim-size4";
8712 }
8713
8714 var corner = buildCommon.makeSpan(["delimsizinginner", sizeClass], [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); // Since this will be passed into `makeVList` in the end, wrap the element
8715 // in the appropriate tag that VList uses.
8716
8717 return {
8718 type: "elem",
8719 elem: corner
8720 };
8721};
8722
8723var makeInner = function makeInner(ch, height, options) {
8724 // Create a span with inline SVG for the inner part of a tall stacked delimiter.
8725 var width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4] : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4];
8726 var path = new PathNode("inner", innerPath(ch, Math.round(1000 * height)));
8727 var svgNode = new SvgNode([path], {
8728 "width": makeEm(width),
8729 "height": makeEm(height),
8730 // Override CSS rule `.katex svg { width: 100% }`
8731 "style": "width:" + makeEm(width),
8732 "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height),
8733 "preserveAspectRatio": "xMinYMin"
8734 });
8735 var span = buildCommon.makeSvgSpan([], [svgNode], options);
8736 span.height = height;
8737 span.style.height = makeEm(height);
8738 span.style.width = makeEm(width);
8739 return {
8740 type: "elem",
8741 elem: span
8742 };
8743}; // Helpers for makeStackedDelim
8744
8745
8746var lapInEms = 0.008;
8747var lap = {
8748 type: "kern",
8749 size: -1 * lapInEms
8750};
8751var verts = ["|", "\\lvert", "\\rvert", "\\vert"];
8752var doubleVerts = ["\\|", "\\lVert", "\\rVert", "\\Vert"];
8753/**
8754 * Make a stacked delimiter out of a given delimiter, with the total height at
8755 * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
8756 */
8757
8758var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, options, mode, classes) {
8759 // There are four parts, the top, an optional middle, a repeated part, and a
8760 // bottom.
8761 var top;
8762 var middle;
8763 var repeat;
8764 var bottom;
8765 top = repeat = bottom = delim;
8766 middle = null; // Also keep track of what font the delimiters are in
8767
8768 var font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use
8769 // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
8770 // repeats of the arrows
8771
8772 if (delim === "\\uparrow") {
8773 repeat = bottom = "\u23d0";
8774 } else if (delim === "\\Uparrow") {
8775 repeat = bottom = "\u2016";
8776 } else if (delim === "\\downarrow") {
8777 top = repeat = "\u23d0";
8778 } else if (delim === "\\Downarrow") {
8779 top = repeat = "\u2016";
8780 } else if (delim === "\\updownarrow") {
8781 top = "\\uparrow";
8782 repeat = "\u23d0";
8783 bottom = "\\downarrow";
8784 } else if (delim === "\\Updownarrow") {
8785 top = "\\Uparrow";
8786 repeat = "\u2016";
8787 bottom = "\\Downarrow";
8788 } else if (utils.contains(verts, delim)) {
8789 repeat = "\u2223";
8790 } else if (utils.contains(doubleVerts, delim)) {
8791 repeat = "\u2225";
8792 } else if (delim === "[" || delim === "\\lbrack") {
8793 top = "\u23a1";
8794 repeat = "\u23a2";
8795 bottom = "\u23a3";
8796 font = "Size4-Regular";
8797 } else if (delim === "]" || delim === "\\rbrack") {
8798 top = "\u23a4";
8799 repeat = "\u23a5";
8800 bottom = "\u23a6";
8801 font = "Size4-Regular";
8802 } else if (delim === "\\lfloor" || delim === "\u230a") {
8803 repeat = top = "\u23a2";
8804 bottom = "\u23a3";
8805 font = "Size4-Regular";
8806 } else if (delim === "\\lceil" || delim === "\u2308") {
8807 top = "\u23a1";
8808 repeat = bottom = "\u23a2";
8809 font = "Size4-Regular";
8810 } else if (delim === "\\rfloor" || delim === "\u230b") {
8811 repeat = top = "\u23a5";
8812 bottom = "\u23a6";
8813 font = "Size4-Regular";
8814 } else if (delim === "\\rceil" || delim === "\u2309") {
8815 top = "\u23a4";
8816 repeat = bottom = "\u23a5";
8817 font = "Size4-Regular";
8818 } else if (delim === "(" || delim === "\\lparen") {
8819 top = "\u239b";
8820 repeat = "\u239c";
8821 bottom = "\u239d";
8822 font = "Size4-Regular";
8823 } else if (delim === ")" || delim === "\\rparen") {
8824 top = "\u239e";
8825 repeat = "\u239f";
8826 bottom = "\u23a0";
8827 font = "Size4-Regular";
8828 } else if (delim === "\\{" || delim === "\\lbrace") {
8829 top = "\u23a7";
8830 middle = "\u23a8";
8831 bottom = "\u23a9";
8832 repeat = "\u23aa";
8833 font = "Size4-Regular";
8834 } else if (delim === "\\}" || delim === "\\rbrace") {
8835 top = "\u23ab";
8836 middle = "\u23ac";
8837 bottom = "\u23ad";
8838 repeat = "\u23aa";
8839 font = "Size4-Regular";
8840 } else if (delim === "\\lgroup" || delim === "\u27ee") {
8841 top = "\u23a7";
8842 bottom = "\u23a9";
8843 repeat = "\u23aa";
8844 font = "Size4-Regular";
8845 } else if (delim === "\\rgroup" || delim === "\u27ef") {
8846 top = "\u23ab";
8847 bottom = "\u23ad";
8848 repeat = "\u23aa";
8849 font = "Size4-Regular";
8850 } else if (delim === "\\lmoustache" || delim === "\u23b0") {
8851 top = "\u23a7";
8852 bottom = "\u23ad";
8853 repeat = "\u23aa";
8854 font = "Size4-Regular";
8855 } else if (delim === "\\rmoustache" || delim === "\u23b1") {
8856 top = "\u23ab";
8857 bottom = "\u23a9";
8858 repeat = "\u23aa";
8859 font = "Size4-Regular";
8860 } // Get the metrics of the four sections
8861
8862
8863 var topMetrics = getMetrics(top, font, mode);
8864 var topHeightTotal = topMetrics.height + topMetrics.depth;
8865 var repeatMetrics = getMetrics(repeat, font, mode);
8866 var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
8867 var bottomMetrics = getMetrics(bottom, font, mode);
8868 var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
8869 var middleHeightTotal = 0;
8870 var middleFactor = 1;
8871
8872 if (middle !== null) {
8873 var middleMetrics = getMetrics(middle, font, mode);
8874 middleHeightTotal = middleMetrics.height + middleMetrics.depth;
8875 middleFactor = 2; // repeat symmetrically above and below middle
8876 } // Calcuate the minimal height that the delimiter can have.
8877 // It is at least the size of the top, bottom, and optional middle combined.
8878
8879
8880 var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need
8881
8882 var repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols
8883
8884 var realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note
8885 // that in this context, "center" means that the delimiter should be
8886 // centered around the axis in the current style, while normally it is
8887 // centered around the axis in textstyle.
8888
8889 var axisHeight = options.fontMetrics().axisHeight;
8890
8891 if (center) {
8892 axisHeight *= options.sizeMultiplier;
8893 } // Calculate the depth
8894
8895
8896 var depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist
8897 // Keep a list of the pieces of the stacked delimiter
8898
8899 var stack = []; // Add the bottom symbol
8900
8901 stack.push(makeGlyphSpan(bottom, font, mode));
8902 stack.push(lap); // overlap
8903
8904 if (middle === null) {
8905 // The middle section will be an SVG. Make it an extra 0.016em tall.
8906 // We'll overlap by 0.008em at top and bottom.
8907 var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms;
8908 stack.push(makeInner(repeat, innerHeight, options));
8909 } else {
8910 // When there is a middle bit, we need the middle part and two repeated
8911 // sections
8912 var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
8913
8914 stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace.
8915
8916 stack.push(lap);
8917 stack.push(makeGlyphSpan(middle, font, mode));
8918 stack.push(lap);
8919 stack.push(makeInner(repeat, _innerHeight, options));
8920 } // Add the top symbol
8921
8922
8923 stack.push(lap);
8924 stack.push(makeGlyphSpan(top, font, mode)); // Finally, build the vlist
8925
8926 var newOptions = options.havingBaseStyle(Style$1.TEXT);
8927 var inner = buildCommon.makeVList({
8928 positionType: "bottom",
8929 positionData: depth,
8930 children: stack
8931 }, newOptions);
8932 return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), Style$1.TEXT, options, classes);
8933}; // All surds have 0.08em padding above the viniculum inside the SVG.
8934// That keeps browser span height rounding error from pinching the line.
8935
8936
8937var vbPad = 80; // padding above the surd, measured inside the viewBox.
8938
8939var emPad = 0.08; // padding, in ems, measured in the document.
8940
8941var sqrtSvg = function sqrtSvg(sqrtName, height, viewBoxHeight, extraViniculum, options) {
8942 var path = sqrtPath(sqrtName, extraViniculum, viewBoxHeight);
8943 var pathNode = new PathNode(sqrtName, path);
8944 var svg = new SvgNode([pathNode], {
8945 // Note: 1000:1 ratio of viewBox to document em width.
8946 "width": "400em",
8947 "height": makeEm(height),
8948 "viewBox": "0 0 400000 " + viewBoxHeight,
8949 "preserveAspectRatio": "xMinYMin slice"
8950 });
8951 return buildCommon.makeSvgSpan(["hide-tail"], [svg], options);
8952};
8953/**
8954 * Make a sqrt image of the given height,
8955 */
8956
8957
8958var makeSqrtImage = function makeSqrtImage(height, options) {
8959 // Define a newOptions that removes the effect of size changes such as \Huge.
8960 // We don't pick different a height surd for \Huge. For it, we scale up.
8961 var newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds.
8962
8963 var delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions);
8964 var sizeMultiplier = newOptions.sizeMultiplier; // default
8965 // The standard sqrt SVGs each have a 0.04em thick viniculum.
8966 // If Settings.minRuleThickness is larger than that, we add extraViniculum.
8967
8968 var extraViniculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol.
8969
8970 var span;
8971 var spanHeight = 0;
8972 var texHeight = 0;
8973 var viewBoxHeight = 0;
8974 var advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd.
8975 // Then browser rounding error on the parent span height will not
8976 // encroach on the ink of the viniculum. But that padding is not
8977 // included in the TeX-like `height` used for calculation of
8978 // vertical alignment. So texHeight = span.height < span.style.height.
8979
8980 if (delim.type === "small") {
8981 // Get an SVG that is derived from glyph U+221A in font KaTeX-Main.
8982 // 1000 unit normal glyph height.
8983 viewBoxHeight = 1000 + 1000 * extraViniculum + vbPad;
8984
8985 if (height < 1.0) {
8986 sizeMultiplier = 1.0; // mimic a \textfont radical
8987 } else if (height < 1.4) {
8988 sizeMultiplier = 0.7; // mimic a \scriptfont radical
8989 }
8990
8991 spanHeight = (1.0 + extraViniculum + emPad) / sizeMultiplier;
8992 texHeight = (1.00 + extraViniculum) / sizeMultiplier;
8993 span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraViniculum, options);
8994 span.style.minWidth = "0.853em";
8995 advanceWidth = 0.833 / sizeMultiplier; // from the font.
8996 } else if (delim.type === "large") {
8997 // These SVGs come from fonts: KaTeX_Size1, _Size2, etc.
8998 viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
8999 texHeight = (sizeToMaxHeight[delim.size] + extraViniculum) / sizeMultiplier;
9000 spanHeight = (sizeToMaxHeight[delim.size] + extraViniculum + emPad) / sizeMultiplier;
9001 span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraViniculum, options);
9002 span.style.minWidth = "1.02em";
9003 advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font.
9004 } else {
9005 // Tall sqrt. In TeX, this would be stacked using multiple glyphs.
9006 // We'll use a single SVG to accomplish the same thing.
9007 spanHeight = height + extraViniculum + emPad;
9008 texHeight = height + extraViniculum;
9009 viewBoxHeight = Math.floor(1000 * height + extraViniculum) + vbPad;
9010 span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraViniculum, options);
9011 span.style.minWidth = "0.742em";
9012 advanceWidth = 1.056;
9013 }
9014
9015 span.height = texHeight;
9016 span.style.height = makeEm(spanHeight);
9017 return {
9018 span,
9019 advanceWidth,
9020 // Calculate the actual line width.
9021 // This actually should depend on the chosen font -- e.g. \boldmath
9022 // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and
9023 // have thicker rules.
9024 ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraViniculum) * sizeMultiplier
9025 };
9026}; // There are three kinds of delimiters, delimiters that stack when they become
9027// too large
9028
9029
9030var stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack
9031
9032var stackAlwaysDelimiters = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"]; // and delimiters that never stack
9033
9034var stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of
9035// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
9036// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
9037
9038var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
9039/**
9040 * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
9041 */
9042
9043var makeSizedDelim = function makeSizedDelim(delim, size, options, mode, classes) {
9044 // < and > turn into \langle and \rangle in delimiters
9045 if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
9046 delim = "\\langle";
9047 } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
9048 delim = "\\rangle";
9049 } // Sized delimiters are never centered.
9050
9051
9052 if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) {
9053 return makeLargeDelim(delim, size, false, options, mode, classes);
9054 } else if (utils.contains(stackAlwaysDelimiters, delim)) {
9055 return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes);
9056 } else {
9057 throw new ParseError("Illegal delimiter: '" + delim + "'");
9058 }
9059};
9060/**
9061 * There are three different sequences of delimiter sizes that the delimiters
9062 * follow depending on the kind of delimiter. This is used when creating custom
9063 * sized delimiters to decide whether to create a small, large, or stacked
9064 * delimiter.
9065 *
9066 * In real TeX, these sequences aren't explicitly defined, but are instead
9067 * defined inside the font metrics. Since there are only three sequences that
9068 * are possible for the delimiters that TeX defines, it is easier to just encode
9069 * them explicitly here.
9070 */
9071
9072
9073// Delimiters that never stack try small delimiters and large delimiters only
9074var stackNeverDelimiterSequence = [{
9075 type: "small",
9076 style: Style$1.SCRIPTSCRIPT
9077}, {
9078 type: "small",
9079 style: Style$1.SCRIPT
9080}, {
9081 type: "small",
9082 style: Style$1.TEXT
9083}, {
9084 type: "large",
9085 size: 1
9086}, {
9087 type: "large",
9088 size: 2
9089}, {
9090 type: "large",
9091 size: 3
9092}, {
9093 type: "large",
9094 size: 4
9095}]; // Delimiters that always stack try the small delimiters first, then stack
9096
9097var stackAlwaysDelimiterSequence = [{
9098 type: "small",
9099 style: Style$1.SCRIPTSCRIPT
9100}, {
9101 type: "small",
9102 style: Style$1.SCRIPT
9103}, {
9104 type: "small",
9105 style: Style$1.TEXT
9106}, {
9107 type: "stack"
9108}]; // Delimiters that stack when large try the small and then large delimiters, and
9109// stack afterwards
9110
9111var stackLargeDelimiterSequence = [{
9112 type: "small",
9113 style: Style$1.SCRIPTSCRIPT
9114}, {
9115 type: "small",
9116 style: Style$1.SCRIPT
9117}, {
9118 type: "small",
9119 style: Style$1.TEXT
9120}, {
9121 type: "large",
9122 size: 1
9123}, {
9124 type: "large",
9125 size: 2
9126}, {
9127 type: "large",
9128 size: 3
9129}, {
9130 type: "large",
9131 size: 4
9132}, {
9133 type: "stack"
9134}];
9135/**
9136 * Get the font used in a delimiter based on what kind of delimiter it is.
9137 * TODO(#963) Use more specific font family return type once that is introduced.
9138 */
9139
9140var delimTypeToFont = function delimTypeToFont(type) {
9141 if (type.type === "small") {
9142 return "Main-Regular";
9143 } else if (type.type === "large") {
9144 return "Size" + type.size + "-Regular";
9145 } else if (type.type === "stack") {
9146 return "Size4-Regular";
9147 } else {
9148 throw new Error("Add support for delim type '" + type.type + "' here.");
9149 }
9150};
9151/**
9152 * Traverse a sequence of types of delimiters to decide what kind of delimiter
9153 * should be used to create a delimiter of the given height+depth.
9154 */
9155
9156
9157var traverseSequence = function traverseSequence(delim, height, sequence, options) {
9158 // Here, we choose the index we should start at in the sequences. In smaller
9159 // sizes (which correspond to larger numbers in style.size) we start earlier
9160 // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
9161 // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
9162 var start = Math.min(2, 3 - options.style.size);
9163
9164 for (var i = start; i < sequence.length; i++) {
9165 if (sequence[i].type === "stack") {
9166 // This is always the last delimiter, so we just break the loop now.
9167 break;
9168 }
9169
9170 var metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math");
9171 var heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we
9172 // account for the style change size.
9173
9174 if (sequence[i].type === "small") {
9175 var newOptions = options.havingBaseStyle(sequence[i].style);
9176 heightDepth *= newOptions.sizeMultiplier;
9177 } // Check if the delimiter at this size works for the given height.
9178
9179
9180 if (heightDepth > height) {
9181 return sequence[i];
9182 }
9183 } // If we reached the end of the sequence, return the last sequence element.
9184
9185
9186 return sequence[sequence.length - 1];
9187};
9188/**
9189 * Make a delimiter of a given height+depth, with optional centering. Here, we
9190 * traverse the sequences, and create a delimiter that the sequence tells us to.
9191 */
9192
9193
9194var makeCustomSizedDelim = function makeCustomSizedDelim(delim, height, center, options, mode, classes) {
9195 if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
9196 delim = "\\langle";
9197 } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
9198 delim = "\\rangle";
9199 } // Decide what sequence to use
9200
9201
9202 var sequence;
9203
9204 if (utils.contains(stackNeverDelimiters, delim)) {
9205 sequence = stackNeverDelimiterSequence;
9206 } else if (utils.contains(stackLargeDelimiters, delim)) {
9207 sequence = stackLargeDelimiterSequence;
9208 } else {
9209 sequence = stackAlwaysDelimiterSequence;
9210 } // Look through the sequence
9211
9212
9213 var delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs.
9214 // Depending on the sequence element we decided on, call the
9215 // appropriate function.
9216
9217 if (delimType.type === "small") {
9218 return makeSmallDelim(delim, delimType.style, center, options, mode, classes);
9219 } else if (delimType.type === "large") {
9220 return makeLargeDelim(delim, delimType.size, center, options, mode, classes);
9221 } else
9222 /* if (delimType.type === "stack") */
9223 {
9224 return makeStackedDelim(delim, height, center, options, mode, classes);
9225 }
9226};
9227/**
9228 * Make a delimiter for use with `\left` and `\right`, given a height and depth
9229 * of an expression that the delimiters surround.
9230 */
9231
9232
9233var makeLeftRightDelim = function makeLeftRightDelim(delim, height, depth, options, mode, classes) {
9234 // We always center \left/\right delimiters, so the axis is always shifted
9235 var axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right
9236
9237 var delimiterFactor = 901;
9238 var delimiterExtend = 5.0 / options.fontMetrics().ptPerEm;
9239 var maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight);
9240 var totalHeight = Math.max( // In real TeX, calculations are done using integral values which are
9241 // 65536 per pt, or 655360 per em. So, the division here truncates in
9242 // TeX but doesn't here, producing different results. If we wanted to
9243 // exactly match TeX's calculation, we could do
9244 // Math.floor(655360 * maxDistFromAxis / 500) *
9245 // delimiterFactor / 655360
9246 // (To see the difference, compare
9247 // x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
9248 // in TeX and KaTeX)
9249 maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total
9250 // height
9251
9252 return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes);
9253};
9254
9255var delimiter = {
9256 sqrtImage: makeSqrtImage,
9257 sizedDelim: makeSizedDelim,
9258 sizeToMaxHeight: sizeToMaxHeight,
9259 customSizedDelim: makeCustomSizedDelim,
9260 leftRightDelim: makeLeftRightDelim
9261};
9262
9263// Extra data needed for the delimiter handler down below
9264var delimiterSizes = {
9265 "\\bigl": {
9266 mclass: "mopen",
9267 size: 1
9268 },
9269 "\\Bigl": {
9270 mclass: "mopen",
9271 size: 2
9272 },
9273 "\\biggl": {
9274 mclass: "mopen",
9275 size: 3
9276 },
9277 "\\Biggl": {
9278 mclass: "mopen",
9279 size: 4
9280 },
9281 "\\bigr": {
9282 mclass: "mclose",
9283 size: 1
9284 },
9285 "\\Bigr": {
9286 mclass: "mclose",
9287 size: 2
9288 },
9289 "\\biggr": {
9290 mclass: "mclose",
9291 size: 3
9292 },
9293 "\\Biggr": {
9294 mclass: "mclose",
9295 size: 4
9296 },
9297 "\\bigm": {
9298 mclass: "mrel",
9299 size: 1
9300 },
9301 "\\Bigm": {
9302 mclass: "mrel",
9303 size: 2
9304 },
9305 "\\biggm": {
9306 mclass: "mrel",
9307 size: 3
9308 },
9309 "\\Biggm": {
9310 mclass: "mrel",
9311 size: 4
9312 },
9313 "\\big": {
9314 mclass: "mord",
9315 size: 1
9316 },
9317 "\\Big": {
9318 mclass: "mord",
9319 size: 2
9320 },
9321 "\\bigg": {
9322 mclass: "mord",
9323 size: 3
9324 },
9325 "\\Bigg": {
9326 mclass: "mord",
9327 size: 4
9328 }
9329};
9330var delimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."];
9331
9332// Delimiter functions
9333function checkDelimiter(delim, context) {
9334 var symDelim = checkSymbolNodeType(delim);
9335
9336 if (symDelim && utils.contains(delimiters, symDelim.text)) {
9337 return symDelim;
9338 } else if (symDelim) {
9339 throw new ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim);
9340 } else {
9341 throw new ParseError("Invalid delimiter type '" + delim.type + "'", delim);
9342 }
9343}
9344
9345defineFunction({
9346 type: "delimsizing",
9347 names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"],
9348 props: {
9349 numArgs: 1,
9350 argTypes: ["primitive"]
9351 },
9352 handler: (context, args) => {
9353 var delim = checkDelimiter(args[0], context);
9354 return {
9355 type: "delimsizing",
9356 mode: context.parser.mode,
9357 size: delimiterSizes[context.funcName].size,
9358 mclass: delimiterSizes[context.funcName].mclass,
9359 delim: delim.text
9360 };
9361 },
9362 htmlBuilder: (group, options) => {
9363 if (group.delim === ".") {
9364 // Empty delimiters still count as elements, even though they don't
9365 // show anything.
9366 return buildCommon.makeSpan([group.mclass]);
9367 } // Use delimiter.sizedDelim to generate the delimiter.
9368
9369
9370 return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]);
9371 },
9372 mathmlBuilder: group => {
9373 var children = [];
9374
9375 if (group.delim !== ".") {
9376 children.push(makeText(group.delim, group.mode));
9377 }
9378
9379 var node = new mathMLTree.MathNode("mo", children);
9380
9381 if (group.mclass === "mopen" || group.mclass === "mclose") {
9382 // Only some of the delimsizing functions act as fences, and they
9383 // return "mopen" or "mclose" mclass.
9384 node.setAttribute("fence", "true");
9385 } else {
9386 // Explicitly disable fencing if it's not a fence, to override the
9387 // defaults.
9388 node.setAttribute("fence", "false");
9389 }
9390
9391 node.setAttribute("stretchy", "true");
9392 var size = makeEm(delimiter.sizeToMaxHeight[group.size]);
9393 node.setAttribute("minsize", size);
9394 node.setAttribute("maxsize", size);
9395 return node;
9396 }
9397});
9398
9399function assertParsed(group) {
9400 if (!group.body) {
9401 throw new Error("Bug: The leftright ParseNode wasn't fully parsed.");
9402 }
9403}
9404
9405defineFunction({
9406 type: "leftright-right",
9407 names: ["\\right"],
9408 props: {
9409 numArgs: 1,
9410 primitive: true
9411 },
9412 handler: (context, args) => {
9413 // \left case below triggers parsing of \right in
9414 // `const right = parser.parseFunction();`
9415 // uses this return value.
9416 var color = context.parser.gullet.macros.get("\\current@color");
9417
9418 if (color && typeof color !== "string") {
9419 throw new ParseError("\\current@color set to non-string in \\right");
9420 }
9421
9422 return {
9423 type: "leftright-right",
9424 mode: context.parser.mode,
9425 delim: checkDelimiter(args[0], context).text,
9426 color // undefined if not set via \color
9427
9428 };
9429 }
9430});
9431defineFunction({
9432 type: "leftright",
9433 names: ["\\left"],
9434 props: {
9435 numArgs: 1,
9436 primitive: true
9437 },
9438 handler: (context, args) => {
9439 var delim = checkDelimiter(args[0], context);
9440 var parser = context.parser; // Parse out the implicit body
9441
9442 ++parser.leftrightDepth; // parseExpression stops before '\\right'
9443
9444 var body = parser.parseExpression(false);
9445 --parser.leftrightDepth; // Check the next token
9446
9447 parser.expect("\\right", false);
9448 var right = assertNodeType(parser.parseFunction(), "leftright-right");
9449 return {
9450 type: "leftright",
9451 mode: parser.mode,
9452 body,
9453 left: delim.text,
9454 right: right.delim,
9455 rightColor: right.color
9456 };
9457 },
9458 htmlBuilder: (group, options) => {
9459 assertParsed(group); // Build the inner expression
9460
9461 var inner = buildExpression$1(group.body, options, true, ["mopen", "mclose"]);
9462 var innerHeight = 0;
9463 var innerDepth = 0;
9464 var hadMiddle = false; // Calculate its height and depth
9465
9466 for (var i = 0; i < inner.length; i++) {
9467 // Property `isMiddle` not defined on `span`. See comment in
9468 // "middle"'s htmlBuilder.
9469 // $FlowFixMe
9470 if (inner[i].isMiddle) {
9471 hadMiddle = true;
9472 } else {
9473 innerHeight = Math.max(inner[i].height, innerHeight);
9474 innerDepth = Math.max(inner[i].depth, innerDepth);
9475 }
9476 } // The size of delimiters is the same, regardless of what style we are
9477 // in. Thus, to correctly calculate the size of delimiter we need around
9478 // a group, we scale down the inner size based on the size.
9479
9480
9481 innerHeight *= options.sizeMultiplier;
9482 innerDepth *= options.sizeMultiplier;
9483 var leftDelim;
9484
9485 if (group.left === ".") {
9486 // Empty delimiters in \left and \right make null delimiter spaces.
9487 leftDelim = makeNullDelimiter(options, ["mopen"]);
9488 } else {
9489 // Otherwise, use leftRightDelim to generate the correct sized
9490 // delimiter.
9491 leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]);
9492 } // Add it to the beginning of the expression
9493
9494
9495 inner.unshift(leftDelim); // Handle middle delimiters
9496
9497 if (hadMiddle) {
9498 for (var _i = 1; _i < inner.length; _i++) {
9499 var middleDelim = inner[_i]; // Property `isMiddle` not defined on `span`. See comment in
9500 // "middle"'s htmlBuilder.
9501 // $FlowFixMe
9502
9503 var isMiddle = middleDelim.isMiddle;
9504
9505 if (isMiddle) {
9506 // Apply the options that were active when \middle was called
9507 inner[_i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
9508 }
9509 }
9510 }
9511
9512 var rightDelim; // Same for the right delimiter, but using color specified by \color
9513
9514 if (group.right === ".") {
9515 rightDelim = makeNullDelimiter(options, ["mclose"]);
9516 } else {
9517 var colorOptions = group.rightColor ? options.withColor(group.rightColor) : options;
9518 rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]);
9519 } // Add it to the end of the expression.
9520
9521
9522 inner.push(rightDelim);
9523 return buildCommon.makeSpan(["minner"], inner, options);
9524 },
9525 mathmlBuilder: (group, options) => {
9526 assertParsed(group);
9527 var inner = buildExpression(group.body, options);
9528
9529 if (group.left !== ".") {
9530 var leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]);
9531 leftNode.setAttribute("fence", "true");
9532 inner.unshift(leftNode);
9533 }
9534
9535 if (group.right !== ".") {
9536 var rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]);
9537 rightNode.setAttribute("fence", "true");
9538
9539 if (group.rightColor) {
9540 rightNode.setAttribute("mathcolor", group.rightColor);
9541 }
9542
9543 inner.push(rightNode);
9544 }
9545
9546 return makeRow(inner);
9547 }
9548});
9549defineFunction({
9550 type: "middle",
9551 names: ["\\middle"],
9552 props: {
9553 numArgs: 1,
9554 primitive: true
9555 },
9556 handler: (context, args) => {
9557 var delim = checkDelimiter(args[0], context);
9558
9559 if (!context.parser.leftrightDepth) {
9560 throw new ParseError("\\middle without preceding \\left", delim);
9561 }
9562
9563 return {
9564 type: "middle",
9565 mode: context.parser.mode,
9566 delim: delim.text
9567 };
9568 },
9569 htmlBuilder: (group, options) => {
9570 var middleDelim;
9571
9572 if (group.delim === ".") {
9573 middleDelim = makeNullDelimiter(options, []);
9574 } else {
9575 middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []);
9576 var isMiddle = {
9577 delim: group.delim,
9578 options
9579 }; // Property `isMiddle` not defined on `span`. It is only used in
9580 // this file above.
9581 // TODO: Fix this violation of the `span` type and possibly rename
9582 // things since `isMiddle` sounds like a boolean, but is a struct.
9583 // $FlowFixMe
9584
9585 middleDelim.isMiddle = isMiddle;
9586 }
9587
9588 return middleDelim;
9589 },
9590 mathmlBuilder: (group, options) => {
9591 // A Firefox \middle will strech a character vertically only if it
9592 // is in the fence part of the operator dictionary at:
9593 // https://www.w3.org/TR/MathML3/appendixc.html.
9594 // So we need to avoid U+2223 and use plain "|" instead.
9595 var textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode);
9596 var middleNode = new mathMLTree.MathNode("mo", [textNode]);
9597 middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each <mo> element.
9598 // \middle should get delimiter spacing instead.
9599
9600 middleNode.setAttribute("lspace", "0.05em");
9601 middleNode.setAttribute("rspace", "0.05em");
9602 return middleNode;
9603 }
9604});
9605
9606var htmlBuilder$8 = (group, options) => {
9607 // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase
9608 // Some groups can return document fragments. Handle those by wrapping
9609 // them in a span.
9610 var inner = buildCommon.wrapFragment(buildGroup$1(group.body, options), options);
9611 var label = group.label.substr(1);
9612 var scale = options.sizeMultiplier;
9613 var img;
9614 var imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different
9615 // depending on whether the subject is wider than it is tall, or vice versa.
9616 // We don't know the width of a group, so as a proxy, we test if
9617 // the subject is a single character. This captures most of the
9618 // subjects that should get the "tall" treatment.
9619
9620 var isSingleChar = utils.isCharacterBox(group.body);
9621
9622 if (label === "sout") {
9623 img = buildCommon.makeSpan(["stretchy", "sout"]);
9624 img.height = options.fontMetrics().defaultRuleThickness / scale;
9625 imgShift = -0.5 * options.fontMetrics().xHeight;
9626 } else if (label === "phase") {
9627 // Set a couple of dimensions from the steinmetz package.
9628 var lineWeight = calculateSize({
9629 number: 0.6,
9630 unit: "pt"
9631 }, options);
9632 var clearance = calculateSize({
9633 number: 0.35,
9634 unit: "ex"
9635 }, options); // Prevent size changes like \Huge from affecting line thickness
9636
9637 var newOptions = options.havingBaseSizing();
9638 scale = scale / newOptions.sizeMultiplier;
9639 var angleHeight = inner.height + inner.depth + lineWeight + clearance; // Reserve a left pad for the angle.
9640
9641 inner.style.paddingLeft = makeEm(angleHeight / 2 + lineWeight); // Create an SVG
9642
9643 var viewBoxHeight = Math.floor(1000 * angleHeight * scale);
9644 var path = phasePath(viewBoxHeight);
9645 var svgNode = new SvgNode([new PathNode("phase", path)], {
9646 "width": "400em",
9647 "height": makeEm(viewBoxHeight / 1000),
9648 "viewBox": "0 0 400000 " + viewBoxHeight,
9649 "preserveAspectRatio": "xMinYMin slice"
9650 }); // Wrap it in a span with overflow: hidden.
9651
9652 img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options);
9653 img.style.height = makeEm(angleHeight);
9654 imgShift = inner.depth + lineWeight + clearance;
9655 } else {
9656 // Add horizontal padding
9657 if (/cancel/.test(label)) {
9658 if (!isSingleChar) {
9659 inner.classes.push("cancel-pad");
9660 }
9661 } else if (label === "angl") {
9662 inner.classes.push("anglpad");
9663 } else {
9664 inner.classes.push("boxpad");
9665 } // Add vertical padding
9666
9667
9668 var topPad = 0;
9669 var bottomPad = 0;
9670 var ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2"
9671
9672 if (/box/.test(label)) {
9673 ruleThickness = Math.max(options.fontMetrics().fboxrule, // default
9674 options.minRuleThickness // User override.
9675 );
9676 topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness);
9677 bottomPad = topPad;
9678 } else if (label === "angl") {
9679 ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
9680 topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself.
9681
9682 bottomPad = Math.max(0, 0.25 - inner.depth);
9683 } else {
9684 topPad = isSingleChar ? 0.2 : 0;
9685 bottomPad = topPad;
9686 }
9687
9688 img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options);
9689
9690 if (/fbox|boxed|fcolorbox/.test(label)) {
9691 img.style.borderStyle = "solid";
9692 img.style.borderWidth = makeEm(ruleThickness);
9693 } else if (label === "angl" && ruleThickness !== 0.049) {
9694 img.style.borderTopWidth = makeEm(ruleThickness);
9695 img.style.borderRightWidth = makeEm(ruleThickness);
9696 }
9697
9698 imgShift = inner.depth + bottomPad;
9699
9700 if (group.backgroundColor) {
9701 img.style.backgroundColor = group.backgroundColor;
9702
9703 if (group.borderColor) {
9704 img.style.borderColor = group.borderColor;
9705 }
9706 }
9707 }
9708
9709 var vlist;
9710
9711 if (group.backgroundColor) {
9712 vlist = buildCommon.makeVList({
9713 positionType: "individualShift",
9714 children: [// Put the color background behind inner;
9715 {
9716 type: "elem",
9717 elem: img,
9718 shift: imgShift
9719 }, {
9720 type: "elem",
9721 elem: inner,
9722 shift: 0
9723 }]
9724 }, options);
9725 } else {
9726 var classes = /cancel|phase/.test(label) ? ["svg-align"] : [];
9727 vlist = buildCommon.makeVList({
9728 positionType: "individualShift",
9729 children: [// Write the \cancel stroke on top of inner.
9730 {
9731 type: "elem",
9732 elem: inner,
9733 shift: 0
9734 }, {
9735 type: "elem",
9736 elem: img,
9737 shift: imgShift,
9738 wrapperClasses: classes
9739 }]
9740 }, options);
9741 }
9742
9743 if (/cancel/.test(label)) {
9744 // The cancel package documentation says that cancel lines add their height
9745 // to the expression, but tests show that isn't how it actually works.
9746 vlist.height = inner.height;
9747 vlist.depth = inner.depth;
9748 }
9749
9750 if (/cancel/.test(label) && !isSingleChar) {
9751 // cancel does not create horiz space for its line extension.
9752 return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options);
9753 } else {
9754 return buildCommon.makeSpan(["mord"], [vlist], options);
9755 }
9756};
9757
9758var mathmlBuilder$7 = (group, options) => {
9759 var fboxsep = 0;
9760 var node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup(group.body, options)]);
9761
9762 switch (group.label) {
9763 case "\\cancel":
9764 node.setAttribute("notation", "updiagonalstrike");
9765 break;
9766
9767 case "\\bcancel":
9768 node.setAttribute("notation", "downdiagonalstrike");
9769 break;
9770
9771 case "\\phase":
9772 node.setAttribute("notation", "phasorangle");
9773 break;
9774
9775 case "\\sout":
9776 node.setAttribute("notation", "horizontalstrike");
9777 break;
9778
9779 case "\\fbox":
9780 node.setAttribute("notation", "box");
9781 break;
9782
9783 case "\\angl":
9784 node.setAttribute("notation", "actuarial");
9785 break;
9786
9787 case "\\fcolorbox":
9788 case "\\colorbox":
9789 // <menclose> doesn't have a good notation option. So use <mpadded>
9790 // instead. Set some attributes that come included with <menclose>.
9791 fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm;
9792 node.setAttribute("width", "+" + 2 * fboxsep + "pt");
9793 node.setAttribute("height", "+" + 2 * fboxsep + "pt");
9794 node.setAttribute("lspace", fboxsep + "pt"); //
9795
9796 node.setAttribute("voffset", fboxsep + "pt");
9797
9798 if (group.label === "\\fcolorbox") {
9799 var thk = Math.max(options.fontMetrics().fboxrule, // default
9800 options.minRuleThickness // user override
9801 );
9802 node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor));
9803 }
9804
9805 break;
9806
9807 case "\\xcancel":
9808 node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
9809 break;
9810 }
9811
9812 if (group.backgroundColor) {
9813 node.setAttribute("mathbackground", group.backgroundColor);
9814 }
9815
9816 return node;
9817};
9818
9819defineFunction({
9820 type: "enclose",
9821 names: ["\\colorbox"],
9822 props: {
9823 numArgs: 2,
9824 allowedInText: true,
9825 argTypes: ["color", "text"]
9826 },
9827
9828 handler(_ref, args, optArgs) {
9829 var {
9830 parser,
9831 funcName
9832 } = _ref;
9833 var color = assertNodeType(args[0], "color-token").color;
9834 var body = args[1];
9835 return {
9836 type: "enclose",
9837 mode: parser.mode,
9838 label: funcName,
9839 backgroundColor: color,
9840 body
9841 };
9842 },
9843
9844 htmlBuilder: htmlBuilder$8,
9845 mathmlBuilder: mathmlBuilder$7
9846});
9847defineFunction({
9848 type: "enclose",
9849 names: ["\\fcolorbox"],
9850 props: {
9851 numArgs: 3,
9852 allowedInText: true,
9853 argTypes: ["color", "color", "text"]
9854 },
9855
9856 handler(_ref2, args, optArgs) {
9857 var {
9858 parser,
9859 funcName
9860 } = _ref2;
9861 var borderColor = assertNodeType(args[0], "color-token").color;
9862 var backgroundColor = assertNodeType(args[1], "color-token").color;
9863 var body = args[2];
9864 return {
9865 type: "enclose",
9866 mode: parser.mode,
9867 label: funcName,
9868 backgroundColor,
9869 borderColor,
9870 body
9871 };
9872 },
9873
9874 htmlBuilder: htmlBuilder$8,
9875 mathmlBuilder: mathmlBuilder$7
9876});
9877defineFunction({
9878 type: "enclose",
9879 names: ["\\fbox"],
9880 props: {
9881 numArgs: 1,
9882 argTypes: ["hbox"],
9883 allowedInText: true
9884 },
9885
9886 handler(_ref3, args) {
9887 var {
9888 parser
9889 } = _ref3;
9890 return {
9891 type: "enclose",
9892 mode: parser.mode,
9893 label: "\\fbox",
9894 body: args[0]
9895 };
9896 }
9897
9898});
9899defineFunction({
9900 type: "enclose",
9901 names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"],
9902 props: {
9903 numArgs: 1
9904 },
9905
9906 handler(_ref4, args) {
9907 var {
9908 parser,
9909 funcName
9910 } = _ref4;
9911 var body = args[0];
9912 return {
9913 type: "enclose",
9914 mode: parser.mode,
9915 label: funcName,
9916 body
9917 };
9918 },
9919
9920 htmlBuilder: htmlBuilder$8,
9921 mathmlBuilder: mathmlBuilder$7
9922});
9923defineFunction({
9924 type: "enclose",
9925 names: ["\\angl"],
9926 props: {
9927 numArgs: 1,
9928 argTypes: ["hbox"],
9929 allowedInText: false
9930 },
9931
9932 handler(_ref5, args) {
9933 var {
9934 parser
9935 } = _ref5;
9936 return {
9937 type: "enclose",
9938 mode: parser.mode,
9939 label: "\\angl",
9940 body: args[0]
9941 };
9942 }
9943
9944});
9945
9946/**
9947 * All registered environments.
9948 * `environments.js` exports this same dictionary again and makes it public.
9949 * `Parser.js` requires this dictionary via `environments.js`.
9950 */
9951var _environments = {};
9952function defineEnvironment(_ref) {
9953 var {
9954 type,
9955 names,
9956 props,
9957 handler,
9958 htmlBuilder,
9959 mathmlBuilder
9960 } = _ref;
9961 // Set default values of environments.
9962 var data = {
9963 type,
9964 numArgs: props.numArgs || 0,
9965 allowedInText: false,
9966 numOptionalArgs: 0,
9967 handler
9968 };
9969
9970 for (var i = 0; i < names.length; ++i) {
9971 // TODO: The value type of _environments should be a type union of all
9972 // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
9973 // an existential type.
9974 _environments[names[i]] = data;
9975 }
9976
9977 if (htmlBuilder) {
9978 _htmlGroupBuilders[type] = htmlBuilder;
9979 }
9980
9981 if (mathmlBuilder) {
9982 _mathmlGroupBuilders[type] = mathmlBuilder;
9983 }
9984}
9985
9986/**
9987 * All registered global/built-in macros.
9988 * `macros.js` exports this same dictionary again and makes it public.
9989 * `Parser.js` requires this dictionary via `macros.js`.
9990 */
9991var _macros = {}; // This function might one day accept an additional argument and do more things.
9992
9993function defineMacro(name, body) {
9994 _macros[name] = body;
9995}
9996
9997// Helper functions
9998function getHLines(parser) {
9999 // Return an array. The array length = number of hlines.
10000 // Each element in the array tells if the line is dashed.
10001 var hlineInfo = [];
10002 parser.consumeSpaces();
10003 var nxt = parser.fetch().text;
10004
10005 while (nxt === "\\hline" || nxt === "\\hdashline") {
10006 parser.consume();
10007 hlineInfo.push(nxt === "\\hdashline");
10008 parser.consumeSpaces();
10009 nxt = parser.fetch().text;
10010 }
10011
10012 return hlineInfo;
10013}
10014
10015var validateAmsEnvironmentContext = context => {
10016 var settings = context.parser.settings;
10017
10018 if (!settings.displayMode) {
10019 throw new ParseError("{" + context.envName + "} can be used only in" + " display mode.");
10020 }
10021}; // autoTag (an argument to parseArray) can be one of three values:
10022// * undefined: Regular (not-top-level) array; no tags on each row
10023// * true: Automatic equation numbering, overridable by \tag
10024// * false: Tags allowed on each row, but no automatic numbering
10025// This function *doesn't* work with the "split" environment name.
10026
10027
10028function getAutoTag(name) {
10029 if (name.indexOf("ed") === -1) {
10030 return name.indexOf("*") === -1;
10031 } // return undefined;
10032
10033}
10034/**
10035 * Parse the body of the environment, with rows delimited by \\ and
10036 * columns delimited by &, and create a nested list in row-major order
10037 * with one group per cell. If given an optional argument style
10038 * ("text", "display", etc.), then each cell is cast into that style.
10039 */
10040
10041
10042function parseArray(parser, _ref, style) {
10043 var {
10044 hskipBeforeAndAfter,
10045 addJot,
10046 cols,
10047 arraystretch,
10048 colSeparationType,
10049 autoTag,
10050 singleRow,
10051 emptySingleRow,
10052 maxNumCols,
10053 leqno
10054 } = _ref;
10055 parser.gullet.beginGroup();
10056
10057 if (!singleRow) {
10058 // \cr is equivalent to \\ without the optional size argument (see below)
10059 // TODO: provide helpful error when \cr is used outside array environment
10060 parser.gullet.macros.set("\\cr", "\\\\\\relax");
10061 } // Get current arraystretch if it's not set by the environment
10062
10063
10064 if (!arraystretch) {
10065 var stretch = parser.gullet.expandMacroAsText("\\arraystretch");
10066
10067 if (stretch == null) {
10068 // Default \arraystretch from lttab.dtx
10069 arraystretch = 1;
10070 } else {
10071 arraystretch = parseFloat(stretch);
10072
10073 if (!arraystretch || arraystretch < 0) {
10074 throw new ParseError("Invalid \\arraystretch: " + stretch);
10075 }
10076 }
10077 } // Start group for first cell
10078
10079
10080 parser.gullet.beginGroup();
10081 var row = [];
10082 var body = [row];
10083 var rowGaps = [];
10084 var hLinesBeforeRow = [];
10085 var tags = autoTag != null ? [] : undefined; // amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent
10086 // whether this row should have an equation number. Simulate this with
10087 // a \@eqnsw macro set to 1 or 0.
10088
10089 function beginRow() {
10090 if (autoTag) {
10091 parser.gullet.macros.set("\\@eqnsw", "1", true);
10092 }
10093 }
10094
10095 function endRow() {
10096 if (tags) {
10097 if (parser.gullet.macros.get("\\df@tag")) {
10098 tags.push(parser.subparse([new Token("\\df@tag")]));
10099 parser.gullet.macros.set("\\df@tag", undefined, true);
10100 } else {
10101 tags.push(Boolean(autoTag) && parser.gullet.macros.get("\\@eqnsw") === "1");
10102 }
10103 }
10104 }
10105
10106 beginRow(); // Test for \hline at the top of the array.
10107
10108 hLinesBeforeRow.push(getHLines(parser));
10109
10110 while (true) {
10111 // eslint-disable-line no-constant-condition
10112 // Parse each cell in its own group (namespace)
10113 var cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
10114 parser.gullet.endGroup();
10115 parser.gullet.beginGroup();
10116 cell = {
10117 type: "ordgroup",
10118 mode: parser.mode,
10119 body: cell
10120 };
10121
10122 if (style) {
10123 cell = {
10124 type: "styling",
10125 mode: parser.mode,
10126 style,
10127 body: [cell]
10128 };
10129 }
10130
10131 row.push(cell);
10132 var next = parser.fetch().text;
10133
10134 if (next === "&") {
10135 if (maxNumCols && row.length === maxNumCols) {
10136 if (singleRow || colSeparationType) {
10137 // {equation} or {split}
10138 throw new ParseError("Too many tab characters: &", parser.nextToken);
10139 } else {
10140 // {array} environment
10141 parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument.");
10142 }
10143 }
10144
10145 parser.consume();
10146 } else if (next === "\\end") {
10147 endRow(); // Arrays terminate newlines with `\crcr` which consumes a `\cr` if
10148 // the last line is empty. However, AMS environments keep the
10149 // empty row if it's the only one.
10150 // NOTE: Currently, `cell` is the last item added into `row`.
10151
10152 if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0 && (body.length > 1 || !emptySingleRow)) {
10153 body.pop();
10154 }
10155
10156 if (hLinesBeforeRow.length < body.length + 1) {
10157 hLinesBeforeRow.push([]);
10158 }
10159
10160 break;
10161 } else if (next === "\\\\") {
10162 parser.consume();
10163 var size = void 0; // \def\Let@{\let\\\math@cr}
10164 // \def\math@cr{...\math@cr@}
10165 // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}}
10166 // \def\math@cr@@[#1]{...\math@cr@@@...}
10167 // \def\math@cr@@@{\cr}
10168
10169 if (parser.gullet.future().text !== " ") {
10170 size = parser.parseSizeGroup(true);
10171 }
10172
10173 rowGaps.push(size ? size.value : null);
10174 endRow(); // check for \hline(s) following the row separator
10175
10176 hLinesBeforeRow.push(getHLines(parser));
10177 row = [];
10178 body.push(row);
10179 beginRow();
10180 } else {
10181 throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken);
10182 }
10183 } // End cell group
10184
10185
10186 parser.gullet.endGroup(); // End array group defining \cr
10187
10188 parser.gullet.endGroup();
10189 return {
10190 type: "array",
10191 mode: parser.mode,
10192 addJot,
10193 arraystretch,
10194 body,
10195 cols,
10196 rowGaps,
10197 hskipBeforeAndAfter,
10198 hLinesBeforeRow,
10199 colSeparationType,
10200 tags,
10201 leqno
10202 };
10203} // Decides on a style for cells in an array according to whether the given
10204// environment name starts with the letter 'd'.
10205
10206
10207function dCellStyle(envName) {
10208 if (envName.substr(0, 1) === "d") {
10209 return "display";
10210 } else {
10211 return "text";
10212 }
10213}
10214
10215var htmlBuilder$7 = function htmlBuilder(group, options) {
10216 var r;
10217 var c;
10218 var nr = group.body.length;
10219 var hLinesBeforeRow = group.hLinesBeforeRow;
10220 var nc = 0;
10221 var body = new Array(nr);
10222 var hlines = [];
10223 var ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.
10224 options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override.
10225 ); // Horizontal spacing
10226
10227 var pt = 1 / options.fontMetrics().ptPerEm;
10228 var arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls
10229
10230 if (group.colSeparationType && group.colSeparationType === "small") {
10231 // We're in a {smallmatrix}. Default column space is \thickspace,
10232 // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.
10233 // But that needs adjustment because LaTeX applies \scriptstyle to the
10234 // entire array, including the colspace, but this function applies
10235 // \scriptstyle only inside each element.
10236 var localMultiplier = options.havingStyle(Style$1.SCRIPT).sizeMultiplier;
10237 arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);
10238 } // Vertical spacing
10239
10240
10241 var baselineskip = group.colSeparationType === "CD" ? calculateSize({
10242 number: 3,
10243 unit: "ex"
10244 }, options) : 12 * pt; // see size10.clo
10245 // Default \jot from ltmath.dtx
10246 // TODO(edemaine): allow overriding \jot via \setlength (#687)
10247
10248 var jot = 3 * pt;
10249 var arrayskip = group.arraystretch * baselineskip;
10250 var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
10251
10252 var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
10253
10254 var totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any.
10255
10256 function setHLinePos(hlinesInGap) {
10257 for (var i = 0; i < hlinesInGap.length; ++i) {
10258 if (i > 0) {
10259 totalHeight += 0.25;
10260 }
10261
10262 hlines.push({
10263 pos: totalHeight,
10264 isDashed: hlinesInGap[i]
10265 });
10266 }
10267 }
10268
10269 setHLinePos(hLinesBeforeRow[0]);
10270
10271 for (r = 0; r < group.body.length; ++r) {
10272 var inrow = group.body[r];
10273 var height = arstrutHeight; // \@array adds an \@arstrut
10274
10275 var depth = arstrutDepth; // to each tow (via the template)
10276
10277 if (nc < inrow.length) {
10278 nc = inrow.length;
10279 }
10280
10281 var outrow = new Array(inrow.length);
10282
10283 for (c = 0; c < inrow.length; ++c) {
10284 var elt = buildGroup$1(inrow[c], options);
10285
10286 if (depth < elt.depth) {
10287 depth = elt.depth;
10288 }
10289
10290 if (height < elt.height) {
10291 height = elt.height;
10292 }
10293
10294 outrow[c] = elt;
10295 }
10296
10297 var rowGap = group.rowGaps[r];
10298 var gap = 0;
10299
10300 if (rowGap) {
10301 gap = calculateSize(rowGap, options);
10302
10303 if (gap > 0) {
10304 // \@argarraycr
10305 gap += arstrutDepth;
10306
10307 if (depth < gap) {
10308 depth = gap; // \@xargarraycr
10309 }
10310
10311 gap = 0;
10312 }
10313 } // In AMS multiline environments such as aligned and gathered, rows
10314 // correspond to lines that have additional \jot added to the
10315 // \baselineskip via \openup.
10316
10317
10318 if (group.addJot) {
10319 depth += jot;
10320 }
10321
10322 outrow.height = height;
10323 outrow.depth = depth;
10324 totalHeight += height;
10325 outrow.pos = totalHeight;
10326 totalHeight += depth + gap; // \@yargarraycr
10327
10328 body[r] = outrow; // Set a position for \hline(s), if any.
10329
10330 setHLinePos(hLinesBeforeRow[r + 1]);
10331 }
10332
10333 var offset = totalHeight / 2 + options.fontMetrics().axisHeight;
10334 var colDescriptions = group.cols || [];
10335 var cols = [];
10336 var colSep;
10337 var colDescrNum;
10338 var tagSpans = [];
10339
10340 if (group.tags && group.tags.some(tag => tag)) {
10341 // An environment with manual tags and/or automatic equation numbers.
10342 // Create node(s), the latter of which trigger CSS counter increment.
10343 for (r = 0; r < nr; ++r) {
10344 var rw = body[r];
10345 var shift = rw.pos - offset;
10346 var tag = group.tags[r];
10347 var tagSpan = void 0;
10348
10349 if (tag === true) {
10350 // automatic numbering
10351 tagSpan = buildCommon.makeSpan(["eqn-num"], [], options);
10352 } else if (tag === false) {
10353 // \nonumber/\notag or starred environment
10354 tagSpan = buildCommon.makeSpan([], [], options);
10355 } else {
10356 // manual \tag
10357 tagSpan = buildCommon.makeSpan([], buildExpression$1(tag, options, true), options);
10358 }
10359
10360 tagSpan.depth = rw.depth;
10361 tagSpan.height = rw.height;
10362 tagSpans.push({
10363 type: "elem",
10364 elem: tagSpan,
10365 shift
10366 });
10367 }
10368 }
10369
10370 for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column
10371 // descriptions, so trailing separators don't get lost.
10372 c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) {
10373 var colDescr = colDescriptions[colDescrNum] || {};
10374 var firstSeparator = true;
10375
10376 while (colDescr.type === "separator") {
10377 // If there is more than one separator in a row, add a space
10378 // between them.
10379 if (!firstSeparator) {
10380 colSep = buildCommon.makeSpan(["arraycolsep"], []);
10381 colSep.style.width = makeEm(options.fontMetrics().doubleRuleSep);
10382 cols.push(colSep);
10383 }
10384
10385 if (colDescr.separator === "|" || colDescr.separator === ":") {
10386 var lineType = colDescr.separator === "|" ? "solid" : "dashed";
10387 var separator = buildCommon.makeSpan(["vertical-separator"], [], options);
10388 separator.style.height = makeEm(totalHeight);
10389 separator.style.borderRightWidth = makeEm(ruleThickness);
10390 separator.style.borderRightStyle = lineType;
10391 separator.style.margin = "0 " + makeEm(-ruleThickness / 2);
10392
10393 var _shift = totalHeight - offset;
10394
10395 if (_shift) {
10396 separator.style.verticalAlign = makeEm(-_shift);
10397 }
10398
10399 cols.push(separator);
10400 } else {
10401 throw new ParseError("Invalid separator type: " + colDescr.separator);
10402 }
10403
10404 colDescrNum++;
10405 colDescr = colDescriptions[colDescrNum] || {};
10406 firstSeparator = false;
10407 }
10408
10409 if (c >= nc) {
10410 continue;
10411 }
10412
10413 var sepwidth = void 0;
10414
10415 if (c > 0 || group.hskipBeforeAndAfter) {
10416 sepwidth = utils.deflt(colDescr.pregap, arraycolsep);
10417
10418 if (sepwidth !== 0) {
10419 colSep = buildCommon.makeSpan(["arraycolsep"], []);
10420 colSep.style.width = makeEm(sepwidth);
10421 cols.push(colSep);
10422 }
10423 }
10424
10425 var col = [];
10426
10427 for (r = 0; r < nr; ++r) {
10428 var row = body[r];
10429 var elem = row[c];
10430
10431 if (!elem) {
10432 continue;
10433 }
10434
10435 var _shift2 = row.pos - offset;
10436
10437 elem.depth = row.depth;
10438 elem.height = row.height;
10439 col.push({
10440 type: "elem",
10441 elem: elem,
10442 shift: _shift2
10443 });
10444 }
10445
10446 col = buildCommon.makeVList({
10447 positionType: "individualShift",
10448 children: col
10449 }, options);
10450 col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]);
10451 cols.push(col);
10452
10453 if (c < nc - 1 || group.hskipBeforeAndAfter) {
10454 sepwidth = utils.deflt(colDescr.postgap, arraycolsep);
10455
10456 if (sepwidth !== 0) {
10457 colSep = buildCommon.makeSpan(["arraycolsep"], []);
10458 colSep.style.width = makeEm(sepwidth);
10459 cols.push(colSep);
10460 }
10461 }
10462 }
10463
10464 body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any.
10465
10466 if (hlines.length > 0) {
10467 var line = buildCommon.makeLineSpan("hline", options, ruleThickness);
10468 var dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness);
10469 var vListElems = [{
10470 type: "elem",
10471 elem: body,
10472 shift: 0
10473 }];
10474
10475 while (hlines.length > 0) {
10476 var hline = hlines.pop();
10477 var lineShift = hline.pos - offset;
10478
10479 if (hline.isDashed) {
10480 vListElems.push({
10481 type: "elem",
10482 elem: dashes,
10483 shift: lineShift
10484 });
10485 } else {
10486 vListElems.push({
10487 type: "elem",
10488 elem: line,
10489 shift: lineShift
10490 });
10491 }
10492 }
10493
10494 body = buildCommon.makeVList({
10495 positionType: "individualShift",
10496 children: vListElems
10497 }, options);
10498 }
10499
10500 if (tagSpans.length === 0) {
10501 return buildCommon.makeSpan(["mord"], [body], options);
10502 } else {
10503 var eqnNumCol = buildCommon.makeVList({
10504 positionType: "individualShift",
10505 children: tagSpans
10506 }, options);
10507 eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options);
10508 return buildCommon.makeFragment([body, eqnNumCol]);
10509 }
10510};
10511
10512var alignMap = {
10513 c: "center ",
10514 l: "left ",
10515 r: "right "
10516};
10517
10518var mathmlBuilder$6 = function mathmlBuilder(group, options) {
10519 var tbl = [];
10520 var glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]);
10521 var tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]);
10522
10523 for (var i = 0; i < group.body.length; i++) {
10524 var rw = group.body[i];
10525 var row = [];
10526
10527 for (var j = 0; j < rw.length; j++) {
10528 row.push(new mathMLTree.MathNode("mtd", [buildGroup(rw[j], options)]));
10529 }
10530
10531 if (group.tags && group.tags[i]) {
10532 row.unshift(glue);
10533 row.push(glue);
10534
10535 if (group.leqno) {
10536 row.unshift(tag);
10537 } else {
10538 row.push(tag);
10539 }
10540 }
10541
10542 tbl.push(new mathMLTree.MathNode("mtr", row));
10543 }
10544
10545 var table = new mathMLTree.MathNode("mtable", tbl); // Set column alignment, row spacing, column spacing, and
10546 // array lines by setting attributes on the table element.
10547 // Set the row spacing. In MathML, we specify a gap distance.
10548 // We do not use rowGap[] because MathML automatically increases
10549 // cell height with the height/depth of the element content.
10550 // LaTeX \arraystretch multiplies the row baseline-to-baseline distance.
10551 // We simulate this by adding (arraystretch - 1)em to the gap. This
10552 // does a reasonable job of adjusting arrays containing 1 em tall content.
10553 // The 0.16 and 0.09 values are found emprically. They produce an array
10554 // similar to LaTeX and in which content does not interfere with \hines.
10555
10556 var gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray}
10557 : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
10558 table.setAttribute("rowspacing", makeEm(gap)); // MathML table lines go only between cells.
10559 // To place a line on an edge we'll use <menclose>, if necessary.
10560
10561 var menclose = "";
10562 var align = "";
10563
10564 if (group.cols && group.cols.length > 0) {
10565 // Find column alignment, column spacing, and vertical lines.
10566 var cols = group.cols;
10567 var columnLines = "";
10568 var prevTypeWasAlign = false;
10569 var iStart = 0;
10570 var iEnd = cols.length;
10571
10572 if (cols[0].type === "separator") {
10573 menclose += "top ";
10574 iStart = 1;
10575 }
10576
10577 if (cols[cols.length - 1].type === "separator") {
10578 menclose += "bottom ";
10579 iEnd -= 1;
10580 }
10581
10582 for (var _i = iStart; _i < iEnd; _i++) {
10583 if (cols[_i].type === "align") {
10584 align += alignMap[cols[_i].align];
10585
10586 if (prevTypeWasAlign) {
10587 columnLines += "none ";
10588 }
10589
10590 prevTypeWasAlign = true;
10591 } else if (cols[_i].type === "separator") {
10592 // MathML accepts only single lines between cells.
10593 // So we read only the first of consecutive separators.
10594 if (prevTypeWasAlign) {
10595 columnLines += cols[_i].separator === "|" ? "solid " : "dashed ";
10596 prevTypeWasAlign = false;
10597 }
10598 }
10599 }
10600
10601 table.setAttribute("columnalign", align.trim());
10602
10603 if (/[sd]/.test(columnLines)) {
10604 table.setAttribute("columnlines", columnLines.trim());
10605 }
10606 } // Set column spacing.
10607
10608
10609 if (group.colSeparationType === "align") {
10610 var _cols = group.cols || [];
10611
10612 var spacing = "";
10613
10614 for (var _i2 = 1; _i2 < _cols.length; _i2++) {
10615 spacing += _i2 % 2 ? "0em " : "1em ";
10616 }
10617
10618 table.setAttribute("columnspacing", spacing.trim());
10619 } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") {
10620 table.setAttribute("columnspacing", "0em");
10621 } else if (group.colSeparationType === "small") {
10622 table.setAttribute("columnspacing", "0.2778em");
10623 } else if (group.colSeparationType === "CD") {
10624 table.setAttribute("columnspacing", "0.5em");
10625 } else {
10626 table.setAttribute("columnspacing", "1em");
10627 } // Address \hline and \hdashline
10628
10629
10630 var rowLines = "";
10631 var hlines = group.hLinesBeforeRow;
10632 menclose += hlines[0].length > 0 ? "left " : "";
10633 menclose += hlines[hlines.length - 1].length > 0 ? "right " : "";
10634
10635 for (var _i3 = 1; _i3 < hlines.length - 1; _i3++) {
10636 rowLines += hlines[_i3].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element.
10637 : hlines[_i3][0] ? "dashed " : "solid ";
10638 }
10639
10640 if (/[sd]/.test(rowLines)) {
10641 table.setAttribute("rowlines", rowLines.trim());
10642 }
10643
10644 if (menclose !== "") {
10645 table = new mathMLTree.MathNode("menclose", [table]);
10646 table.setAttribute("notation", menclose.trim());
10647 }
10648
10649 if (group.arraystretch && group.arraystretch < 1) {
10650 // A small array. Wrap in scriptstyle so row gap is not too large.
10651 table = new mathMLTree.MathNode("mstyle", [table]);
10652 table.setAttribute("scriptlevel", "1");
10653 }
10654
10655 return table;
10656}; // Convenience function for align, align*, aligned, alignat, alignat*, alignedat.
10657
10658
10659var alignedHandler = function alignedHandler(context, args) {
10660 if (context.envName.indexOf("ed") === -1) {
10661 validateAmsEnvironmentContext(context);
10662 }
10663
10664 var cols = [];
10665 var separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align";
10666 var isSplit = context.envName === "split";
10667 var res = parseArray(context.parser, {
10668 cols,
10669 addJot: true,
10670 autoTag: isSplit ? undefined : getAutoTag(context.envName),
10671 emptySingleRow: true,
10672 colSeparationType: separationType,
10673 maxNumCols: isSplit ? 2 : undefined,
10674 leqno: context.parser.settings.leqno
10675 }, "display"); // Determining number of columns.
10676 // 1. If the first argument is given, we use it as a number of columns,
10677 // and makes sure that each row doesn't exceed that number.
10678 // 2. Otherwise, just count number of columns = maximum number
10679 // of cells in each row ("aligned" mode -- isAligned will be true).
10680 //
10681 // At the same time, prepend empty group {} at beginning of every second
10682 // cell in each row (starting with second cell) so that operators become
10683 // binary. This behavior is implemented in amsmath's \start@aligned.
10684
10685 var numMaths;
10686 var numCols = 0;
10687 var emptyGroup = {
10688 type: "ordgroup",
10689 mode: context.mode,
10690 body: []
10691 };
10692
10693 if (args[0] && args[0].type === "ordgroup") {
10694 var arg0 = "";
10695
10696 for (var i = 0; i < args[0].body.length; i++) {
10697 var textord = assertNodeType(args[0].body[i], "textord");
10698 arg0 += textord.text;
10699 }
10700
10701 numMaths = Number(arg0);
10702 numCols = numMaths * 2;
10703 }
10704
10705 var isAligned = !numCols;
10706 res.body.forEach(function (row) {
10707 for (var _i4 = 1; _i4 < row.length; _i4 += 2) {
10708 // Modify ordgroup node within styling node
10709 var styling = assertNodeType(row[_i4], "styling");
10710 var ordgroup = assertNodeType(styling.body[0], "ordgroup");
10711 ordgroup.body.unshift(emptyGroup);
10712 }
10713
10714 if (!isAligned) {
10715 // Case 1
10716 var curMaths = row.length / 2;
10717
10718 if (numMaths < curMaths) {
10719 throw new ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]);
10720 }
10721 } else if (numCols < row.length) {
10722 // Case 2
10723 numCols = row.length;
10724 }
10725 }); // Adjusting alignment.
10726 // In aligned mode, we add one \qquad between columns;
10727 // otherwise we add nothing.
10728
10729 for (var _i5 = 0; _i5 < numCols; ++_i5) {
10730 var align = "r";
10731 var pregap = 0;
10732
10733 if (_i5 % 2 === 1) {
10734 align = "l";
10735 } else if (_i5 > 0 && isAligned) {
10736 // "aligned" mode.
10737 pregap = 1; // add one \quad
10738 }
10739
10740 cols[_i5] = {
10741 type: "align",
10742 align: align,
10743 pregap: pregap,
10744 postgap: 0
10745 };
10746 }
10747
10748 res.colSeparationType = isAligned ? "align" : "alignat";
10749 return res;
10750}; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation
10751// is part of the source2e.pdf file of LaTeX2e source documentation.
10752// {darray} is an {array} environment where cells are set in \displaystyle,
10753// as defined in nccmath.sty.
10754
10755
10756defineEnvironment({
10757 type: "array",
10758 names: ["array", "darray"],
10759 props: {
10760 numArgs: 1
10761 },
10762
10763 handler(context, args) {
10764 // Since no types are specified above, the two possibilities are
10765 // - The argument is wrapped in {} or [], in which case Parser's
10766 // parseGroup() returns an "ordgroup" wrapping some symbol node.
10767 // - The argument is a bare symbol node.
10768 var symNode = checkSymbolNodeType(args[0]);
10769 var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
10770 var cols = colalign.map(function (nde) {
10771 var node = assertSymbolNodeType(nde);
10772 var ca = node.text;
10773
10774 if ("lcr".indexOf(ca) !== -1) {
10775 return {
10776 type: "align",
10777 align: ca
10778 };
10779 } else if (ca === "|") {
10780 return {
10781 type: "separator",
10782 separator: "|"
10783 };
10784 } else if (ca === ":") {
10785 return {
10786 type: "separator",
10787 separator: ":"
10788 };
10789 }
10790
10791 throw new ParseError("Unknown column alignment: " + ca, nde);
10792 });
10793 var res = {
10794 cols,
10795 hskipBeforeAndAfter: true,
10796 // \@preamble in lttab.dtx
10797 maxNumCols: cols.length
10798 };
10799 return parseArray(context.parser, res, dCellStyle(context.envName));
10800 },
10801
10802 htmlBuilder: htmlBuilder$7,
10803 mathmlBuilder: mathmlBuilder$6
10804}); // The matrix environments of amsmath builds on the array environment
10805// of LaTeX, which is discussed above.
10806// The mathtools package adds starred versions of the same environments.
10807// These have an optional argument to choose left|center|right justification.
10808
10809defineEnvironment({
10810 type: "array",
10811 names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"],
10812 props: {
10813 numArgs: 0
10814 },
10815
10816 handler(context) {
10817 var delimiters = {
10818 "matrix": null,
10819 "pmatrix": ["(", ")"],
10820 "bmatrix": ["[", "]"],
10821 "Bmatrix": ["\\{", "\\}"],
10822 "vmatrix": ["|", "|"],
10823 "Vmatrix": ["\\Vert", "\\Vert"]
10824 }[context.envName.replace("*", "")]; // \hskip -\arraycolsep in amsmath
10825
10826 var colAlign = "c";
10827 var payload = {
10828 hskipBeforeAndAfter: false,
10829 cols: [{
10830 type: "align",
10831 align: colAlign
10832 }]
10833 };
10834
10835 if (context.envName.charAt(context.envName.length - 1) === "*") {
10836 // It's one of the mathtools starred functions.
10837 // Parse the optional alignment argument.
10838 var parser = context.parser;
10839 parser.consumeSpaces();
10840
10841 if (parser.fetch().text === "[") {
10842 parser.consume();
10843 parser.consumeSpaces();
10844 colAlign = parser.fetch().text;
10845
10846 if ("lcr".indexOf(colAlign) === -1) {
10847 throw new ParseError("Expected l or c or r", parser.nextToken);
10848 }
10849
10850 parser.consume();
10851 parser.consumeSpaces();
10852 parser.expect("]");
10853 parser.consume();
10854 payload.cols = [{
10855 type: "align",
10856 align: colAlign
10857 }];
10858 }
10859 }
10860
10861 var res = parseArray(context.parser, payload, dCellStyle(context.envName)); // Populate cols with the correct number of column alignment specs.
10862
10863 var numCols = Math.max(0, ...res.body.map(row => row.length));
10864 res.cols = new Array(numCols).fill({
10865 type: "align",
10866 align: colAlign
10867 });
10868 return delimiters ? {
10869 type: "leftright",
10870 mode: context.mode,
10871 body: [res],
10872 left: delimiters[0],
10873 right: delimiters[1],
10874 rightColor: undefined // \right uninfluenced by \color in array
10875
10876 } : res;
10877 },
10878
10879 htmlBuilder: htmlBuilder$7,
10880 mathmlBuilder: mathmlBuilder$6
10881});
10882defineEnvironment({
10883 type: "array",
10884 names: ["smallmatrix"],
10885 props: {
10886 numArgs: 0
10887 },
10888
10889 handler(context) {
10890 var payload = {
10891 arraystretch: 0.5
10892 };
10893 var res = parseArray(context.parser, payload, "script");
10894 res.colSeparationType = "small";
10895 return res;
10896 },
10897
10898 htmlBuilder: htmlBuilder$7,
10899 mathmlBuilder: mathmlBuilder$6
10900});
10901defineEnvironment({
10902 type: "array",
10903 names: ["subarray"],
10904 props: {
10905 numArgs: 1
10906 },
10907
10908 handler(context, args) {
10909 // Parsing of {subarray} is similar to {array}
10910 var symNode = checkSymbolNodeType(args[0]);
10911 var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
10912 var cols = colalign.map(function (nde) {
10913 var node = assertSymbolNodeType(nde);
10914 var ca = node.text; // {subarray} only recognizes "l" & "c"
10915
10916 if ("lc".indexOf(ca) !== -1) {
10917 return {
10918 type: "align",
10919 align: ca
10920 };
10921 }
10922
10923 throw new ParseError("Unknown column alignment: " + ca, nde);
10924 });
10925
10926 if (cols.length > 1) {
10927 throw new ParseError("{subarray} can contain only one column");
10928 }
10929
10930 var res = {
10931 cols,
10932 hskipBeforeAndAfter: false,
10933 arraystretch: 0.5
10934 };
10935 res = parseArray(context.parser, res, "script");
10936
10937 if (res.body.length > 0 && res.body[0].length > 1) {
10938 throw new ParseError("{subarray} can contain only one column");
10939 }
10940
10941 return res;
10942 },
10943
10944 htmlBuilder: htmlBuilder$7,
10945 mathmlBuilder: mathmlBuilder$6
10946}); // A cases environment (in amsmath.sty) is almost equivalent to
10947// \def\arraystretch{1.2}%
10948// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
10949// {dcases} is a {cases} environment where cells are set in \displaystyle,
10950// as defined in mathtools.sty.
10951// {rcases} is another mathtools environment. It's brace is on the right side.
10952
10953defineEnvironment({
10954 type: "array",
10955 names: ["cases", "dcases", "rcases", "drcases"],
10956 props: {
10957 numArgs: 0
10958 },
10959
10960 handler(context) {
10961 var payload = {
10962 arraystretch: 1.2,
10963 cols: [{
10964 type: "align",
10965 align: "l",
10966 pregap: 0,
10967 // TODO(kevinb) get the current style.
10968 // For now we use the metrics for TEXT style which is what we were
10969 // doing before. Before attempting to get the current style we
10970 // should look at TeX's behavior especially for \over and matrices.
10971 postgap: 1.0
10972 /* 1em quad */
10973
10974 }, {
10975 type: "align",
10976 align: "l",
10977 pregap: 0,
10978 postgap: 0
10979 }]
10980 };
10981 var res = parseArray(context.parser, payload, dCellStyle(context.envName));
10982 return {
10983 type: "leftright",
10984 mode: context.mode,
10985 body: [res],
10986 left: context.envName.indexOf("r") > -1 ? "." : "\\{",
10987 right: context.envName.indexOf("r") > -1 ? "\\}" : ".",
10988 rightColor: undefined
10989 };
10990 },
10991
10992 htmlBuilder: htmlBuilder$7,
10993 mathmlBuilder: mathmlBuilder$6
10994}); // In the align environment, one uses ampersands, &, to specify number of
10995// columns in each row, and to locate spacing between each column.
10996// align gets automatic numbering. align* and aligned do not.
10997// The alignedat environment can be used in math mode.
10998// Note that we assume \nomallineskiplimit to be zero,
10999// so that \strut@ is the same as \strut.
11000
11001defineEnvironment({
11002 type: "array",
11003 names: ["align", "align*", "aligned", "split"],
11004 props: {
11005 numArgs: 0
11006 },
11007 handler: alignedHandler,
11008 htmlBuilder: htmlBuilder$7,
11009 mathmlBuilder: mathmlBuilder$6
11010}); // A gathered environment is like an array environment with one centered
11011// column, but where rows are considered lines so get \jot line spacing
11012// and contents are set in \displaystyle.
11013
11014defineEnvironment({
11015 type: "array",
11016 names: ["gathered", "gather", "gather*"],
11017 props: {
11018 numArgs: 0
11019 },
11020
11021 handler(context) {
11022 if (utils.contains(["gather", "gather*"], context.envName)) {
11023 validateAmsEnvironmentContext(context);
11024 }
11025
11026 var res = {
11027 cols: [{
11028 type: "align",
11029 align: "c"
11030 }],
11031 addJot: true,
11032 colSeparationType: "gather",
11033 autoTag: getAutoTag(context.envName),
11034 emptySingleRow: true,
11035 leqno: context.parser.settings.leqno
11036 };
11037 return parseArray(context.parser, res, "display");
11038 },
11039
11040 htmlBuilder: htmlBuilder$7,
11041 mathmlBuilder: mathmlBuilder$6
11042}); // alignat environment is like an align environment, but one must explicitly
11043// specify maximum number of columns in each row, and can adjust spacing between
11044// each columns.
11045
11046defineEnvironment({
11047 type: "array",
11048 names: ["alignat", "alignat*", "alignedat"],
11049 props: {
11050 numArgs: 1
11051 },
11052 handler: alignedHandler,
11053 htmlBuilder: htmlBuilder$7,
11054 mathmlBuilder: mathmlBuilder$6
11055});
11056defineEnvironment({
11057 type: "array",
11058 names: ["equation", "equation*"],
11059 props: {
11060 numArgs: 0
11061 },
11062
11063 handler(context) {
11064 validateAmsEnvironmentContext(context);
11065 var res = {
11066 autoTag: getAutoTag(context.envName),
11067 emptySingleRow: true,
11068 singleRow: true,
11069 maxNumCols: 1,
11070 leqno: context.parser.settings.leqno
11071 };
11072 return parseArray(context.parser, res, "display");
11073 },
11074
11075 htmlBuilder: htmlBuilder$7,
11076 mathmlBuilder: mathmlBuilder$6
11077});
11078defineEnvironment({
11079 type: "array",
11080 names: ["CD"],
11081 props: {
11082 numArgs: 0
11083 },
11084
11085 handler(context) {
11086 validateAmsEnvironmentContext(context);
11087 return parseCD(context.parser);
11088 },
11089
11090 htmlBuilder: htmlBuilder$7,
11091 mathmlBuilder: mathmlBuilder$6
11092});
11093defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}");
11094defineMacro("\\notag", "\\nonumber"); // Catch \hline outside array environment
11095
11096defineFunction({
11097 type: "text",
11098 // Doesn't matter what this is.
11099 names: ["\\hline", "\\hdashline"],
11100 props: {
11101 numArgs: 0,
11102 allowedInText: true,
11103 allowedInMath: true
11104 },
11105
11106 handler(context, args) {
11107 throw new ParseError(context.funcName + " valid only within array environment");
11108 }
11109
11110});
11111
11112var environments = _environments;
11113
11114// defineEnvironment definitions.
11115
11116defineFunction({
11117 type: "environment",
11118 names: ["\\begin", "\\end"],
11119 props: {
11120 numArgs: 1,
11121 argTypes: ["text"]
11122 },
11123
11124 handler(_ref, args) {
11125 var {
11126 parser,
11127 funcName
11128 } = _ref;
11129 var nameGroup = args[0];
11130
11131 if (nameGroup.type !== "ordgroup") {
11132 throw new ParseError("Invalid environment name", nameGroup);
11133 }
11134
11135 var envName = "";
11136
11137 for (var i = 0; i < nameGroup.body.length; ++i) {
11138 envName += assertNodeType(nameGroup.body[i], "textord").text;
11139 }
11140
11141 if (funcName === "\\begin") {
11142 // begin...end is similar to left...right
11143 if (!environments.hasOwnProperty(envName)) {
11144 throw new ParseError("No such environment: " + envName, nameGroup);
11145 } // Build the environment object. Arguments and other information will
11146 // be made available to the begin and end methods using properties.
11147
11148
11149 var env = environments[envName];
11150 var {
11151 args: _args,
11152 optArgs
11153 } = parser.parseArguments("\\begin{" + envName + "}", env);
11154 var context = {
11155 mode: parser.mode,
11156 envName,
11157 parser
11158 };
11159 var result = env.handler(context, _args, optArgs);
11160 parser.expect("\\end", false);
11161 var endNameToken = parser.nextToken;
11162 var end = assertNodeType(parser.parseFunction(), "environment");
11163
11164 if (end.name !== envName) {
11165 throw new ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken);
11166 } // $FlowFixMe, "environment" handler returns an environment ParseNode
11167
11168
11169 return result;
11170 }
11171
11172 return {
11173 type: "environment",
11174 mode: parser.mode,
11175 name: envName,
11176 nameGroup
11177 };
11178 }
11179
11180});
11181
11182var makeSpan = buildCommon.makeSpan;
11183
11184function htmlBuilder$6(group, options) {
11185 var elements = buildExpression$1(group.body, options, true);
11186 return makeSpan([group.mclass], elements, options);
11187}
11188
11189function mathmlBuilder$5(group, options) {
11190 var node;
11191 var inner = buildExpression(group.body, options);
11192
11193 if (group.mclass === "minner") {
11194 node = new mathMLTree.MathNode("mpadded", inner);
11195 } else if (group.mclass === "mord") {
11196 if (group.isCharacterBox) {
11197 node = inner[0];
11198 node.type = "mi";
11199 } else {
11200 node = new mathMLTree.MathNode("mi", inner);
11201 }
11202 } else {
11203 if (group.isCharacterBox) {
11204 node = inner[0];
11205 node.type = "mo";
11206 } else {
11207 node = new mathMLTree.MathNode("mo", inner);
11208 } // Set spacing based on what is the most likely adjacent atom type.
11209 // See TeXbook p170.
11210
11211
11212 if (group.mclass === "mbin") {
11213 node.attributes.lspace = "0.22em"; // medium space
11214
11215 node.attributes.rspace = "0.22em";
11216 } else if (group.mclass === "mpunct") {
11217 node.attributes.lspace = "0em";
11218 node.attributes.rspace = "0.17em"; // thinspace
11219 } else if (group.mclass === "mopen" || group.mclass === "mclose") {
11220 node.attributes.lspace = "0em";
11221 node.attributes.rspace = "0em";
11222 } else if (group.mclass === "minner") {
11223 node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option
11224
11225 node.attributes.width = "+0.1111em";
11226 } // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
11227 // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
11228
11229 }
11230
11231 return node;
11232} // Math class commands except \mathop
11233
11234
11235defineFunction({
11236 type: "mclass",
11237 names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
11238 props: {
11239 numArgs: 1,
11240 primitive: true
11241 },
11242
11243 handler(_ref, args) {
11244 var {
11245 parser,
11246 funcName
11247 } = _ref;
11248 var body = args[0];
11249 return {
11250 type: "mclass",
11251 mode: parser.mode,
11252 mclass: "m" + funcName.substr(5),
11253 // TODO(kevinb): don't prefix with 'm'
11254 body: ordargument(body),
11255 isCharacterBox: utils.isCharacterBox(body)
11256 };
11257 },
11258
11259 htmlBuilder: htmlBuilder$6,
11260 mathmlBuilder: mathmlBuilder$5
11261});
11262var binrelClass = arg => {
11263 // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
11264 // (by rendering separately and with {}s before and after, and measuring
11265 // the change in spacing). We'll do roughly the same by detecting the
11266 // atom type directly.
11267 var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
11268
11269 if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
11270 return "m" + atom.family;
11271 } else {
11272 return "mord";
11273 }
11274}; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
11275// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
11276
11277defineFunction({
11278 type: "mclass",
11279 names: ["\\@binrel"],
11280 props: {
11281 numArgs: 2
11282 },
11283
11284 handler(_ref2, args) {
11285 var {
11286 parser
11287 } = _ref2;
11288 return {
11289 type: "mclass",
11290 mode: parser.mode,
11291 mclass: binrelClass(args[0]),
11292 body: ordargument(args[1]),
11293 isCharacterBox: utils.isCharacterBox(args[1])
11294 };
11295 }
11296
11297}); // Build a relation or stacked op by placing one symbol on top of another
11298
11299defineFunction({
11300 type: "mclass",
11301 names: ["\\stackrel", "\\overset", "\\underset"],
11302 props: {
11303 numArgs: 2
11304 },
11305
11306 handler(_ref3, args) {
11307 var {
11308 parser,
11309 funcName
11310 } = _ref3;
11311 var baseArg = args[1];
11312 var shiftedArg = args[0];
11313 var mclass;
11314
11315 if (funcName !== "\\stackrel") {
11316 // LaTeX applies \binrel spacing to \overset and \underset.
11317 mclass = binrelClass(baseArg);
11318 } else {
11319 mclass = "mrel"; // for \stackrel
11320 }
11321
11322 var baseOp = {
11323 type: "op",
11324 mode: baseArg.mode,
11325 limits: true,
11326 alwaysHandleSupSub: true,
11327 parentIsSupSub: false,
11328 symbol: false,
11329 suppressBaseShift: funcName !== "\\stackrel",
11330 body: ordargument(baseArg)
11331 };
11332 var supsub = {
11333 type: "supsub",
11334 mode: shiftedArg.mode,
11335 base: baseOp,
11336 sup: funcName === "\\underset" ? null : shiftedArg,
11337 sub: funcName === "\\underset" ? shiftedArg : null
11338 };
11339 return {
11340 type: "mclass",
11341 mode: parser.mode,
11342 mclass,
11343 body: [supsub],
11344 isCharacterBox: utils.isCharacterBox(supsub)
11345 };
11346 },
11347
11348 htmlBuilder: htmlBuilder$6,
11349 mathmlBuilder: mathmlBuilder$5
11350});
11351
11352// TODO(kevinb): implement \\sl and \\sc
11353
11354var htmlBuilder$5 = (group, options) => {
11355 var font = group.font;
11356 var newOptions = options.withFont(font);
11357 return buildGroup$1(group.body, newOptions);
11358};
11359
11360var mathmlBuilder$4 = (group, options) => {
11361 var font = group.font;
11362 var newOptions = options.withFont(font);
11363 return buildGroup(group.body, newOptions);
11364};
11365
11366var fontAliases = {
11367 "\\Bbb": "\\mathbb",
11368 "\\bold": "\\mathbf",
11369 "\\frak": "\\mathfrak",
11370 "\\bm": "\\boldsymbol"
11371};
11372defineFunction({
11373 type: "font",
11374 names: [// styles, except \boldsymbol defined below
11375 "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", // families
11376 "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below
11377 "\\Bbb", "\\bold", "\\frak"],
11378 props: {
11379 numArgs: 1,
11380 allowedInArgument: true
11381 },
11382 handler: (_ref, args) => {
11383 var {
11384 parser,
11385 funcName
11386 } = _ref;
11387 var body = normalizeArgument(args[0]);
11388 var func = funcName;
11389
11390 if (func in fontAliases) {
11391 func = fontAliases[func];
11392 }
11393
11394 return {
11395 type: "font",
11396 mode: parser.mode,
11397 font: func.slice(1),
11398 body
11399 };
11400 },
11401 htmlBuilder: htmlBuilder$5,
11402 mathmlBuilder: mathmlBuilder$4
11403});
11404defineFunction({
11405 type: "mclass",
11406 names: ["\\boldsymbol", "\\bm"],
11407 props: {
11408 numArgs: 1
11409 },
11410 handler: (_ref2, args) => {
11411 var {
11412 parser
11413 } = _ref2;
11414 var body = args[0];
11415 var isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the
11416 // argument's bin|rel|ord status
11417
11418 return {
11419 type: "mclass",
11420 mode: parser.mode,
11421 mclass: binrelClass(body),
11422 body: [{
11423 type: "font",
11424 mode: parser.mode,
11425 font: "boldsymbol",
11426 body
11427 }],
11428 isCharacterBox: isCharacterBox
11429 };
11430 }
11431}); // Old font changing functions
11432
11433defineFunction({
11434 type: "font",
11435 names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"],
11436 props: {
11437 numArgs: 0,
11438 allowedInText: true
11439 },
11440 handler: (_ref3, args) => {
11441 var {
11442 parser,
11443 funcName,
11444 breakOnTokenText
11445 } = _ref3;
11446 var {
11447 mode
11448 } = parser;
11449 var body = parser.parseExpression(true, breakOnTokenText);
11450 var style = "math" + funcName.slice(1);
11451 return {
11452 type: "font",
11453 mode: mode,
11454 font: style,
11455 body: {
11456 type: "ordgroup",
11457 mode: parser.mode,
11458 body
11459 }
11460 };
11461 },
11462 htmlBuilder: htmlBuilder$5,
11463 mathmlBuilder: mathmlBuilder$4
11464});
11465
11466var adjustStyle = (size, originalStyle) => {
11467 // Figure out what style this fraction should be in based on the
11468 // function used
11469 var style = originalStyle;
11470
11471 if (size === "display") {
11472 // Get display style as a default.
11473 // If incoming style is sub/sup, use style.text() to get correct size.
11474 style = style.id >= Style$1.SCRIPT.id ? style.text() : Style$1.DISPLAY;
11475 } else if (size === "text" && style.size === Style$1.DISPLAY.size) {
11476 // We're in a \tfrac but incoming style is displaystyle, so:
11477 style = Style$1.TEXT;
11478 } else if (size === "script") {
11479 style = Style$1.SCRIPT;
11480 } else if (size === "scriptscript") {
11481 style = Style$1.SCRIPTSCRIPT;
11482 }
11483
11484 return style;
11485};
11486
11487var htmlBuilder$4 = (group, options) => {
11488 // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
11489 var style = adjustStyle(group.size, options.style);
11490 var nstyle = style.fracNum();
11491 var dstyle = style.fracDen();
11492 var newOptions;
11493 newOptions = options.havingStyle(nstyle);
11494 var numerm = buildGroup$1(group.numer, newOptions, options);
11495
11496 if (group.continued) {
11497 // \cfrac inserts a \strut into the numerator.
11498 // Get \strut dimensions from TeXbook page 353.
11499 var hStrut = 8.5 / options.fontMetrics().ptPerEm;
11500 var dStrut = 3.5 / options.fontMetrics().ptPerEm;
11501 numerm.height = numerm.height < hStrut ? hStrut : numerm.height;
11502 numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth;
11503 }
11504
11505 newOptions = options.havingStyle(dstyle);
11506 var denomm = buildGroup$1(group.denom, newOptions, options);
11507 var rule;
11508 var ruleWidth;
11509 var ruleSpacing;
11510
11511 if (group.hasBarLine) {
11512 if (group.barSize) {
11513 ruleWidth = calculateSize(group.barSize, options);
11514 rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth);
11515 } else {
11516 rule = buildCommon.makeLineSpan("frac-line", options);
11517 }
11518
11519 ruleWidth = rule.height;
11520 ruleSpacing = rule.height;
11521 } else {
11522 rule = null;
11523 ruleWidth = 0;
11524 ruleSpacing = options.fontMetrics().defaultRuleThickness;
11525 } // Rule 15b
11526
11527
11528 var numShift;
11529 var clearance;
11530 var denomShift;
11531
11532 if (style.size === Style$1.DISPLAY.size || group.size === "display") {
11533 numShift = options.fontMetrics().num1;
11534
11535 if (ruleWidth > 0) {
11536 clearance = 3 * ruleSpacing;
11537 } else {
11538 clearance = 7 * ruleSpacing;
11539 }
11540
11541 denomShift = options.fontMetrics().denom1;
11542 } else {
11543 if (ruleWidth > 0) {
11544 numShift = options.fontMetrics().num2;
11545 clearance = ruleSpacing;
11546 } else {
11547 numShift = options.fontMetrics().num3;
11548 clearance = 3 * ruleSpacing;
11549 }
11550
11551 denomShift = options.fontMetrics().denom2;
11552 }
11553
11554 var frac;
11555
11556 if (!rule) {
11557 // Rule 15c
11558 var candidateClearance = numShift - numerm.depth - (denomm.height - denomShift);
11559
11560 if (candidateClearance < clearance) {
11561 numShift += 0.5 * (clearance - candidateClearance);
11562 denomShift += 0.5 * (clearance - candidateClearance);
11563 }
11564
11565 frac = buildCommon.makeVList({
11566 positionType: "individualShift",
11567 children: [{
11568 type: "elem",
11569 elem: denomm,
11570 shift: denomShift
11571 }, {
11572 type: "elem",
11573 elem: numerm,
11574 shift: -numShift
11575 }]
11576 }, options);
11577 } else {
11578 // Rule 15d
11579 var axisHeight = options.fontMetrics().axisHeight;
11580
11581 if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) {
11582 numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth));
11583 }
11584
11585 if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) {
11586 denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift));
11587 }
11588
11589 var midShift = -(axisHeight - 0.5 * ruleWidth);
11590 frac = buildCommon.makeVList({
11591 positionType: "individualShift",
11592 children: [{
11593 type: "elem",
11594 elem: denomm,
11595 shift: denomShift
11596 }, {
11597 type: "elem",
11598 elem: rule,
11599 shift: midShift
11600 }, {
11601 type: "elem",
11602 elem: numerm,
11603 shift: -numShift
11604 }]
11605 }, options);
11606 } // Since we manually change the style sometimes (with \dfrac or \tfrac),
11607 // account for the possible size change here.
11608
11609
11610 newOptions = options.havingStyle(style);
11611 frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier;
11612 frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e
11613
11614 var delimSize;
11615
11616 if (style.size === Style$1.DISPLAY.size) {
11617 delimSize = options.fontMetrics().delim1;
11618 } else if (style.size === Style$1.SCRIPTSCRIPT.size) {
11619 delimSize = options.havingStyle(Style$1.SCRIPT).fontMetrics().delim2;
11620 } else {
11621 delimSize = options.fontMetrics().delim2;
11622 }
11623
11624 var leftDelim;
11625 var rightDelim;
11626
11627 if (group.leftDelim == null) {
11628 leftDelim = makeNullDelimiter(options, ["mopen"]);
11629 } else {
11630 leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]);
11631 }
11632
11633 if (group.continued) {
11634 rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac
11635 } else if (group.rightDelim == null) {
11636 rightDelim = makeNullDelimiter(options, ["mclose"]);
11637 } else {
11638 rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]);
11639 }
11640
11641 return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options);
11642};
11643
11644var mathmlBuilder$3 = (group, options) => {
11645 var node = new mathMLTree.MathNode("mfrac", [buildGroup(group.numer, options), buildGroup(group.denom, options)]);
11646
11647 if (!group.hasBarLine) {
11648 node.setAttribute("linethickness", "0px");
11649 } else if (group.barSize) {
11650 var ruleWidth = calculateSize(group.barSize, options);
11651 node.setAttribute("linethickness", makeEm(ruleWidth));
11652 }
11653
11654 var style = adjustStyle(group.size, options.style);
11655
11656 if (style.size !== options.style.size) {
11657 node = new mathMLTree.MathNode("mstyle", [node]);
11658 var isDisplay = style.size === Style$1.DISPLAY.size ? "true" : "false";
11659 node.setAttribute("displaystyle", isDisplay);
11660 node.setAttribute("scriptlevel", "0");
11661 }
11662
11663 if (group.leftDelim != null || group.rightDelim != null) {
11664 var withDelims = [];
11665
11666 if (group.leftDelim != null) {
11667 var leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]);
11668 leftOp.setAttribute("fence", "true");
11669 withDelims.push(leftOp);
11670 }
11671
11672 withDelims.push(node);
11673
11674 if (group.rightDelim != null) {
11675 var rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]);
11676 rightOp.setAttribute("fence", "true");
11677 withDelims.push(rightOp);
11678 }
11679
11680 return makeRow(withDelims);
11681 }
11682
11683 return node;
11684};
11685
11686defineFunction({
11687 type: "genfrac",
11688 names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly
11689 "\\\\bracefrac", "\\\\brackfrac" // ditto
11690 ],
11691 props: {
11692 numArgs: 2,
11693 allowedInArgument: true
11694 },
11695 handler: (_ref, args) => {
11696 var {
11697 parser,
11698 funcName
11699 } = _ref;
11700 var numer = args[0];
11701 var denom = args[1];
11702 var hasBarLine;
11703 var leftDelim = null;
11704 var rightDelim = null;
11705 var size = "auto";
11706
11707 switch (funcName) {
11708 case "\\dfrac":
11709 case "\\frac":
11710 case "\\tfrac":
11711 hasBarLine = true;
11712 break;
11713
11714 case "\\\\atopfrac":
11715 hasBarLine = false;
11716 break;
11717
11718 case "\\dbinom":
11719 case "\\binom":
11720 case "\\tbinom":
11721 hasBarLine = false;
11722 leftDelim = "(";
11723 rightDelim = ")";
11724 break;
11725
11726 case "\\\\bracefrac":
11727 hasBarLine = false;
11728 leftDelim = "\\{";
11729 rightDelim = "\\}";
11730 break;
11731
11732 case "\\\\brackfrac":
11733 hasBarLine = false;
11734 leftDelim = "[";
11735 rightDelim = "]";
11736 break;
11737
11738 default:
11739 throw new Error("Unrecognized genfrac command");
11740 }
11741
11742 switch (funcName) {
11743 case "\\dfrac":
11744 case "\\dbinom":
11745 size = "display";
11746 break;
11747
11748 case "\\tfrac":
11749 case "\\tbinom":
11750 size = "text";
11751 break;
11752 }
11753
11754 return {
11755 type: "genfrac",
11756 mode: parser.mode,
11757 continued: false,
11758 numer,
11759 denom,
11760 hasBarLine,
11761 leftDelim,
11762 rightDelim,
11763 size,
11764 barSize: null
11765 };
11766 },
11767 htmlBuilder: htmlBuilder$4,
11768 mathmlBuilder: mathmlBuilder$3
11769});
11770defineFunction({
11771 type: "genfrac",
11772 names: ["\\cfrac"],
11773 props: {
11774 numArgs: 2
11775 },
11776 handler: (_ref2, args) => {
11777 var {
11778 parser,
11779 funcName
11780 } = _ref2;
11781 var numer = args[0];
11782 var denom = args[1];
11783 return {
11784 type: "genfrac",
11785 mode: parser.mode,
11786 continued: true,
11787 numer,
11788 denom,
11789 hasBarLine: true,
11790 leftDelim: null,
11791 rightDelim: null,
11792 size: "display",
11793 barSize: null
11794 };
11795 }
11796}); // Infix generalized fractions -- these are not rendered directly, but replaced
11797// immediately by one of the variants above.
11798
11799defineFunction({
11800 type: "infix",
11801 names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"],
11802 props: {
11803 numArgs: 0,
11804 infix: true
11805 },
11806
11807 handler(_ref3) {
11808 var {
11809 parser,
11810 funcName,
11811 token
11812 } = _ref3;
11813 var replaceWith;
11814
11815 switch (funcName) {
11816 case "\\over":
11817 replaceWith = "\\frac";
11818 break;
11819
11820 case "\\choose":
11821 replaceWith = "\\binom";
11822 break;
11823
11824 case "\\atop":
11825 replaceWith = "\\\\atopfrac";
11826 break;
11827
11828 case "\\brace":
11829 replaceWith = "\\\\bracefrac";
11830 break;
11831
11832 case "\\brack":
11833 replaceWith = "\\\\brackfrac";
11834 break;
11835
11836 default:
11837 throw new Error("Unrecognized infix genfrac command");
11838 }
11839
11840 return {
11841 type: "infix",
11842 mode: parser.mode,
11843 replaceWith,
11844 token
11845 };
11846 }
11847
11848});
11849var stylArray = ["display", "text", "script", "scriptscript"];
11850
11851var delimFromValue = function delimFromValue(delimString) {
11852 var delim = null;
11853
11854 if (delimString.length > 0) {
11855 delim = delimString;
11856 delim = delim === "." ? null : delim;
11857 }
11858
11859 return delim;
11860};
11861
11862defineFunction({
11863 type: "genfrac",
11864 names: ["\\genfrac"],
11865 props: {
11866 numArgs: 6,
11867 allowedInArgument: true,
11868 argTypes: ["math", "math", "size", "text", "math", "math"]
11869 },
11870
11871 handler(_ref4, args) {
11872 var {
11873 parser
11874 } = _ref4;
11875 var numer = args[4];
11876 var denom = args[5]; // Look into the parse nodes to get the desired delimiters.
11877
11878 var leftNode = normalizeArgument(args[0]);
11879 var leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null;
11880 var rightNode = normalizeArgument(args[1]);
11881 var rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null;
11882 var barNode = assertNodeType(args[2], "size");
11883 var hasBarLine;
11884 var barSize = null;
11885
11886 if (barNode.isBlank) {
11887 // \genfrac acts differently than \above.
11888 // \genfrac treats an empty size group as a signal to use a
11889 // standard bar size. \above would see size = 0 and omit the bar.
11890 hasBarLine = true;
11891 } else {
11892 barSize = barNode.value;
11893 hasBarLine = barSize.number > 0;
11894 } // Find out if we want displaystyle, textstyle, etc.
11895
11896
11897 var size = "auto";
11898 var styl = args[3];
11899
11900 if (styl.type === "ordgroup") {
11901 if (styl.body.length > 0) {
11902 var textOrd = assertNodeType(styl.body[0], "textord");
11903 size = stylArray[Number(textOrd.text)];
11904 }
11905 } else {
11906 styl = assertNodeType(styl, "textord");
11907 size = stylArray[Number(styl.text)];
11908 }
11909
11910 return {
11911 type: "genfrac",
11912 mode: parser.mode,
11913 numer,
11914 denom,
11915 continued: false,
11916 hasBarLine,
11917 barSize,
11918 leftDelim,
11919 rightDelim,
11920 size
11921 };
11922 },
11923
11924 htmlBuilder: htmlBuilder$4,
11925 mathmlBuilder: mathmlBuilder$3
11926}); // \above is an infix fraction that also defines a fraction bar size.
11927
11928defineFunction({
11929 type: "infix",
11930 names: ["\\above"],
11931 props: {
11932 numArgs: 1,
11933 argTypes: ["size"],
11934 infix: true
11935 },
11936
11937 handler(_ref5, args) {
11938 var {
11939 parser,
11940 funcName,
11941 token
11942 } = _ref5;
11943 return {
11944 type: "infix",
11945 mode: parser.mode,
11946 replaceWith: "\\\\abovefrac",
11947 size: assertNodeType(args[0], "size").value,
11948 token
11949 };
11950 }
11951
11952});
11953defineFunction({
11954 type: "genfrac",
11955 names: ["\\\\abovefrac"],
11956 props: {
11957 numArgs: 3,
11958 argTypes: ["math", "size", "math"]
11959 },
11960 handler: (_ref6, args) => {
11961 var {
11962 parser,
11963 funcName
11964 } = _ref6;
11965 var numer = args[0];
11966 var barSize = assert(assertNodeType(args[1], "infix").size);
11967 var denom = args[2];
11968 var hasBarLine = barSize.number > 0;
11969 return {
11970 type: "genfrac",
11971 mode: parser.mode,
11972 numer,
11973 denom,
11974 continued: false,
11975 hasBarLine,
11976 barSize,
11977 leftDelim: null,
11978 rightDelim: null,
11979 size: "auto"
11980 };
11981 },
11982 htmlBuilder: htmlBuilder$4,
11983 mathmlBuilder: mathmlBuilder$3
11984});
11985
11986// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but
11987// also "supsub" since an over/underbrace can affect super/subscripting.
11988var htmlBuilder$3 = (grp, options) => {
11989 var style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node.
11990
11991 var supSubGroup;
11992 var group;
11993
11994 if (grp.type === "supsub") {
11995 // Ref: LaTeX source2e: }}}}\limits}
11996 // i.e. LaTeX treats the brace similar to an op and passes it
11997 // with \limits, so we need to assign supsub style.
11998 supSubGroup = grp.sup ? buildGroup$1(grp.sup, options.havingStyle(style.sup()), options) : buildGroup$1(grp.sub, options.havingStyle(style.sub()), options);
11999 group = assertNodeType(grp.base, "horizBrace");
12000 } else {
12001 group = assertNodeType(grp, "horizBrace");
12002 } // Build the base group
12003
12004
12005 var body = buildGroup$1(group.base, options.havingBaseStyle(Style$1.DISPLAY)); // Create the stretchy element
12006
12007 var braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns ┏━━━━━━━━┓
12008 // This first vlist contains the content and the brace: equation
12009
12010 var vlist;
12011
12012 if (group.isOver) {
12013 vlist = buildCommon.makeVList({
12014 positionType: "firstBaseline",
12015 children: [{
12016 type: "elem",
12017 elem: body
12018 }, {
12019 type: "kern",
12020 size: 0.1
12021 }, {
12022 type: "elem",
12023 elem: braceBody
12024 }]
12025 }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
12026
12027 vlist.children[0].children[0].children[1].classes.push("svg-align");
12028 } else {
12029 vlist = buildCommon.makeVList({
12030 positionType: "bottom",
12031 positionData: body.depth + 0.1 + braceBody.height,
12032 children: [{
12033 type: "elem",
12034 elem: braceBody
12035 }, {
12036 type: "kern",
12037 size: 0.1
12038 }, {
12039 type: "elem",
12040 elem: body
12041 }]
12042 }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
12043
12044 vlist.children[0].children[0].children[0].classes.push("svg-align");
12045 }
12046
12047 if (supSubGroup) {
12048 // To write the supsub, wrap the first vlist in another vlist:
12049 // They can't all go in the same vlist, because the note might be
12050 // wider than the equation. We want the equation to control the
12051 // brace width.
12052 // note long note long note
12053 // ┏━━━━━━━━┓ or ┏━━━┓ not ┏━━━━━━━━━┓
12054 // equation eqn eqn
12055 var vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
12056
12057 if (group.isOver) {
12058 vlist = buildCommon.makeVList({
12059 positionType: "firstBaseline",
12060 children: [{
12061 type: "elem",
12062 elem: vSpan
12063 }, {
12064 type: "kern",
12065 size: 0.2
12066 }, {
12067 type: "elem",
12068 elem: supSubGroup
12069 }]
12070 }, options);
12071 } else {
12072 vlist = buildCommon.makeVList({
12073 positionType: "bottom",
12074 positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth,
12075 children: [{
12076 type: "elem",
12077 elem: supSubGroup
12078 }, {
12079 type: "kern",
12080 size: 0.2
12081 }, {
12082 type: "elem",
12083 elem: vSpan
12084 }]
12085 }, options);
12086 }
12087 }
12088
12089 return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
12090};
12091
12092var mathmlBuilder$2 = (group, options) => {
12093 var accentNode = stretchy.mathMLnode(group.label);
12094 return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildGroup(group.base, options), accentNode]);
12095}; // Horizontal stretchy braces
12096
12097
12098defineFunction({
12099 type: "horizBrace",
12100 names: ["\\overbrace", "\\underbrace"],
12101 props: {
12102 numArgs: 1
12103 },
12104
12105 handler(_ref, args) {
12106 var {
12107 parser,
12108 funcName
12109 } = _ref;
12110 return {
12111 type: "horizBrace",
12112 mode: parser.mode,
12113 label: funcName,
12114 isOver: /^\\over/.test(funcName),
12115 base: args[0]
12116 };
12117 },
12118
12119 htmlBuilder: htmlBuilder$3,
12120 mathmlBuilder: mathmlBuilder$2
12121});
12122
12123defineFunction({
12124 type: "href",
12125 names: ["\\href"],
12126 props: {
12127 numArgs: 2,
12128 argTypes: ["url", "original"],
12129 allowedInText: true
12130 },
12131 handler: (_ref, args) => {
12132 var {
12133 parser
12134 } = _ref;
12135 var body = args[1];
12136 var href = assertNodeType(args[0], "url").url;
12137
12138 if (!parser.settings.isTrusted({
12139 command: "\\href",
12140 url: href
12141 })) {
12142 return parser.formatUnsupportedCmd("\\href");
12143 }
12144
12145 return {
12146 type: "href",
12147 mode: parser.mode,
12148 href,
12149 body: ordargument(body)
12150 };
12151 },
12152 htmlBuilder: (group, options) => {
12153 var elements = buildExpression$1(group.body, options, false);
12154 return buildCommon.makeAnchor(group.href, [], elements, options);
12155 },
12156 mathmlBuilder: (group, options) => {
12157 var math = buildExpressionRow(group.body, options);
12158
12159 if (!(math instanceof MathNode)) {
12160 math = new MathNode("mrow", [math]);
12161 }
12162
12163 math.setAttribute("href", group.href);
12164 return math;
12165 }
12166});
12167defineFunction({
12168 type: "href",
12169 names: ["\\url"],
12170 props: {
12171 numArgs: 1,
12172 argTypes: ["url"],
12173 allowedInText: true
12174 },
12175 handler: (_ref2, args) => {
12176 var {
12177 parser
12178 } = _ref2;
12179 var href = assertNodeType(args[0], "url").url;
12180
12181 if (!parser.settings.isTrusted({
12182 command: "\\url",
12183 url: href
12184 })) {
12185 return parser.formatUnsupportedCmd("\\url");
12186 }
12187
12188 var chars = [];
12189
12190 for (var i = 0; i < href.length; i++) {
12191 var c = href[i];
12192
12193 if (c === "~") {
12194 c = "\\textasciitilde";
12195 }
12196
12197 chars.push({
12198 type: "textord",
12199 mode: "text",
12200 text: c
12201 });
12202 }
12203
12204 var body = {
12205 type: "text",
12206 mode: parser.mode,
12207 font: "\\texttt",
12208 body: chars
12209 };
12210 return {
12211 type: "href",
12212 mode: parser.mode,
12213 href,
12214 body: ordargument(body)
12215 };
12216 }
12217});
12218
12219// In LaTeX, \vcenter can act only on a box, as in
12220// \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}}
12221// This function by itself doesn't do anything but prevent a soft line break.
12222
12223defineFunction({
12224 type: "hbox",
12225 names: ["\\hbox"],
12226 props: {
12227 numArgs: 1,
12228 argTypes: ["text"],
12229 allowedInText: true,
12230 primitive: true
12231 },
12232
12233 handler(_ref, args) {
12234 var {
12235 parser
12236 } = _ref;
12237 return {
12238 type: "hbox",
12239 mode: parser.mode,
12240 body: ordargument(args[0])
12241 };
12242 },
12243
12244 htmlBuilder(group, options) {
12245 var elements = buildExpression$1(group.body, options, false);
12246 return buildCommon.makeFragment(elements);
12247 },
12248
12249 mathmlBuilder(group, options) {
12250 return new mathMLTree.MathNode("mrow", buildExpression(group.body, options));
12251 }
12252
12253});
12254
12255defineFunction({
12256 type: "html",
12257 names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"],
12258 props: {
12259 numArgs: 2,
12260 argTypes: ["raw", "original"],
12261 allowedInText: true
12262 },
12263 handler: (_ref, args) => {
12264 var {
12265 parser,
12266 funcName,
12267 token
12268 } = _ref;
12269 var value = assertNodeType(args[0], "raw").string;
12270 var body = args[1];
12271
12272 if (parser.settings.strict) {
12273 parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode");
12274 }
12275
12276 var trustContext;
12277 var attributes = {};
12278
12279 switch (funcName) {
12280 case "\\htmlClass":
12281 attributes.class = value;
12282 trustContext = {
12283 command: "\\htmlClass",
12284 class: value
12285 };
12286 break;
12287
12288 case "\\htmlId":
12289 attributes.id = value;
12290 trustContext = {
12291 command: "\\htmlId",
12292 id: value
12293 };
12294 break;
12295
12296 case "\\htmlStyle":
12297 attributes.style = value;
12298 trustContext = {
12299 command: "\\htmlStyle",
12300 style: value
12301 };
12302 break;
12303
12304 case "\\htmlData":
12305 {
12306 var data = value.split(",");
12307
12308 for (var i = 0; i < data.length; i++) {
12309 var keyVal = data[i].split("=");
12310
12311 if (keyVal.length !== 2) {
12312 throw new ParseError("Error parsing key-value for \\htmlData");
12313 }
12314
12315 attributes["data-" + keyVal[0].trim()] = keyVal[1].trim();
12316 }
12317
12318 trustContext = {
12319 command: "\\htmlData",
12320 attributes
12321 };
12322 break;
12323 }
12324
12325 default:
12326 throw new Error("Unrecognized html command");
12327 }
12328
12329 if (!parser.settings.isTrusted(trustContext)) {
12330 return parser.formatUnsupportedCmd(funcName);
12331 }
12332
12333 return {
12334 type: "html",
12335 mode: parser.mode,
12336 attributes,
12337 body: ordargument(body)
12338 };
12339 },
12340 htmlBuilder: (group, options) => {
12341 var elements = buildExpression$1(group.body, options, false);
12342 var classes = ["enclosing"];
12343
12344 if (group.attributes.class) {
12345 classes.push(...group.attributes.class.trim().split(/\s+/));
12346 }
12347
12348 var span = buildCommon.makeSpan(classes, elements, options);
12349
12350 for (var attr in group.attributes) {
12351 if (attr !== "class" && group.attributes.hasOwnProperty(attr)) {
12352 span.setAttribute(attr, group.attributes[attr]);
12353 }
12354 }
12355
12356 return span;
12357 },
12358 mathmlBuilder: (group, options) => {
12359 return buildExpressionRow(group.body, options);
12360 }
12361});
12362
12363defineFunction({
12364 type: "htmlmathml",
12365 names: ["\\html@mathml"],
12366 props: {
12367 numArgs: 2,
12368 allowedInText: true
12369 },
12370 handler: (_ref, args) => {
12371 var {
12372 parser
12373 } = _ref;
12374 return {
12375 type: "htmlmathml",
12376 mode: parser.mode,
12377 html: ordargument(args[0]),
12378 mathml: ordargument(args[1])
12379 };
12380 },
12381 htmlBuilder: (group, options) => {
12382 var elements = buildExpression$1(group.html, options, false);
12383 return buildCommon.makeFragment(elements);
12384 },
12385 mathmlBuilder: (group, options) => {
12386 return buildExpressionRow(group.mathml, options);
12387 }
12388});
12389
12390var sizeData = function sizeData(str) {
12391 if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) {
12392 // str is a number with no unit specified.
12393 // default unit is bp, per graphix package.
12394 return {
12395 number: +str,
12396 unit: "bp"
12397 };
12398 } else {
12399 var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str);
12400
12401 if (!match) {
12402 throw new ParseError("Invalid size: '" + str + "' in \\includegraphics");
12403 }
12404
12405 var data = {
12406 number: +(match[1] + match[2]),
12407 // sign + magnitude, cast to number
12408 unit: match[3]
12409 };
12410
12411 if (!validUnit(data)) {
12412 throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics.");
12413 }
12414
12415 return data;
12416 }
12417};
12418
12419defineFunction({
12420 type: "includegraphics",
12421 names: ["\\includegraphics"],
12422 props: {
12423 numArgs: 1,
12424 numOptionalArgs: 1,
12425 argTypes: ["raw", "url"],
12426 allowedInText: false
12427 },
12428 handler: (_ref, args, optArgs) => {
12429 var {
12430 parser
12431 } = _ref;
12432 var width = {
12433 number: 0,
12434 unit: "em"
12435 };
12436 var height = {
12437 number: 0.9,
12438 unit: "em"
12439 }; // sorta character sized.
12440
12441 var totalheight = {
12442 number: 0,
12443 unit: "em"
12444 };
12445 var alt = "";
12446
12447 if (optArgs[0]) {
12448 var attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string.
12449
12450 var attributes = attributeStr.split(",");
12451
12452 for (var i = 0; i < attributes.length; i++) {
12453 var keyVal = attributes[i].split("=");
12454
12455 if (keyVal.length === 2) {
12456 var str = keyVal[1].trim();
12457
12458 switch (keyVal[0].trim()) {
12459 case "alt":
12460 alt = str;
12461 break;
12462
12463 case "width":
12464 width = sizeData(str);
12465 break;
12466
12467 case "height":
12468 height = sizeData(str);
12469 break;
12470
12471 case "totalheight":
12472 totalheight = sizeData(str);
12473 break;
12474
12475 default:
12476 throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.");
12477 }
12478 }
12479 }
12480 }
12481
12482 var src = assertNodeType(args[0], "url").url;
12483
12484 if (alt === "") {
12485 // No alt given. Use the file name. Strip away the path.
12486 alt = src;
12487 alt = alt.replace(/^.*[\\/]/, '');
12488 alt = alt.substring(0, alt.lastIndexOf('.'));
12489 }
12490
12491 if (!parser.settings.isTrusted({
12492 command: "\\includegraphics",
12493 url: src
12494 })) {
12495 return parser.formatUnsupportedCmd("\\includegraphics");
12496 }
12497
12498 return {
12499 type: "includegraphics",
12500 mode: parser.mode,
12501 alt: alt,
12502 width: width,
12503 height: height,
12504 totalheight: totalheight,
12505 src: src
12506 };
12507 },
12508 htmlBuilder: (group, options) => {
12509 var height = calculateSize(group.height, options);
12510 var depth = 0;
12511
12512 if (group.totalheight.number > 0) {
12513 depth = calculateSize(group.totalheight, options) - height;
12514 }
12515
12516 var width = 0;
12517
12518 if (group.width.number > 0) {
12519 width = calculateSize(group.width, options);
12520 }
12521
12522 var style = {
12523 height: makeEm(height + depth)
12524 };
12525
12526 if (width > 0) {
12527 style.width = makeEm(width);
12528 }
12529
12530 if (depth > 0) {
12531 style.verticalAlign = makeEm(-depth);
12532 }
12533
12534 var node = new Img(group.src, group.alt, style);
12535 node.height = height;
12536 node.depth = depth;
12537 return node;
12538 },
12539 mathmlBuilder: (group, options) => {
12540 var node = new mathMLTree.MathNode("mglyph", []);
12541 node.setAttribute("alt", group.alt);
12542 var height = calculateSize(group.height, options);
12543 var depth = 0;
12544
12545 if (group.totalheight.number > 0) {
12546 depth = calculateSize(group.totalheight, options) - height;
12547 node.setAttribute("valign", makeEm(-depth));
12548 }
12549
12550 node.setAttribute("height", makeEm(height + depth));
12551
12552 if (group.width.number > 0) {
12553 var width = calculateSize(group.width, options);
12554 node.setAttribute("width", makeEm(width));
12555 }
12556
12557 node.setAttribute("src", group.src);
12558 return node;
12559 }
12560});
12561
12562// Horizontal spacing commands
12563
12564defineFunction({
12565 type: "kern",
12566 names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"],
12567 props: {
12568 numArgs: 1,
12569 argTypes: ["size"],
12570 primitive: true,
12571 allowedInText: true
12572 },
12573
12574 handler(_ref, args) {
12575 var {
12576 parser,
12577 funcName
12578 } = _ref;
12579 var size = assertNodeType(args[0], "size");
12580
12581 if (parser.settings.strict) {
12582 var mathFunction = funcName[1] === 'm'; // \mkern, \mskip
12583
12584 var muUnit = size.value.unit === 'mu';
12585
12586 if (mathFunction) {
12587 if (!muUnit) {
12588 parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units"));
12589 }
12590
12591 if (parser.mode !== "math") {
12592 parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode");
12593 }
12594 } else {
12595 // !mathFunction
12596 if (muUnit) {
12597 parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units");
12598 }
12599 }
12600 }
12601
12602 return {
12603 type: "kern",
12604 mode: parser.mode,
12605 dimension: size.value
12606 };
12607 },
12608
12609 htmlBuilder(group, options) {
12610 return buildCommon.makeGlue(group.dimension, options);
12611 },
12612
12613 mathmlBuilder(group, options) {
12614 var dimension = calculateSize(group.dimension, options);
12615 return new mathMLTree.SpaceNode(dimension);
12616 }
12617
12618});
12619
12620// Horizontal overlap functions
12621defineFunction({
12622 type: "lap",
12623 names: ["\\mathllap", "\\mathrlap", "\\mathclap"],
12624 props: {
12625 numArgs: 1,
12626 allowedInText: true
12627 },
12628 handler: (_ref, args) => {
12629 var {
12630 parser,
12631 funcName
12632 } = _ref;
12633 var body = args[0];
12634 return {
12635 type: "lap",
12636 mode: parser.mode,
12637 alignment: funcName.slice(5),
12638 body
12639 };
12640 },
12641 htmlBuilder: (group, options) => {
12642 // mathllap, mathrlap, mathclap
12643 var inner;
12644
12645 if (group.alignment === "clap") {
12646 // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/
12647 inner = buildCommon.makeSpan([], [buildGroup$1(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span
12648
12649 inner = buildCommon.makeSpan(["inner"], [inner], options);
12650 } else {
12651 inner = buildCommon.makeSpan(["inner"], [buildGroup$1(group.body, options)]);
12652 }
12653
12654 var fix = buildCommon.makeSpan(["fix"], []);
12655 var node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the
12656 // two items involved in the lap.
12657 // Next, use a strut to set the height of the HTML bounding box.
12658 // Otherwise, a tall argument may be misplaced.
12659 // This code resolved issue #1153
12660
12661 var strut = buildCommon.makeSpan(["strut"]);
12662 strut.style.height = makeEm(node.height + node.depth);
12663
12664 if (node.depth) {
12665 strut.style.verticalAlign = makeEm(-node.depth);
12666 }
12667
12668 node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall.
12669 // This code resolves issue #1234
12670
12671 node = buildCommon.makeSpan(["thinbox"], [node], options);
12672 return buildCommon.makeSpan(["mord", "vbox"], [node], options);
12673 },
12674 mathmlBuilder: (group, options) => {
12675 // mathllap, mathrlap, mathclap
12676 var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]);
12677
12678 if (group.alignment !== "rlap") {
12679 var offset = group.alignment === "llap" ? "-1" : "-0.5";
12680 node.setAttribute("lspace", offset + "width");
12681 }
12682
12683 node.setAttribute("width", "0px");
12684 return node;
12685 }
12686});
12687
12688defineFunction({
12689 type: "styling",
12690 names: ["\\(", "$"],
12691 props: {
12692 numArgs: 0,
12693 allowedInText: true,
12694 allowedInMath: false
12695 },
12696
12697 handler(_ref, args) {
12698 var {
12699 funcName,
12700 parser
12701 } = _ref;
12702 var outerMode = parser.mode;
12703 parser.switchMode("math");
12704 var close = funcName === "\\(" ? "\\)" : "$";
12705 var body = parser.parseExpression(false, close);
12706 parser.expect(close);
12707 parser.switchMode(outerMode);
12708 return {
12709 type: "styling",
12710 mode: parser.mode,
12711 style: "text",
12712 body
12713 };
12714 }
12715
12716}); // Check for extra closing math delimiters
12717
12718defineFunction({
12719 type: "text",
12720 // Doesn't matter what this is.
12721 names: ["\\)", "\\]"],
12722 props: {
12723 numArgs: 0,
12724 allowedInText: true,
12725 allowedInMath: false
12726 },
12727
12728 handler(context, args) {
12729 throw new ParseError("Mismatched " + context.funcName);
12730 }
12731
12732});
12733
12734var chooseMathStyle = (group, options) => {
12735 switch (options.style.size) {
12736 case Style$1.DISPLAY.size:
12737 return group.display;
12738
12739 case Style$1.TEXT.size:
12740 return group.text;
12741
12742 case Style$1.SCRIPT.size:
12743 return group.script;
12744
12745 case Style$1.SCRIPTSCRIPT.size:
12746 return group.scriptscript;
12747
12748 default:
12749 return group.text;
12750 }
12751};
12752
12753defineFunction({
12754 type: "mathchoice",
12755 names: ["\\mathchoice"],
12756 props: {
12757 numArgs: 4,
12758 primitive: true
12759 },
12760 handler: (_ref, args) => {
12761 var {
12762 parser
12763 } = _ref;
12764 return {
12765 type: "mathchoice",
12766 mode: parser.mode,
12767 display: ordargument(args[0]),
12768 text: ordargument(args[1]),
12769 script: ordargument(args[2]),
12770 scriptscript: ordargument(args[3])
12771 };
12772 },
12773 htmlBuilder: (group, options) => {
12774 var body = chooseMathStyle(group, options);
12775 var elements = buildExpression$1(body, options, false);
12776 return buildCommon.makeFragment(elements);
12777 },
12778 mathmlBuilder: (group, options) => {
12779 var body = chooseMathStyle(group, options);
12780 return buildExpressionRow(body, options);
12781 }
12782});
12783
12784var assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => {
12785 base = buildCommon.makeSpan([], [base]);
12786 var subIsSingleCharacter = subGroup && utils.isCharacterBox(subGroup);
12787 var sub;
12788 var sup; // We manually have to handle the superscripts and subscripts. This,
12789 // aside from the kern calculations, is copied from supsub.
12790
12791 if (supGroup) {
12792 var elem = buildGroup$1(supGroup, options.havingStyle(style.sup()), options);
12793 sup = {
12794 elem,
12795 kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth)
12796 };
12797 }
12798
12799 if (subGroup) {
12800 var _elem = buildGroup$1(subGroup, options.havingStyle(style.sub()), options);
12801
12802 sub = {
12803 elem: _elem,
12804 kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - _elem.height)
12805 };
12806 } // Build the final group as a vlist of the possible subscript, base,
12807 // and possible superscript.
12808
12809
12810 var finalGroup;
12811
12812 if (sup && sub) {
12813 var bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift;
12814 finalGroup = buildCommon.makeVList({
12815 positionType: "bottom",
12816 positionData: bottom,
12817 children: [{
12818 type: "kern",
12819 size: options.fontMetrics().bigOpSpacing5
12820 }, {
12821 type: "elem",
12822 elem: sub.elem,
12823 marginLeft: makeEm(-slant)
12824 }, {
12825 type: "kern",
12826 size: sub.kern
12827 }, {
12828 type: "elem",
12829 elem: base
12830 }, {
12831 type: "kern",
12832 size: sup.kern
12833 }, {
12834 type: "elem",
12835 elem: sup.elem,
12836 marginLeft: makeEm(slant)
12837 }, {
12838 type: "kern",
12839 size: options.fontMetrics().bigOpSpacing5
12840 }]
12841 }, options);
12842 } else if (sub) {
12843 var top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note
12844 // that we are supposed to shift the limits by 1/2 of the slant,
12845 // but since we are centering the limits adding a full slant of
12846 // margin will shift by 1/2 that.
12847
12848 finalGroup = buildCommon.makeVList({
12849 positionType: "top",
12850 positionData: top,
12851 children: [{
12852 type: "kern",
12853 size: options.fontMetrics().bigOpSpacing5
12854 }, {
12855 type: "elem",
12856 elem: sub.elem,
12857 marginLeft: makeEm(-slant)
12858 }, {
12859 type: "kern",
12860 size: sub.kern
12861 }, {
12862 type: "elem",
12863 elem: base
12864 }]
12865 }, options);
12866 } else if (sup) {
12867 var _bottom = base.depth + baseShift;
12868
12869 finalGroup = buildCommon.makeVList({
12870 positionType: "bottom",
12871 positionData: _bottom,
12872 children: [{
12873 type: "elem",
12874 elem: base
12875 }, {
12876 type: "kern",
12877 size: sup.kern
12878 }, {
12879 type: "elem",
12880 elem: sup.elem,
12881 marginLeft: makeEm(slant)
12882 }, {
12883 type: "kern",
12884 size: options.fontMetrics().bigOpSpacing5
12885 }]
12886 }, options);
12887 } else {
12888 // This case probably shouldn't occur (this would mean the
12889 // supsub was sending us a group with no superscript or
12890 // subscript) but be safe.
12891 return base;
12892 }
12893
12894 var parts = [finalGroup];
12895
12896 if (sub && slant !== 0 && !subIsSingleCharacter) {
12897 // A negative margin-left was applied to the lower limit.
12898 // Avoid an overlap by placing a spacer on the left on the group.
12899 var spacer = buildCommon.makeSpan(["mspace"], [], options);
12900 spacer.style.marginRight = makeEm(slant);
12901 parts.unshift(spacer);
12902 }
12903
12904 return buildCommon.makeSpan(["mop", "op-limits"], parts, options);
12905};
12906
12907// Limits, symbols
12908// Most operators have a large successor symbol, but these don't.
12909var noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
12910// "supsub" since some of them (like \int) can affect super/subscripting.
12911
12912var htmlBuilder$2 = (grp, options) => {
12913 // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
12914 var supGroup;
12915 var subGroup;
12916 var hasLimits = false;
12917 var group;
12918
12919 if (grp.type === "supsub") {
12920 // If we have limits, supsub will pass us its group to handle. Pull
12921 // out the superscript and subscript and set the group to the op in
12922 // its base.
12923 supGroup = grp.sup;
12924 subGroup = grp.sub;
12925 group = assertNodeType(grp.base, "op");
12926 hasLimits = true;
12927 } else {
12928 group = assertNodeType(grp, "op");
12929 }
12930
12931 var style = options.style;
12932 var large = false;
12933
12934 if (style.size === Style$1.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) {
12935 // Most symbol operators get larger in displaystyle (rule 13)
12936 large = true;
12937 }
12938
12939 var base;
12940
12941 if (group.symbol) {
12942 // If this is a symbol, create the symbol.
12943 var fontName = large ? "Size2-Regular" : "Size1-Regular";
12944 var stash = "";
12945
12946 if (group.name === "\\oiint" || group.name === "\\oiiint") {
12947 // No font glyphs yet, so use a glyph w/o the oval.
12948 // TODO: When font glyphs are available, delete this code.
12949 stash = group.name.substr(1);
12950 group.name = stash === "oiint" ? "\\iint" : "\\iiint";
12951 }
12952
12953 base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
12954
12955 if (stash.length > 0) {
12956 // We're in \oiint or \oiiint. Overlay the oval.
12957 // TODO: When font glyphs are available, delete this code.
12958 var italic = base.italic;
12959 var oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options);
12960 base = buildCommon.makeVList({
12961 positionType: "individualShift",
12962 children: [{
12963 type: "elem",
12964 elem: base,
12965 shift: 0
12966 }, {
12967 type: "elem",
12968 elem: oval,
12969 shift: large ? 0.08 : 0
12970 }]
12971 }, options);
12972 group.name = "\\" + stash;
12973 base.classes.unshift("mop"); // $FlowFixMe
12974
12975 base.italic = italic;
12976 }
12977 } else if (group.body) {
12978 // If this is a list, compose that list.
12979 var inner = buildExpression$1(group.body, options, true);
12980
12981 if (inner.length === 1 && inner[0] instanceof SymbolNode) {
12982 base = inner[0];
12983 base.classes[0] = "mop"; // replace old mclass
12984 } else {
12985 base = buildCommon.makeSpan(["mop"], inner, options);
12986 }
12987 } else {
12988 // Otherwise, this is a text operator. Build the text from the
12989 // operator's name.
12990 var output = [];
12991
12992 for (var i = 1; i < group.name.length; i++) {
12993 output.push(buildCommon.mathsym(group.name[i], group.mode, options));
12994 }
12995
12996 base = buildCommon.makeSpan(["mop"], output, options);
12997 } // If content of op is a single symbol, shift it vertically.
12998
12999
13000 var baseShift = 0;
13001 var slant = 0;
13002
13003 if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
13004 // We suppress the shift of the base of \overset and \underset. Otherwise,
13005 // shift the symbol so its center lies on the axis (rule 13). It
13006 // appears that our fonts have the centers of the symbols already
13007 // almost on the axis, so these numbers are very small. Note we
13008 // don't actually apply this here, but instead it is used either in
13009 // the vlist creation or separately when there are no limits.
13010 baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction.
13011 // $FlowFixMe
13012
13013 slant = base.italic;
13014 }
13015
13016 if (hasLimits) {
13017 return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
13018 } else {
13019 if (baseShift) {
13020 base.style.position = "relative";
13021 base.style.top = makeEm(baseShift);
13022 }
13023
13024 return base;
13025 }
13026};
13027
13028var mathmlBuilder$1 = (group, options) => {
13029 var node;
13030
13031 if (group.symbol) {
13032 // This is a symbol. Just add the symbol.
13033 node = new MathNode("mo", [makeText(group.name, group.mode)]);
13034
13035 if (utils.contains(noSuccessor, group.name)) {
13036 node.setAttribute("largeop", "false");
13037 }
13038 } else if (group.body) {
13039 // This is an operator with children. Add them.
13040 node = new MathNode("mo", buildExpression(group.body, options));
13041 } else {
13042 // This is a text operator. Add all of the characters from the
13043 // operator's name.
13044 node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an <mo>⁡</mo>.
13045 // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
13046
13047 var operator = new MathNode("mo", [makeText("\u2061", "text")]);
13048
13049 if (group.parentIsSupSub) {
13050 node = new MathNode("mrow", [node, operator]);
13051 } else {
13052 node = newDocumentFragment([node, operator]);
13053 }
13054 }
13055
13056 return node;
13057};
13058
13059var singleCharBigOps = {
13060 "\u220F": "\\prod",
13061 "\u2210": "\\coprod",
13062 "\u2211": "\\sum",
13063 "\u22c0": "\\bigwedge",
13064 "\u22c1": "\\bigvee",
13065 "\u22c2": "\\bigcap",
13066 "\u22c3": "\\bigcup",
13067 "\u2a00": "\\bigodot",
13068 "\u2a01": "\\bigoplus",
13069 "\u2a02": "\\bigotimes",
13070 "\u2a04": "\\biguplus",
13071 "\u2a06": "\\bigsqcup"
13072};
13073defineFunction({
13074 type: "op",
13075 names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"],
13076 props: {
13077 numArgs: 0
13078 },
13079 handler: (_ref, args) => {
13080 var {
13081 parser,
13082 funcName
13083 } = _ref;
13084 var fName = funcName;
13085
13086 if (fName.length === 1) {
13087 fName = singleCharBigOps[fName];
13088 }
13089
13090 return {
13091 type: "op",
13092 mode: parser.mode,
13093 limits: true,
13094 parentIsSupSub: false,
13095 symbol: true,
13096 name: fName
13097 };
13098 },
13099 htmlBuilder: htmlBuilder$2,
13100 mathmlBuilder: mathmlBuilder$1
13101}); // Note: calling defineFunction with a type that's already been defined only
13102// works because the same htmlBuilder and mathmlBuilder are being used.
13103
13104defineFunction({
13105 type: "op",
13106 names: ["\\mathop"],
13107 props: {
13108 numArgs: 1,
13109 primitive: true
13110 },
13111 handler: (_ref2, args) => {
13112 var {
13113 parser
13114 } = _ref2;
13115 var body = args[0];
13116 return {
13117 type: "op",
13118 mode: parser.mode,
13119 limits: false,
13120 parentIsSupSub: false,
13121 symbol: false,
13122 body: ordargument(body)
13123 };
13124 },
13125 htmlBuilder: htmlBuilder$2,
13126 mathmlBuilder: mathmlBuilder$1
13127}); // There are 2 flags for operators; whether they produce limits in
13128// displaystyle, and whether they are symbols and should grow in
13129// displaystyle. These four groups cover the four possible choices.
13130
13131var singleCharIntegrals = {
13132 "\u222b": "\\int",
13133 "\u222c": "\\iint",
13134 "\u222d": "\\iiint",
13135 "\u222e": "\\oint",
13136 "\u222f": "\\oiint",
13137 "\u2230": "\\oiiint"
13138}; // No limits, not symbols
13139
13140defineFunction({
13141 type: "op",
13142 names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"],
13143 props: {
13144 numArgs: 0
13145 },
13146
13147 handler(_ref3) {
13148 var {
13149 parser,
13150 funcName
13151 } = _ref3;
13152 return {
13153 type: "op",
13154 mode: parser.mode,
13155 limits: false,
13156 parentIsSupSub: false,
13157 symbol: false,
13158 name: funcName
13159 };
13160 },
13161
13162 htmlBuilder: htmlBuilder$2,
13163 mathmlBuilder: mathmlBuilder$1
13164}); // Limits, not symbols
13165
13166defineFunction({
13167 type: "op",
13168 names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"],
13169 props: {
13170 numArgs: 0
13171 },
13172
13173 handler(_ref4) {
13174 var {
13175 parser,
13176 funcName
13177 } = _ref4;
13178 return {
13179 type: "op",
13180 mode: parser.mode,
13181 limits: true,
13182 parentIsSupSub: false,
13183 symbol: false,
13184 name: funcName
13185 };
13186 },
13187
13188 htmlBuilder: htmlBuilder$2,
13189 mathmlBuilder: mathmlBuilder$1
13190}); // No limits, symbols
13191
13192defineFunction({
13193 type: "op",
13194 names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"],
13195 props: {
13196 numArgs: 0
13197 },
13198
13199 handler(_ref5) {
13200 var {
13201 parser,
13202 funcName
13203 } = _ref5;
13204 var fName = funcName;
13205
13206 if (fName.length === 1) {
13207 fName = singleCharIntegrals[fName];
13208 }
13209
13210 return {
13211 type: "op",
13212 mode: parser.mode,
13213 limits: false,
13214 parentIsSupSub: false,
13215 symbol: true,
13216 name: fName
13217 };
13218 },
13219
13220 htmlBuilder: htmlBuilder$2,
13221 mathmlBuilder: mathmlBuilder$1
13222});
13223
13224// NOTE: Unlike most `htmlBuilder`s, this one handles not only
13225// "operatorname", but also "supsub" since \operatorname* can
13226// affect super/subscripting.
13227var htmlBuilder$1 = (grp, options) => {
13228 // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
13229 var supGroup;
13230 var subGroup;
13231 var hasLimits = false;
13232 var group;
13233
13234 if (grp.type === "supsub") {
13235 // If we have limits, supsub will pass us its group to handle. Pull
13236 // out the superscript and subscript and set the group to the op in
13237 // its base.
13238 supGroup = grp.sup;
13239 subGroup = grp.sub;
13240 group = assertNodeType(grp.base, "operatorname");
13241 hasLimits = true;
13242 } else {
13243 group = assertNodeType(grp, "operatorname");
13244 }
13245
13246 var base;
13247
13248 if (group.body.length > 0) {
13249 var body = group.body.map(child => {
13250 // $FlowFixMe: Check if the node has a string `text` property.
13251 var childText = child.text;
13252
13253 if (typeof childText === "string") {
13254 return {
13255 type: "textord",
13256 mode: child.mode,
13257 text: childText
13258 };
13259 } else {
13260 return child;
13261 }
13262 }); // Consolidate function names into symbol characters.
13263
13264 var expression = buildExpression$1(body, options.withFont("mathrm"), true);
13265
13266 for (var i = 0; i < expression.length; i++) {
13267 var child = expression[i];
13268
13269 if (child instanceof SymbolNode) {
13270 // Per amsopn package,
13271 // change minus to hyphen and \ast to asterisk
13272 child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
13273 }
13274 }
13275
13276 base = buildCommon.makeSpan(["mop"], expression, options);
13277 } else {
13278 base = buildCommon.makeSpan(["mop"], [], options);
13279 }
13280
13281 if (hasLimits) {
13282 return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0);
13283 } else {
13284 return base;
13285 }
13286};
13287
13288var mathmlBuilder = (group, options) => {
13289 // The steps taken here are similar to the html version.
13290 var expression = buildExpression(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction?
13291
13292 var isAllString = true; // default
13293
13294 for (var i = 0; i < expression.length; i++) {
13295 var node = expression[i];
13296
13297 if (node instanceof mathMLTree.SpaceNode) ; else if (node instanceof mathMLTree.MathNode) {
13298 switch (node.type) {
13299 case "mi":
13300 case "mn":
13301 case "ms":
13302 case "mspace":
13303 case "mtext":
13304 break;
13305 // Do nothing yet.
13306
13307 case "mo":
13308 {
13309 var child = node.children[0];
13310
13311 if (node.children.length === 1 && child instanceof mathMLTree.TextNode) {
13312 child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
13313 } else {
13314 isAllString = false;
13315 }
13316
13317 break;
13318 }
13319
13320 default:
13321 isAllString = false;
13322 }
13323 } else {
13324 isAllString = false;
13325 }
13326 }
13327
13328 if (isAllString) {
13329 // Write a single TextNode instead of multiple nested tags.
13330 var word = expression.map(node => node.toText()).join("");
13331 expression = [new mathMLTree.TextNode(word)];
13332 }
13333
13334 var identifier = new mathMLTree.MathNode("mi", expression);
13335 identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as ⁡
13336 // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
13337
13338 var operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]);
13339
13340 if (group.parentIsSupSub) {
13341 return new mathMLTree.MathNode("mrow", [identifier, operator]);
13342 } else {
13343 return mathMLTree.newDocumentFragment([identifier, operator]);
13344 }
13345}; // \operatorname
13346// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
13347
13348
13349defineFunction({
13350 type: "operatorname",
13351 names: ["\\operatorname@", "\\operatornamewithlimits"],
13352 props: {
13353 numArgs: 1
13354 },
13355 handler: (_ref, args) => {
13356 var {
13357 parser,
13358 funcName
13359 } = _ref;
13360 var body = args[0];
13361 return {
13362 type: "operatorname",
13363 mode: parser.mode,
13364 body: ordargument(body),
13365 alwaysHandleSupSub: funcName === "\\operatornamewithlimits",
13366 limits: false,
13367 parentIsSupSub: false
13368 };
13369 },
13370 htmlBuilder: htmlBuilder$1,
13371 mathmlBuilder
13372});
13373defineMacro("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@");
13374
13375defineFunctionBuilders({
13376 type: "ordgroup",
13377
13378 htmlBuilder(group, options) {
13379 if (group.semisimple) {
13380 return buildCommon.makeFragment(buildExpression$1(group.body, options, false));
13381 }
13382
13383 return buildCommon.makeSpan(["mord"], buildExpression$1(group.body, options, true), options);
13384 },
13385
13386 mathmlBuilder(group, options) {
13387 return buildExpressionRow(group.body, options, true);
13388 }
13389
13390});
13391
13392defineFunction({
13393 type: "overline",
13394 names: ["\\overline"],
13395 props: {
13396 numArgs: 1
13397 },
13398
13399 handler(_ref, args) {
13400 var {
13401 parser
13402 } = _ref;
13403 var body = args[0];
13404 return {
13405 type: "overline",
13406 mode: parser.mode,
13407 body
13408 };
13409 },
13410
13411 htmlBuilder(group, options) {
13412 // Overlines are handled in the TeXbook pg 443, Rule 9.
13413 // Build the inner group in the cramped style.
13414 var innerGroup = buildGroup$1(group.body, options.havingCrampedStyle()); // Create the line above the body
13415
13416 var line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns
13417
13418 var defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
13419 var vlist = buildCommon.makeVList({
13420 positionType: "firstBaseline",
13421 children: [{
13422 type: "elem",
13423 elem: innerGroup
13424 }, {
13425 type: "kern",
13426 size: 3 * defaultRuleThickness
13427 }, {
13428 type: "elem",
13429 elem: line
13430 }, {
13431 type: "kern",
13432 size: defaultRuleThickness
13433 }]
13434 }, options);
13435 return buildCommon.makeSpan(["mord", "overline"], [vlist], options);
13436 },
13437
13438 mathmlBuilder(group, options) {
13439 var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
13440 operator.setAttribute("stretchy", "true");
13441 var node = new mathMLTree.MathNode("mover", [buildGroup(group.body, options), operator]);
13442 node.setAttribute("accent", "true");
13443 return node;
13444 }
13445
13446});
13447
13448defineFunction({
13449 type: "phantom",
13450 names: ["\\phantom"],
13451 props: {
13452 numArgs: 1,
13453 allowedInText: true
13454 },
13455 handler: (_ref, args) => {
13456 var {
13457 parser
13458 } = _ref;
13459 var body = args[0];
13460 return {
13461 type: "phantom",
13462 mode: parser.mode,
13463 body: ordargument(body)
13464 };
13465 },
13466 htmlBuilder: (group, options) => {
13467 var elements = buildExpression$1(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains.
13468 // See "color" for more details.
13469
13470 return buildCommon.makeFragment(elements);
13471 },
13472 mathmlBuilder: (group, options) => {
13473 var inner = buildExpression(group.body, options);
13474 return new mathMLTree.MathNode("mphantom", inner);
13475 }
13476});
13477defineFunction({
13478 type: "hphantom",
13479 names: ["\\hphantom"],
13480 props: {
13481 numArgs: 1,
13482 allowedInText: true
13483 },
13484 handler: (_ref2, args) => {
13485 var {
13486 parser
13487 } = _ref2;
13488 var body = args[0];
13489 return {
13490 type: "hphantom",
13491 mode: parser.mode,
13492 body
13493 };
13494 },
13495 htmlBuilder: (group, options) => {
13496 var node = buildCommon.makeSpan([], [buildGroup$1(group.body, options.withPhantom())]);
13497 node.height = 0;
13498 node.depth = 0;
13499
13500 if (node.children) {
13501 for (var i = 0; i < node.children.length; i++) {
13502 node.children[i].height = 0;
13503 node.children[i].depth = 0;
13504 }
13505 } // See smash for comment re: use of makeVList
13506
13507
13508 node = buildCommon.makeVList({
13509 positionType: "firstBaseline",
13510 children: [{
13511 type: "elem",
13512 elem: node
13513 }]
13514 }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord).
13515
13516 return buildCommon.makeSpan(["mord"], [node], options);
13517 },
13518 mathmlBuilder: (group, options) => {
13519 var inner = buildExpression(ordargument(group.body), options);
13520 var phantom = new mathMLTree.MathNode("mphantom", inner);
13521 var node = new mathMLTree.MathNode("mpadded", [phantom]);
13522 node.setAttribute("height", "0px");
13523 node.setAttribute("depth", "0px");
13524 return node;
13525 }
13526});
13527defineFunction({
13528 type: "vphantom",
13529 names: ["\\vphantom"],
13530 props: {
13531 numArgs: 1,
13532 allowedInText: true
13533 },
13534 handler: (_ref3, args) => {
13535 var {
13536 parser
13537 } = _ref3;
13538 var body = args[0];
13539 return {
13540 type: "vphantom",
13541 mode: parser.mode,
13542 body
13543 };
13544 },
13545 htmlBuilder: (group, options) => {
13546 var inner = buildCommon.makeSpan(["inner"], [buildGroup$1(group.body, options.withPhantom())]);
13547 var fix = buildCommon.makeSpan(["fix"], []);
13548 return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options);
13549 },
13550 mathmlBuilder: (group, options) => {
13551 var inner = buildExpression(ordargument(group.body), options);
13552 var phantom = new mathMLTree.MathNode("mphantom", inner);
13553 var node = new mathMLTree.MathNode("mpadded", [phantom]);
13554 node.setAttribute("width", "0px");
13555 return node;
13556 }
13557});
13558
13559defineFunction({
13560 type: "raisebox",
13561 names: ["\\raisebox"],
13562 props: {
13563 numArgs: 2,
13564 argTypes: ["size", "hbox"],
13565 allowedInText: true
13566 },
13567
13568 handler(_ref, args) {
13569 var {
13570 parser
13571 } = _ref;
13572 var amount = assertNodeType(args[0], "size").value;
13573 var body = args[1];
13574 return {
13575 type: "raisebox",
13576 mode: parser.mode,
13577 dy: amount,
13578 body
13579 };
13580 },
13581
13582 htmlBuilder(group, options) {
13583 var body = buildGroup$1(group.body, options);
13584 var dy = calculateSize(group.dy, options);
13585 return buildCommon.makeVList({
13586 positionType: "shift",
13587 positionData: -dy,
13588 children: [{
13589 type: "elem",
13590 elem: body
13591 }]
13592 }, options);
13593 },
13594
13595 mathmlBuilder(group, options) {
13596 var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]);
13597 var dy = group.dy.number + group.dy.unit;
13598 node.setAttribute("voffset", dy);
13599 return node;
13600 }
13601
13602});
13603
13604defineFunction({
13605 type: "internal",
13606 names: ["\\relax"],
13607 props: {
13608 numArgs: 0,
13609 allowedInText: true
13610 },
13611
13612 handler(_ref) {
13613 var {
13614 parser
13615 } = _ref;
13616 return {
13617 type: "internal",
13618 mode: parser.mode
13619 };
13620 }
13621
13622});
13623
13624defineFunction({
13625 type: "rule",
13626 names: ["\\rule"],
13627 props: {
13628 numArgs: 2,
13629 numOptionalArgs: 1,
13630 argTypes: ["size", "size", "size"]
13631 },
13632
13633 handler(_ref, args, optArgs) {
13634 var {
13635 parser
13636 } = _ref;
13637 var shift = optArgs[0];
13638 var width = assertNodeType(args[0], "size");
13639 var height = assertNodeType(args[1], "size");
13640 return {
13641 type: "rule",
13642 mode: parser.mode,
13643 shift: shift && assertNodeType(shift, "size").value,
13644 width: width.value,
13645 height: height.value
13646 };
13647 },
13648
13649 htmlBuilder(group, options) {
13650 // Make an empty span for the rule
13651 var rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units
13652
13653 var width = calculateSize(group.width, options);
13654 var height = calculateSize(group.height, options);
13655 var shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size
13656
13657 rule.style.borderRightWidth = makeEm(width);
13658 rule.style.borderTopWidth = makeEm(height);
13659 rule.style.bottom = makeEm(shift); // Record the height and width
13660
13661 rule.width = width;
13662 rule.height = height + shift;
13663 rule.depth = -shift; // Font size is the number large enough that the browser will
13664 // reserve at least `absHeight` space above the baseline.
13665 // The 1.125 factor was empirically determined
13666
13667 rule.maxFontSize = height * 1.125 * options.sizeMultiplier;
13668 return rule;
13669 },
13670
13671 mathmlBuilder(group, options) {
13672 var width = calculateSize(group.width, options);
13673 var height = calculateSize(group.height, options);
13674 var shift = group.shift ? calculateSize(group.shift, options) : 0;
13675 var color = options.color && options.getColor() || "black";
13676 var rule = new mathMLTree.MathNode("mspace");
13677 rule.setAttribute("mathbackground", color);
13678 rule.setAttribute("width", makeEm(width));
13679 rule.setAttribute("height", makeEm(height));
13680 var wrapper = new mathMLTree.MathNode("mpadded", [rule]);
13681
13682 if (shift >= 0) {
13683 wrapper.setAttribute("height", makeEm(shift));
13684 } else {
13685 wrapper.setAttribute("height", makeEm(shift));
13686 wrapper.setAttribute("depth", makeEm(-shift));
13687 }
13688
13689 wrapper.setAttribute("voffset", makeEm(shift));
13690 return wrapper;
13691 }
13692
13693});
13694
13695function sizingGroup(value, options, baseOptions) {
13696 var inner = buildExpression$1(value, options, false);
13697 var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize
13698 // manually. Handle nested size changes.
13699
13700 for (var i = 0; i < inner.length; i++) {
13701 var pos = inner[i].classes.indexOf("sizing");
13702
13703 if (pos < 0) {
13704 Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions));
13705 } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
13706 // This is a nested size change: e.g., inner[i] is the "b" in
13707 // `\Huge a \small b`. Override the old size (the `reset-` class)
13708 // but not the new size.
13709 inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
13710 }
13711
13712 inner[i].height *= multiplier;
13713 inner[i].depth *= multiplier;
13714 }
13715
13716 return buildCommon.makeFragment(inner);
13717}
13718var sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"];
13719var htmlBuilder = (group, options) => {
13720 // Handle sizing operators like \Huge. Real TeX doesn't actually allow
13721 // these functions inside of math expressions, so we do some special
13722 // handling.
13723 var newOptions = options.havingSize(group.size);
13724 return sizingGroup(group.body, newOptions, options);
13725};
13726defineFunction({
13727 type: "sizing",
13728 names: sizeFuncs,
13729 props: {
13730 numArgs: 0,
13731 allowedInText: true
13732 },
13733 handler: (_ref, args) => {
13734 var {
13735 breakOnTokenText,
13736 funcName,
13737 parser
13738 } = _ref;
13739 var body = parser.parseExpression(false, breakOnTokenText);
13740 return {
13741 type: "sizing",
13742 mode: parser.mode,
13743 // Figure out what size to use based on the list of functions above
13744 size: sizeFuncs.indexOf(funcName) + 1,
13745 body
13746 };
13747 },
13748 htmlBuilder,
13749 mathmlBuilder: (group, options) => {
13750 var newOptions = options.havingSize(group.size);
13751 var inner = buildExpression(group.body, newOptions);
13752 var node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size
13753 // changes, because we don't keep state of what style we're currently
13754 // in, so we can't reset the size to normal before changing it. Now
13755 // that we're passing an options parameter we should be able to fix
13756 // this.
13757
13758 node.setAttribute("mathsize", makeEm(newOptions.sizeMultiplier));
13759 return node;
13760 }
13761});
13762
13763// smash, with optional [tb], as in AMS
13764defineFunction({
13765 type: "smash",
13766 names: ["\\smash"],
13767 props: {
13768 numArgs: 1,
13769 numOptionalArgs: 1,
13770 allowedInText: true
13771 },
13772 handler: (_ref, args, optArgs) => {
13773 var {
13774 parser
13775 } = _ref;
13776 var smashHeight = false;
13777 var smashDepth = false;
13778 var tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup");
13779
13780 if (tbArg) {
13781 // Optional [tb] argument is engaged.
13782 // ref: amsmath: \renewcommand{\smash}[1][tb]{%
13783 // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
13784 var letter = "";
13785
13786 for (var i = 0; i < tbArg.body.length; ++i) {
13787 var node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property.
13788
13789 letter = node.text;
13790
13791 if (letter === "t") {
13792 smashHeight = true;
13793 } else if (letter === "b") {
13794 smashDepth = true;
13795 } else {
13796 smashHeight = false;
13797 smashDepth = false;
13798 break;
13799 }
13800 }
13801 } else {
13802 smashHeight = true;
13803 smashDepth = true;
13804 }
13805
13806 var body = args[0];
13807 return {
13808 type: "smash",
13809 mode: parser.mode,
13810 body,
13811 smashHeight,
13812 smashDepth
13813 };
13814 },
13815 htmlBuilder: (group, options) => {
13816 var node = buildCommon.makeSpan([], [buildGroup$1(group.body, options)]);
13817
13818 if (!group.smashHeight && !group.smashDepth) {
13819 return node;
13820 }
13821
13822 if (group.smashHeight) {
13823 node.height = 0; // In order to influence makeVList, we have to reset the children.
13824
13825 if (node.children) {
13826 for (var i = 0; i < node.children.length; i++) {
13827 node.children[i].height = 0;
13828 }
13829 }
13830 }
13831
13832 if (group.smashDepth) {
13833 node.depth = 0;
13834
13835 if (node.children) {
13836 for (var _i = 0; _i < node.children.length; _i++) {
13837 node.children[_i].depth = 0;
13838 }
13839 }
13840 } // At this point, we've reset the TeX-like height and depth values.
13841 // But the span still has an HTML line height.
13842 // makeVList applies "display: table-cell", which prevents the browser
13843 // from acting on that line height. So we'll call makeVList now.
13844
13845
13846 var smashedNode = buildCommon.makeVList({
13847 positionType: "firstBaseline",
13848 children: [{
13849 type: "elem",
13850 elem: node
13851 }]
13852 }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord).
13853
13854 return buildCommon.makeSpan(["mord"], [smashedNode], options);
13855 },
13856 mathmlBuilder: (group, options) => {
13857 var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]);
13858
13859 if (group.smashHeight) {
13860 node.setAttribute("height", "0px");
13861 }
13862
13863 if (group.smashDepth) {
13864 node.setAttribute("depth", "0px");
13865 }
13866
13867 return node;
13868 }
13869});
13870
13871defineFunction({
13872 type: "sqrt",
13873 names: ["\\sqrt"],
13874 props: {
13875 numArgs: 1,
13876 numOptionalArgs: 1
13877 },
13878
13879 handler(_ref, args, optArgs) {
13880 var {
13881 parser
13882 } = _ref;
13883 var index = optArgs[0];
13884 var body = args[0];
13885 return {
13886 type: "sqrt",
13887 mode: parser.mode,
13888 body,
13889 index
13890 };
13891 },
13892
13893 htmlBuilder(group, options) {
13894 // Square roots are handled in the TeXbook pg. 443, Rule 11.
13895 // First, we do the same steps as in overline to build the inner group
13896 // and line
13897 var inner = buildGroup$1(group.body, options.havingCrampedStyle());
13898
13899 if (inner.height === 0) {
13900 // Render a small surd.
13901 inner.height = options.fontMetrics().xHeight;
13902 } // Some groups can return document fragments. Handle those by wrapping
13903 // them in a span.
13904
13905
13906 inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter
13907
13908 var metrics = options.fontMetrics();
13909 var theta = metrics.defaultRuleThickness;
13910 var phi = theta;
13911
13912 if (options.style.id < Style$1.TEXT.id) {
13913 phi = options.fontMetrics().xHeight;
13914 } // Calculate the clearance between the body and line
13915
13916
13917 var lineClearance = theta + phi / 4;
13918 var minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size
13919
13920 var {
13921 span: img,
13922 ruleWidth,
13923 advanceWidth
13924 } = delimiter.sqrtImage(minDelimiterHeight, options);
13925 var delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size
13926
13927 if (delimDepth > inner.height + inner.depth + lineClearance) {
13928 lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2;
13929 } // Shift the sqrt image
13930
13931
13932 var imgShift = img.height - inner.height - lineClearance - ruleWidth;
13933 inner.style.paddingLeft = makeEm(advanceWidth); // Overlay the image and the argument.
13934
13935 var body = buildCommon.makeVList({
13936 positionType: "firstBaseline",
13937 children: [{
13938 type: "elem",
13939 elem: inner,
13940 wrapperClasses: ["svg-align"]
13941 }, {
13942 type: "kern",
13943 size: -(inner.height + imgShift)
13944 }, {
13945 type: "elem",
13946 elem: img
13947 }, {
13948 type: "kern",
13949 size: ruleWidth
13950 }]
13951 }, options);
13952
13953 if (!group.index) {
13954 return buildCommon.makeSpan(["mord", "sqrt"], [body], options);
13955 } else {
13956 // Handle the optional root index
13957 // The index is always in scriptscript style
13958 var newOptions = options.havingStyle(Style$1.SCRIPTSCRIPT);
13959 var rootm = buildGroup$1(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX
13960 // source, in the definition of `\r@@t`.
13961
13962 var toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly
13963
13964 var rootVList = buildCommon.makeVList({
13965 positionType: "shift",
13966 positionData: -toShift,
13967 children: [{
13968 type: "elem",
13969 elem: rootm
13970 }]
13971 }, options); // Add a class surrounding it so we can add on the appropriate
13972 // kerning
13973
13974 var rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]);
13975 return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options);
13976 }
13977 },
13978
13979 mathmlBuilder(group, options) {
13980 var {
13981 body,
13982 index
13983 } = group;
13984 return index ? new mathMLTree.MathNode("mroot", [buildGroup(body, options), buildGroup(index, options)]) : new mathMLTree.MathNode("msqrt", [buildGroup(body, options)]);
13985 }
13986
13987});
13988
13989var styleMap = {
13990 "display": Style$1.DISPLAY,
13991 "text": Style$1.TEXT,
13992 "script": Style$1.SCRIPT,
13993 "scriptscript": Style$1.SCRIPTSCRIPT
13994};
13995defineFunction({
13996 type: "styling",
13997 names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
13998 props: {
13999 numArgs: 0,
14000 allowedInText: true,
14001 primitive: true
14002 },
14003
14004 handler(_ref, args) {
14005 var {
14006 breakOnTokenText,
14007 funcName,
14008 parser
14009 } = _ref;
14010 // parse out the implicit body
14011 var body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
14012 // here and in buildHTML and de-dupe the enumeration of all the styles).
14013 // $FlowFixMe: The names above exactly match the styles.
14014
14015 var style = funcName.slice(1, funcName.length - 5);
14016 return {
14017 type: "styling",
14018 mode: parser.mode,
14019 // Figure out what style to use by pulling out the style from
14020 // the function name
14021 style,
14022 body
14023 };
14024 },
14025
14026 htmlBuilder(group, options) {
14027 // Style changes are handled in the TeXbook on pg. 442, Rule 3.
14028 var newStyle = styleMap[group.style];
14029 var newOptions = options.havingStyle(newStyle).withFont('');
14030 return sizingGroup(group.body, newOptions, options);
14031 },
14032
14033 mathmlBuilder(group, options) {
14034 // Figure out what style we're changing to.
14035 var newStyle = styleMap[group.style];
14036 var newOptions = options.havingStyle(newStyle);
14037 var inner = buildExpression(group.body, newOptions);
14038 var node = new mathMLTree.MathNode("mstyle", inner);
14039 var styleAttributes = {
14040 "display": ["0", "true"],
14041 "text": ["0", "false"],
14042 "script": ["1", "false"],
14043 "scriptscript": ["2", "false"]
14044 };
14045 var attr = styleAttributes[group.style];
14046 node.setAttribute("scriptlevel", attr[0]);
14047 node.setAttribute("displaystyle", attr[1]);
14048 return node;
14049 }
14050
14051});
14052
14053/**
14054 * Sometimes, groups perform special rules when they have superscripts or
14055 * subscripts attached to them. This function lets the `supsub` group know that
14056 * Sometimes, groups perform special rules when they have superscripts or
14057 * its inner element should handle the superscripts and subscripts instead of
14058 * handling them itself.
14059 */
14060var htmlBuilderDelegate = function htmlBuilderDelegate(group, options) {
14061 var base = group.base;
14062
14063 if (!base) {
14064 return null;
14065 } else if (base.type === "op") {
14066 // Operators handle supsubs differently when they have limits
14067 // (e.g. `\displaystyle\sum_2^3`)
14068 var delegate = base.limits && (options.style.size === Style$1.DISPLAY.size || base.alwaysHandleSupSub);
14069 return delegate ? htmlBuilder$2 : null;
14070 } else if (base.type === "operatorname") {
14071 var _delegate = base.alwaysHandleSupSub && (options.style.size === Style$1.DISPLAY.size || base.limits);
14072
14073 return _delegate ? htmlBuilder$1 : null;
14074 } else if (base.type === "accent") {
14075 return utils.isCharacterBox(base.base) ? htmlBuilder$a : null;
14076 } else if (base.type === "horizBrace") {
14077 var isSup = !group.sub;
14078 return isSup === base.isOver ? htmlBuilder$3 : null;
14079 } else {
14080 return null;
14081 }
14082}; // Super scripts and subscripts, whose precise placement can depend on other
14083// functions that precede them.
14084
14085
14086defineFunctionBuilders({
14087 type: "supsub",
14088
14089 htmlBuilder(group, options) {
14090 // Superscript and subscripts are handled in the TeXbook on page
14091 // 445-446, rules 18(a-f).
14092 // Here is where we defer to the inner group if it should handle
14093 // superscripts and subscripts itself.
14094 var builderDelegate = htmlBuilderDelegate(group, options);
14095
14096 if (builderDelegate) {
14097 return builderDelegate(group, options);
14098 }
14099
14100 var {
14101 base: valueBase,
14102 sup: valueSup,
14103 sub: valueSub
14104 } = group;
14105 var base = buildGroup$1(valueBase, options);
14106 var supm;
14107 var subm;
14108 var metrics = options.fontMetrics(); // Rule 18a
14109
14110 var supShift = 0;
14111 var subShift = 0;
14112 var isCharacterBox = valueBase && utils.isCharacterBox(valueBase);
14113
14114 if (valueSup) {
14115 var newOptions = options.havingStyle(options.style.sup());
14116 supm = buildGroup$1(valueSup, newOptions, options);
14117
14118 if (!isCharacterBox) {
14119 supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
14120 }
14121 }
14122
14123 if (valueSub) {
14124 var _newOptions = options.havingStyle(options.style.sub());
14125
14126 subm = buildGroup$1(valueSub, _newOptions, options);
14127
14128 if (!isCharacterBox) {
14129 subShift = base.depth + _newOptions.fontMetrics().subDrop * _newOptions.sizeMultiplier / options.sizeMultiplier;
14130 }
14131 } // Rule 18c
14132
14133
14134 var minSupShift;
14135
14136 if (options.style === Style$1.DISPLAY) {
14137 minSupShift = metrics.sup1;
14138 } else if (options.style.cramped) {
14139 minSupShift = metrics.sup3;
14140 } else {
14141 minSupShift = metrics.sup2;
14142 } // scriptspace is a font-size-independent size, so scale it
14143 // appropriately for use as the marginRight.
14144
14145
14146 var multiplier = options.sizeMultiplier;
14147 var marginRight = makeEm(0.5 / metrics.ptPerEm / multiplier);
14148 var marginLeft = null;
14149
14150 if (subm) {
14151 // Subscripts shouldn't be shifted by the base's italic correction.
14152 // Account for that by shifting the subscript back the appropriate
14153 // amount. Note we only do this when the base is a single symbol.
14154 var isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
14155
14156 if (base instanceof SymbolNode || isOiint) {
14157 // $FlowFixMe
14158 marginLeft = makeEm(-base.italic);
14159 }
14160 }
14161
14162 var supsub;
14163
14164 if (supm && subm) {
14165 supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
14166 subShift = Math.max(subShift, metrics.sub2);
14167 var ruleWidth = metrics.defaultRuleThickness; // Rule 18e
14168
14169 var maxWidth = 4 * ruleWidth;
14170
14171 if (supShift - supm.depth - (subm.height - subShift) < maxWidth) {
14172 subShift = maxWidth - (supShift - supm.depth) + subm.height;
14173 var psi = 0.8 * metrics.xHeight - (supShift - supm.depth);
14174
14175 if (psi > 0) {
14176 supShift += psi;
14177 subShift -= psi;
14178 }
14179 }
14180
14181 var vlistElem = [{
14182 type: "elem",
14183 elem: subm,
14184 shift: subShift,
14185 marginRight,
14186 marginLeft
14187 }, {
14188 type: "elem",
14189 elem: supm,
14190 shift: -supShift,
14191 marginRight
14192 }];
14193 supsub = buildCommon.makeVList({
14194 positionType: "individualShift",
14195 children: vlistElem
14196 }, options);
14197 } else if (subm) {
14198 // Rule 18b
14199 subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight);
14200 var _vlistElem = [{
14201 type: "elem",
14202 elem: subm,
14203 marginLeft,
14204 marginRight
14205 }];
14206 supsub = buildCommon.makeVList({
14207 positionType: "shift",
14208 positionData: subShift,
14209 children: _vlistElem
14210 }, options);
14211 } else if (supm) {
14212 // Rule 18c, d
14213 supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
14214 supsub = buildCommon.makeVList({
14215 positionType: "shift",
14216 positionData: -supShift,
14217 children: [{
14218 type: "elem",
14219 elem: supm,
14220 marginRight
14221 }]
14222 }, options);
14223 } else {
14224 throw new Error("supsub must have either sup or sub.");
14225 } // Wrap the supsub vlist in a span.msupsub to reset text-align.
14226
14227
14228 var mclass = getTypeOfDomTree(base, "right") || "mord";
14229 return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options);
14230 },
14231
14232 mathmlBuilder(group, options) {
14233 // Is the inner group a relevant horizonal brace?
14234 var isBrace = false;
14235 var isOver;
14236 var isSup;
14237
14238 if (group.base && group.base.type === "horizBrace") {
14239 isSup = !!group.sup;
14240
14241 if (isSup === group.base.isOver) {
14242 isBrace = true;
14243 isOver = group.base.isOver;
14244 }
14245 }
14246
14247 if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) {
14248 group.base.parentIsSupSub = true;
14249 }
14250
14251 var children = [buildGroup(group.base, options)];
14252
14253 if (group.sub) {
14254 children.push(buildGroup(group.sub, options));
14255 }
14256
14257 if (group.sup) {
14258 children.push(buildGroup(group.sup, options));
14259 }
14260
14261 var nodeType;
14262
14263 if (isBrace) {
14264 nodeType = isOver ? "mover" : "munder";
14265 } else if (!group.sub) {
14266 var base = group.base;
14267
14268 if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) {
14269 nodeType = "mover";
14270 } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) {
14271 nodeType = "mover";
14272 } else {
14273 nodeType = "msup";
14274 }
14275 } else if (!group.sup) {
14276 var _base = group.base;
14277
14278 if (_base && _base.type === "op" && _base.limits && (options.style === Style$1.DISPLAY || _base.alwaysHandleSupSub)) {
14279 nodeType = "munder";
14280 } else if (_base && _base.type === "operatorname" && _base.alwaysHandleSupSub && (_base.limits || options.style === Style$1.DISPLAY)) {
14281 nodeType = "munder";
14282 } else {
14283 nodeType = "msub";
14284 }
14285 } else {
14286 var _base2 = group.base;
14287
14288 if (_base2 && _base2.type === "op" && _base2.limits && options.style === Style$1.DISPLAY) {
14289 nodeType = "munderover";
14290 } else if (_base2 && _base2.type === "operatorname" && _base2.alwaysHandleSupSub && (options.style === Style$1.DISPLAY || _base2.limits)) {
14291 nodeType = "munderover";
14292 } else {
14293 nodeType = "msubsup";
14294 }
14295 }
14296
14297 return new mathMLTree.MathNode(nodeType, children);
14298 }
14299
14300});
14301
14302defineFunctionBuilders({
14303 type: "atom",
14304
14305 htmlBuilder(group, options) {
14306 return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]);
14307 },
14308
14309 mathmlBuilder(group, options) {
14310 var node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]);
14311
14312 if (group.family === "bin") {
14313 var variant = getVariant(group, options);
14314
14315 if (variant === "bold-italic") {
14316 node.setAttribute("mathvariant", variant);
14317 }
14318 } else if (group.family === "punct") {
14319 node.setAttribute("separator", "true");
14320 } else if (group.family === "open" || group.family === "close") {
14321 // Delims built here should not stretch vertically.
14322 // See delimsizing.js for stretchy delims.
14323 node.setAttribute("stretchy", "false");
14324 }
14325
14326 return node;
14327 }
14328
14329});
14330
14331// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
14332// src/symbols.js.
14333var defaultVariant = {
14334 "mi": "italic",
14335 "mn": "normal",
14336 "mtext": "normal"
14337};
14338defineFunctionBuilders({
14339 type: "mathord",
14340
14341 htmlBuilder(group, options) {
14342 return buildCommon.makeOrd(group, options, "mathord");
14343 },
14344
14345 mathmlBuilder(group, options) {
14346 var node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]);
14347 var variant = getVariant(group, options) || "italic";
14348
14349 if (variant !== defaultVariant[node.type]) {
14350 node.setAttribute("mathvariant", variant);
14351 }
14352
14353 return node;
14354 }
14355
14356});
14357defineFunctionBuilders({
14358 type: "textord",
14359
14360 htmlBuilder(group, options) {
14361 return buildCommon.makeOrd(group, options, "textord");
14362 },
14363
14364 mathmlBuilder(group, options) {
14365 var text = makeText(group.text, group.mode, options);
14366 var variant = getVariant(group, options) || "normal";
14367 var node;
14368
14369 if (group.mode === 'text') {
14370 node = new mathMLTree.MathNode("mtext", [text]);
14371 } else if (/[0-9]/.test(group.text)) {
14372 node = new mathMLTree.MathNode("mn", [text]);
14373 } else if (group.text === "\\prime") {
14374 node = new mathMLTree.MathNode("mo", [text]);
14375 } else {
14376 node = new mathMLTree.MathNode("mi", [text]);
14377 }
14378
14379 if (variant !== defaultVariant[node.type]) {
14380 node.setAttribute("mathvariant", variant);
14381 }
14382
14383 return node;
14384 }
14385
14386});
14387
14388var cssSpace = {
14389 "\\nobreak": "nobreak",
14390 "\\allowbreak": "allowbreak"
14391}; // A lookup table to determine whether a spacing function/symbol should be
14392// treated like a regular space character. If a symbol or command is a key
14393// in this table, then it should be a regular space character. Furthermore,
14394// the associated value may have a `className` specifying an extra CSS class
14395// to add to the created `span`.
14396
14397var regularSpace = {
14398 " ": {},
14399 "\\ ": {},
14400 "~": {
14401 className: "nobreak"
14402 },
14403 "\\space": {},
14404 "\\nobreakspace": {
14405 className: "nobreak"
14406 }
14407}; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in
14408// src/symbols.js.
14409
14410defineFunctionBuilders({
14411 type: "spacing",
14412
14413 htmlBuilder(group, options) {
14414 if (regularSpace.hasOwnProperty(group.text)) {
14415 var className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these
14416 // things has an entry in the symbols table, so these will be turned
14417 // into appropriate outputs.
14418
14419 if (group.mode === "text") {
14420 var ord = buildCommon.makeOrd(group, options, "textord");
14421 ord.classes.push(className);
14422 return ord;
14423 } else {
14424 return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options);
14425 }
14426 } else if (cssSpace.hasOwnProperty(group.text)) {
14427 // Spaces based on just a CSS class.
14428 return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options);
14429 } else {
14430 throw new ParseError("Unknown type of space \"" + group.text + "\"");
14431 }
14432 },
14433
14434 mathmlBuilder(group, options) {
14435 var node;
14436
14437 if (regularSpace.hasOwnProperty(group.text)) {
14438 node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]);
14439 } else if (cssSpace.hasOwnProperty(group.text)) {
14440 // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored
14441 return new mathMLTree.MathNode("mspace");
14442 } else {
14443 throw new ParseError("Unknown type of space \"" + group.text + "\"");
14444 }
14445
14446 return node;
14447 }
14448
14449});
14450
14451var pad = () => {
14452 var padNode = new mathMLTree.MathNode("mtd", []);
14453 padNode.setAttribute("width", "50%");
14454 return padNode;
14455};
14456
14457defineFunctionBuilders({
14458 type: "tag",
14459
14460 mathmlBuilder(group, options) {
14461 var table = new mathMLTree.MathNode("mtable", [new mathMLTree.MathNode("mtr", [pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.body, options)]), pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.tag, options)])])]);
14462 table.setAttribute("width", "100%");
14463 return table; // TODO: Left-aligned tags.
14464 // Currently, the group and options passed here do not contain
14465 // enough info to set tag alignment. `leqno` is in Settings but it is
14466 // not passed to Options. On the HTML side, leqno is
14467 // set by a CSS class applied in buildTree.js. That would have worked
14468 // in MathML if browsers supported <mlabeledtr>. Since they don't, we
14469 // need to rewrite the way this function is called.
14470 }
14471
14472});
14473
14474var textFontFamilies = {
14475 "\\text": undefined,
14476 "\\textrm": "textrm",
14477 "\\textsf": "textsf",
14478 "\\texttt": "texttt",
14479 "\\textnormal": "textrm"
14480};
14481var textFontWeights = {
14482 "\\textbf": "textbf",
14483 "\\textmd": "textmd"
14484};
14485var textFontShapes = {
14486 "\\textit": "textit",
14487 "\\textup": "textup"
14488};
14489
14490var optionsWithFont = (group, options) => {
14491 var font = group.font; // Checks if the argument is a font family or a font style.
14492
14493 if (!font) {
14494 return options;
14495 } else if (textFontFamilies[font]) {
14496 return options.withTextFontFamily(textFontFamilies[font]);
14497 } else if (textFontWeights[font]) {
14498 return options.withTextFontWeight(textFontWeights[font]);
14499 } else {
14500 return options.withTextFontShape(textFontShapes[font]);
14501 }
14502};
14503
14504defineFunction({
14505 type: "text",
14506 names: [// Font families
14507 "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights
14508 "\\textbf", "\\textmd", // Font Shapes
14509 "\\textit", "\\textup"],
14510 props: {
14511 numArgs: 1,
14512 argTypes: ["text"],
14513 allowedInArgument: true,
14514 allowedInText: true
14515 },
14516
14517 handler(_ref, args) {
14518 var {
14519 parser,
14520 funcName
14521 } = _ref;
14522 var body = args[0];
14523 return {
14524 type: "text",
14525 mode: parser.mode,
14526 body: ordargument(body),
14527 font: funcName
14528 };
14529 },
14530
14531 htmlBuilder(group, options) {
14532 var newOptions = optionsWithFont(group, options);
14533 var inner = buildExpression$1(group.body, newOptions, true);
14534 return buildCommon.makeSpan(["mord", "text"], inner, newOptions);
14535 },
14536
14537 mathmlBuilder(group, options) {
14538 var newOptions = optionsWithFont(group, options);
14539 return buildExpressionRow(group.body, newOptions);
14540 }
14541
14542});
14543
14544defineFunction({
14545 type: "underline",
14546 names: ["\\underline"],
14547 props: {
14548 numArgs: 1,
14549 allowedInText: true
14550 },
14551
14552 handler(_ref, args) {
14553 var {
14554 parser
14555 } = _ref;
14556 return {
14557 type: "underline",
14558 mode: parser.mode,
14559 body: args[0]
14560 };
14561 },
14562
14563 htmlBuilder(group, options) {
14564 // Underlines are handled in the TeXbook pg 443, Rule 10.
14565 // Build the inner group.
14566 var innerGroup = buildGroup$1(group.body, options); // Create the line to go below the body
14567
14568 var line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns
14569
14570 var defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
14571 var vlist = buildCommon.makeVList({
14572 positionType: "top",
14573 positionData: innerGroup.height,
14574 children: [{
14575 type: "kern",
14576 size: defaultRuleThickness
14577 }, {
14578 type: "elem",
14579 elem: line
14580 }, {
14581 type: "kern",
14582 size: 3 * defaultRuleThickness
14583 }, {
14584 type: "elem",
14585 elem: innerGroup
14586 }]
14587 }, options);
14588 return buildCommon.makeSpan(["mord", "underline"], [vlist], options);
14589 },
14590
14591 mathmlBuilder(group, options) {
14592 var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
14593 operator.setAttribute("stretchy", "true");
14594 var node = new mathMLTree.MathNode("munder", [buildGroup(group.body, options), operator]);
14595 node.setAttribute("accentunder", "true");
14596 return node;
14597 }
14598
14599});
14600
14601defineFunction({
14602 type: "vcenter",
14603 names: ["\\vcenter"],
14604 props: {
14605 numArgs: 1,
14606 argTypes: ["original"],
14607 // In LaTeX, \vcenter can act only on a box.
14608 allowedInText: false
14609 },
14610
14611 handler(_ref, args) {
14612 var {
14613 parser
14614 } = _ref;
14615 return {
14616 type: "vcenter",
14617 mode: parser.mode,
14618 body: args[0]
14619 };
14620 },
14621
14622 htmlBuilder(group, options) {
14623 var body = buildGroup$1(group.body, options);
14624 var axisHeight = options.fontMetrics().axisHeight;
14625 var dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight));
14626 return buildCommon.makeVList({
14627 positionType: "shift",
14628 positionData: dy,
14629 children: [{
14630 type: "elem",
14631 elem: body
14632 }]
14633 }, options);
14634 },
14635
14636 mathmlBuilder(group, options) {
14637 // There is no way to do this in MathML.
14638 // Write a class as a breadcrumb in case some post-processor wants
14639 // to perform a vcenter adjustment.
14640 return new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)], ["vcenter"]);
14641 }
14642
14643});
14644
14645defineFunction({
14646 type: "verb",
14647 names: ["\\verb"],
14648 props: {
14649 numArgs: 0,
14650 allowedInText: true
14651 },
14652
14653 handler(context, args, optArgs) {
14654 // \verb and \verb* are dealt with directly in Parser.js.
14655 // If we end up here, it's because of a failure to match the two delimiters
14656 // in the regex in Lexer.js. LaTeX raises the following error when \verb is
14657 // terminated by end of line (or file).
14658 throw new ParseError("\\verb ended by end of line instead of matching delimiter");
14659 },
14660
14661 htmlBuilder(group, options) {
14662 var text = makeVerb(group);
14663 var body = []; // \verb enters text mode and therefore is sized like \textstyle
14664
14665 var newOptions = options.havingStyle(options.style.text());
14666
14667 for (var i = 0; i < text.length; i++) {
14668 var c = text[i];
14669
14670 if (c === '~') {
14671 c = '\\textasciitilde';
14672 }
14673
14674 body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"]));
14675 }
14676
14677 return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions);
14678 },
14679
14680 mathmlBuilder(group, options) {
14681 var text = new mathMLTree.TextNode(makeVerb(group));
14682 var node = new mathMLTree.MathNode("mtext", [text]);
14683 node.setAttribute("mathvariant", "monospace");
14684 return node;
14685 }
14686
14687});
14688/**
14689 * Converts verb group into body string.
14690 *
14691 * \verb* replaces each space with an open box \u2423
14692 * \verb replaces each space with a no-break space \xA0
14693 */
14694
14695var makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0');
14696
14697/** Include this to ensure that all functions are defined. */
14698var functions = _functions;
14699
14700/**
14701 * The Lexer class handles tokenizing the input in various ways. Since our
14702 * parser expects us to be able to backtrack, the lexer allows lexing from any
14703 * given starting point.
14704 *
14705 * Its main exposed function is the `lex` function, which takes a position to
14706 * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
14707 * function.
14708 *
14709 * The various `_innerLex` functions perform the actual lexing of different
14710 * kinds.
14711 */
14712
14713/* The following tokenRegex
14714 * - matches typical whitespace (but not NBSP etc.) using its first group
14715 * - does not match any control character \x00-\x1f except whitespace
14716 * - does not match a bare backslash
14717 * - matches any ASCII character except those just mentioned
14718 * - does not match the BMP private use area \uE000-\uF8FF
14719 * - does not match bare surrogate code units
14720 * - matches any BMP character except for those just described
14721 * - matches any valid Unicode surrogate pair
14722 * - matches a backslash followed by one or more whitespace characters
14723 * - matches a backslash followed by one or more letters then whitespace
14724 * - matches a backslash followed by any BMP character
14725 * Capturing groups:
14726 * [1] regular whitespace
14727 * [2] backslash followed by whitespace
14728 * [3] anything else, which may include:
14729 * [4] left character of \verb*
14730 * [5] left character of \verb
14731 * [6] backslash followed by word, excluding any trailing whitespace
14732 * Just because the Lexer matches something doesn't mean it's valid input:
14733 * If there is no matching function or symbol definition, the Parser will
14734 * still reject the input.
14735 */
14736var spaceRegexString = "[ \r\n\t]";
14737var controlWordRegexString = "\\\\[a-zA-Z@]+";
14738var controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]";
14739var controlWordWhitespaceRegexString = "(" + controlWordRegexString + ")" + spaceRegexString + "*";
14740var controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*";
14741var combiningDiacriticalMarkString = "[\u0300-\u036f]";
14742var combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$");
14743var tokenRegexString = "(" + spaceRegexString + "+)|" + ( // whitespace
14744controlSpaceRegexString + "|") + // \whitespace
14745"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + ( // single codepoint
14746combiningDiacriticalMarkString + "*") + // ...plus accents
14747"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + ( // surrogate pair
14748combiningDiacriticalMarkString + "*") + // ...plus accents
14749"|\\\\verb\\*([^]).*?\\4" + // \verb*
14750"|\\\\verb([^*a-zA-Z]).*?\\5" + ( // \verb unstarred
14751"|" + controlWordWhitespaceRegexString) + ( // \macroName + spaces
14752"|" + controlSymbolRegexString + ")"); // \\, \', etc.
14753
14754/** Main Lexer class */
14755
14756class Lexer {
14757 // Category codes. The lexer only supports comment characters (14) for now.
14758 // MacroExpander additionally distinguishes active (13).
14759 constructor(input, settings) {
14760 this.input = void 0;
14761 this.settings = void 0;
14762 this.tokenRegex = void 0;
14763 this.catcodes = void 0;
14764 // Separate accents from characters
14765 this.input = input;
14766 this.settings = settings;
14767 this.tokenRegex = new RegExp(tokenRegexString, 'g');
14768 this.catcodes = {
14769 "%": 14,
14770 // comment character
14771 "~": 13 // active character
14772
14773 };
14774 }
14775
14776 setCatcode(char, code) {
14777 this.catcodes[char] = code;
14778 }
14779 /**
14780 * This function lexes a single token.
14781 */
14782
14783
14784 lex() {
14785 var input = this.input;
14786 var pos = this.tokenRegex.lastIndex;
14787
14788 if (pos === input.length) {
14789 return new Token("EOF", new SourceLocation(this, pos, pos));
14790 }
14791
14792 var match = this.tokenRegex.exec(input);
14793
14794 if (match === null || match.index !== pos) {
14795 throw new ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1)));
14796 }
14797
14798 var text = match[6] || match[3] || (match[2] ? "\\ " : " ");
14799
14800 if (this.catcodes[text] === 14) {
14801 // comment character
14802 var nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex);
14803
14804 if (nlIndex === -1) {
14805 this.tokenRegex.lastIndex = input.length; // EOF
14806
14807 this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)");
14808 } else {
14809 this.tokenRegex.lastIndex = nlIndex + 1;
14810 }
14811
14812 return this.lex();
14813 }
14814
14815 return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex));
14816 }
14817
14818}
14819
14820/**
14821 * A `Namespace` refers to a space of nameable things like macros or lengths,
14822 * which can be `set` either globally or local to a nested group, using an
14823 * undo stack similar to how TeX implements this functionality.
14824 * Performance-wise, `get` and local `set` take constant time, while global
14825 * `set` takes time proportional to the depth of group nesting.
14826 */
14827class Namespace {
14828 /**
14829 * Both arguments are optional. The first argument is an object of
14830 * built-in mappings which never change. The second argument is an object
14831 * of initial (global-level) mappings, which will constantly change
14832 * according to any global/top-level `set`s done.
14833 */
14834 constructor(builtins, globalMacros) {
14835 if (builtins === void 0) {
14836 builtins = {};
14837 }
14838
14839 if (globalMacros === void 0) {
14840 globalMacros = {};
14841 }
14842
14843 this.current = void 0;
14844 this.builtins = void 0;
14845 this.undefStack = void 0;
14846 this.current = globalMacros;
14847 this.builtins = builtins;
14848 this.undefStack = [];
14849 }
14850 /**
14851 * Start a new nested group, affecting future local `set`s.
14852 */
14853
14854
14855 beginGroup() {
14856 this.undefStack.push({});
14857 }
14858 /**
14859 * End current nested group, restoring values before the group began.
14860 */
14861
14862
14863 endGroup() {
14864 if (this.undefStack.length === 0) {
14865 throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug");
14866 }
14867
14868 var undefs = this.undefStack.pop();
14869
14870 for (var undef in undefs) {
14871 if (undefs.hasOwnProperty(undef)) {
14872 if (undefs[undef] == null) {
14873 delete this.current[undef];
14874 } else {
14875 this.current[undef] = undefs[undef];
14876 }
14877 }
14878 }
14879 }
14880 /**
14881 * Ends all currently nested groups (if any), restoring values before the
14882 * groups began. Useful in case of an error in the middle of parsing.
14883 */
14884
14885
14886 endGroups() {
14887 while (this.undefStack.length > 0) {
14888 this.endGroup();
14889 }
14890 }
14891 /**
14892 * Detect whether `name` has a definition. Equivalent to
14893 * `get(name) != null`.
14894 */
14895
14896
14897 has(name) {
14898 return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name);
14899 }
14900 /**
14901 * Get the current value of a name, or `undefined` if there is no value.
14902 *
14903 * Note: Do not use `if (namespace.get(...))` to detect whether a macro
14904 * is defined, as the definition may be the empty string which evaluates
14905 * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or
14906 * `if (namespace.has(...))`.
14907 */
14908
14909
14910 get(name) {
14911 if (this.current.hasOwnProperty(name)) {
14912 return this.current[name];
14913 } else {
14914 return this.builtins[name];
14915 }
14916 }
14917 /**
14918 * Set the current value of a name, and optionally set it globally too.
14919 * Local set() sets the current value and (when appropriate) adds an undo
14920 * operation to the undo stack. Global set() may change the undo
14921 * operation at every level, so takes time linear in their number.
14922 * A value of undefined means to delete existing definitions.
14923 */
14924
14925
14926 set(name, value, global) {
14927 if (global === void 0) {
14928 global = false;
14929 }
14930
14931 if (global) {
14932 // Global set is equivalent to setting in all groups. Simulate this
14933 // by destroying any undos currently scheduled for this name,
14934 // and adding an undo with the *new* value (in case it later gets
14935 // locally reset within this environment).
14936 for (var i = 0; i < this.undefStack.length; i++) {
14937 delete this.undefStack[i][name];
14938 }
14939
14940 if (this.undefStack.length > 0) {
14941 this.undefStack[this.undefStack.length - 1][name] = value;
14942 }
14943 } else {
14944 // Undo this set at end of this group (possibly to `undefined`),
14945 // unless an undo is already in place, in which case that older
14946 // value is the correct one.
14947 var top = this.undefStack[this.undefStack.length - 1];
14948
14949 if (top && !top.hasOwnProperty(name)) {
14950 top[name] = this.current[name];
14951 }
14952 }
14953
14954 if (value == null) {
14955 delete this.current[name];
14956 } else {
14957 this.current[name] = value;
14958 }
14959 }
14960
14961}
14962
14963/**
14964 * Predefined macros for KaTeX.
14965 * This can be used to define some commands in terms of others.
14966 */
14967var macros = _macros;
14968// macro tools
14969
14970defineMacro("\\noexpand", function (context) {
14971 // The expansion is the token itself; but that token is interpreted
14972 // as if its meaning were ‘\relax’ if it is a control sequence that
14973 // would ordinarily be expanded by TeX’s expansion rules.
14974 var t = context.popToken();
14975
14976 if (context.isExpandable(t.text)) {
14977 t.noexpand = true;
14978 t.treatAsRelax = true;
14979 }
14980
14981 return {
14982 tokens: [t],
14983 numArgs: 0
14984 };
14985});
14986defineMacro("\\expandafter", function (context) {
14987 // TeX first reads the token that comes immediately after \expandafter,
14988 // without expanding it; let’s call this token t. Then TeX reads the
14989 // token that comes after t (and possibly more tokens, if that token
14990 // has an argument), replacing it by its expansion. Finally TeX puts
14991 // t back in front of that expansion.
14992 var t = context.popToken();
14993 context.expandOnce(true); // expand only an expandable token
14994
14995 return {
14996 tokens: [t],
14997 numArgs: 0
14998 };
14999}); // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2
15000// TeX source: \long\def\@firstoftwo#1#2{#1}
15001
15002defineMacro("\\@firstoftwo", function (context) {
15003 var args = context.consumeArgs(2);
15004 return {
15005 tokens: args[0],
15006 numArgs: 0
15007 };
15008}); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1
15009// TeX source: \long\def\@secondoftwo#1#2{#2}
15010
15011defineMacro("\\@secondoftwo", function (context) {
15012 var args = context.consumeArgs(2);
15013 return {
15014 tokens: args[1],
15015 numArgs: 0
15016 };
15017}); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
15018// symbol that isn't a space, consuming any spaces but not consuming the
15019// first nonspace character. If that nonspace character matches #1, then
15020// the macro expands to #2; otherwise, it expands to #3.
15021
15022defineMacro("\\@ifnextchar", function (context) {
15023 var args = context.consumeArgs(3); // symbol, if, else
15024
15025 context.consumeSpaces();
15026 var nextToken = context.future();
15027
15028 if (args[0].length === 1 && args[0][0].text === nextToken.text) {
15029 return {
15030 tokens: args[1],
15031 numArgs: 0
15032 };
15033 } else {
15034 return {
15035 tokens: args[2],
15036 numArgs: 0
15037 };
15038 }
15039}); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol.
15040// If it is `*`, then it consumes the symbol, and the macro expands to #1;
15041// otherwise, the macro expands to #2 (without consuming the symbol).
15042// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
15043
15044defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode
15045
15046defineMacro("\\TextOrMath", function (context) {
15047 var args = context.consumeArgs(2);
15048
15049 if (context.mode === 'text') {
15050 return {
15051 tokens: args[0],
15052 numArgs: 0
15053 };
15054 } else {
15055 return {
15056 tokens: args[1],
15057 numArgs: 0
15058 };
15059 }
15060}); // Lookup table for parsing numbers in base 8 through 16
15061
15062var digitToNumber = {
15063 "0": 0,
15064 "1": 1,
15065 "2": 2,
15066 "3": 3,
15067 "4": 4,
15068 "5": 5,
15069 "6": 6,
15070 "7": 7,
15071 "8": 8,
15072 "9": 9,
15073 "a": 10,
15074 "A": 10,
15075 "b": 11,
15076 "B": 11,
15077 "c": 12,
15078 "C": 12,
15079 "d": 13,
15080 "D": 13,
15081 "e": 14,
15082 "E": 14,
15083 "f": 15,
15084 "F": 15
15085}; // TeX \char makes a literal character (catcode 12) using the following forms:
15086// (see The TeXBook, p. 43)
15087// \char123 -- decimal
15088// \char'123 -- octal
15089// \char"123 -- hex
15090// \char`x -- character that can be written (i.e. isn't active)
15091// \char`\x -- character that cannot be written (e.g. %)
15092// These all refer to characters from the font, so we turn them into special
15093// calls to a function \@char dealt with in the Parser.
15094
15095defineMacro("\\char", function (context) {
15096 var token = context.popToken();
15097 var base;
15098 var number = '';
15099
15100 if (token.text === "'") {
15101 base = 8;
15102 token = context.popToken();
15103 } else if (token.text === '"') {
15104 base = 16;
15105 token = context.popToken();
15106 } else if (token.text === "`") {
15107 token = context.popToken();
15108
15109 if (token.text[0] === "\\") {
15110 number = token.text.charCodeAt(1);
15111 } else if (token.text === "EOF") {
15112 throw new ParseError("\\char` missing argument");
15113 } else {
15114 number = token.text.charCodeAt(0);
15115 }
15116 } else {
15117 base = 10;
15118 }
15119
15120 if (base) {
15121 // Parse a number in the given base, starting with first `token`.
15122 number = digitToNumber[token.text];
15123
15124 if (number == null || number >= base) {
15125 throw new ParseError("Invalid base-" + base + " digit " + token.text);
15126 }
15127
15128 var digit;
15129
15130 while ((digit = digitToNumber[context.future().text]) != null && digit < base) {
15131 number *= base;
15132 number += digit;
15133 context.popToken();
15134 }
15135 }
15136
15137 return "\\@char{" + number + "}";
15138}); // \newcommand{\macro}[args]{definition}
15139// \renewcommand{\macro}[args]{definition}
15140// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
15141
15142var newcommand = (context, existsOK, nonexistsOK) => {
15143 var arg = context.consumeArg().tokens;
15144
15145 if (arg.length !== 1) {
15146 throw new ParseError("\\newcommand's first argument must be a macro name");
15147 }
15148
15149 var name = arg[0].text;
15150 var exists = context.isDefined(name);
15151
15152 if (exists && !existsOK) {
15153 throw new ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand"));
15154 }
15155
15156 if (!exists && !nonexistsOK) {
15157 throw new ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand");
15158 }
15159
15160 var numArgs = 0;
15161 arg = context.consumeArg().tokens;
15162
15163 if (arg.length === 1 && arg[0].text === "[") {
15164 var argText = '';
15165 var token = context.expandNextToken();
15166
15167 while (token.text !== "]" && token.text !== "EOF") {
15168 // TODO: Should properly expand arg, e.g., ignore {}s
15169 argText += token.text;
15170 token = context.expandNextToken();
15171 }
15172
15173 if (!argText.match(/^\s*[0-9]+\s*$/)) {
15174 throw new ParseError("Invalid number of arguments: " + argText);
15175 }
15176
15177 numArgs = parseInt(argText);
15178 arg = context.consumeArg().tokens;
15179 } // Final arg is the expansion of the macro
15180
15181
15182 context.macros.set(name, {
15183 tokens: arg,
15184 numArgs
15185 });
15186 return '';
15187};
15188
15189defineMacro("\\newcommand", context => newcommand(context, false, true));
15190defineMacro("\\renewcommand", context => newcommand(context, true, false));
15191defineMacro("\\providecommand", context => newcommand(context, true, true)); // terminal (console) tools
15192
15193defineMacro("\\message", context => {
15194 var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console
15195
15196 console.log(arg.reverse().map(token => token.text).join(""));
15197 return '';
15198});
15199defineMacro("\\errmessage", context => {
15200 var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console
15201
15202 console.error(arg.reverse().map(token => token.text).join(""));
15203 return '';
15204});
15205defineMacro("\\show", context => {
15206 var tok = context.popToken();
15207 var name = tok.text; // eslint-disable-next-line no-console
15208
15209 console.log(tok, context.macros.get(name), functions[name], symbols.math[name], symbols.text[name]);
15210 return '';
15211}); //////////////////////////////////////////////////////////////////////
15212// Grouping
15213// \let\bgroup={ \let\egroup=}
15214
15215defineMacro("\\bgroup", "{");
15216defineMacro("\\egroup", "}"); // Symbols from latex.ltx:
15217// \def~{\nobreakspace{}}
15218// \def\lq{`}
15219// \def\rq{'}
15220// \def \aa {\r a}
15221// \def \AA {\r A}
15222
15223defineMacro("~", "\\nobreakspace");
15224defineMacro("\\lq", "`");
15225defineMacro("\\rq", "'");
15226defineMacro("\\aa", "\\r a");
15227defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML.
15228// \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}}
15229// \DeclareTextCommandDefault{\textregistered}{\textcircled{%
15230// \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}}
15231// \DeclareRobustCommand{\copyright}{%
15232// \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi}
15233
15234defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}");
15235defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}");
15236defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF
15237
15238defineMacro("\u212C", "\\mathscr{B}"); // script
15239
15240defineMacro("\u2130", "\\mathscr{E}");
15241defineMacro("\u2131", "\\mathscr{F}");
15242defineMacro("\u210B", "\\mathscr{H}");
15243defineMacro("\u2110", "\\mathscr{I}");
15244defineMacro("\u2112", "\\mathscr{L}");
15245defineMacro("\u2133", "\\mathscr{M}");
15246defineMacro("\u211B", "\\mathscr{R}");
15247defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur
15248
15249defineMacro("\u210C", "\\mathfrak{H}");
15250defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML.
15251
15252defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot
15253// The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays
15254// the dot at U+22C5 and gives it punct spacing.
15255
15256defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode
15257
15258defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
15259defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
15260defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \mathstrut from the TeXbook, p 360
15261
15262defineMacro("\\mathstrut", "\\vphantom{(}"); // \underbar from TeXbook p 353
15263
15264defineMacro("\\underbar", "\\underline{\\text{#1}}"); // \not is defined by base/fontmath.ltx via
15265// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36}
15266// It's thus treated like a \mathrel, but defined by a symbol that has zero
15267// width but extends to the right. We use \rlap to get that spacing.
15268// For MathML we write U+0338 here. buildMathML.js will then do the overlay.
15269
15270defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx:
15271// \def\neq{\not=} \let\ne=\neq
15272// \DeclareRobustCommand
15273// \notin{\mathrel{\m@th\mathpalette\c@ncel\in}}
15274// \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
15275
15276defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}");
15277defineMacro("\\ne", "\\neq");
15278defineMacro("\u2260", "\\neq");
15279defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}");
15280defineMacro("\u2209", "\\notin"); // Unicode stacked relations
15281
15282defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}");
15283defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}");
15284defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}");
15285defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}");
15286defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}");
15287defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}");
15288defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode
15289
15290defineMacro("\u27C2", "\\perp");
15291defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}");
15292defineMacro("\u220C", "\\notni");
15293defineMacro("\u231C", "\\ulcorner");
15294defineMacro("\u231D", "\\urcorner");
15295defineMacro("\u231E", "\\llcorner");
15296defineMacro("\u231F", "\\lrcorner");
15297defineMacro("\u00A9", "\\copyright");
15298defineMacro("\u00AE", "\\textregistered");
15299defineMacro("\uFE0F", "\\textregistered"); // The KaTeX fonts have corners at codepoints that don't match Unicode.
15300// For MathML purposes, use the Unicode code point.
15301
15302defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}");
15303defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}");
15304defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}");
15305defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}"); //////////////////////////////////////////////////////////////////////
15306// LaTeX_2ε
15307// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@
15308// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
15309// We'll call \varvdots, which gets a glyph from symbols.js.
15310// The zero-width rule gets us an equivalent to the vertical 6pt kern.
15311
15312defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}");
15313defineMacro("\u22ee", "\\vdots"); //////////////////////////////////////////////////////////////////////
15314// amsmath.sty
15315// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf
15316// Italic Greek capital letters. AMS defines these with \DeclareMathSymbol,
15317// but they are equivalent to \mathit{\Letter}.
15318
15319defineMacro("\\varGamma", "\\mathit{\\Gamma}");
15320defineMacro("\\varDelta", "\\mathit{\\Delta}");
15321defineMacro("\\varTheta", "\\mathit{\\Theta}");
15322defineMacro("\\varLambda", "\\mathit{\\Lambda}");
15323defineMacro("\\varXi", "\\mathit{\\Xi}");
15324defineMacro("\\varPi", "\\mathit{\\Pi}");
15325defineMacro("\\varSigma", "\\mathit{\\Sigma}");
15326defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}");
15327defineMacro("\\varPhi", "\\mathit{\\Phi}");
15328defineMacro("\\varPsi", "\\mathit{\\Psi}");
15329defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
15330
15331defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript
15332// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}
15333
15334defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
15335
15336defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;}
15337// \def\implies{\DOTSB\;\Longrightarrow\;}
15338// \def\impliedby{\DOTSB\;\Longleftarrow\;}
15339
15340defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;");
15341defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;");
15342defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // AMSMath's automatic \dots, based on \mdots@@ macro.
15343
15344var dotsByToken = {
15345 ',': '\\dotsc',
15346 '\\not': '\\dotsb',
15347 // \keybin@ checks for the following:
15348 '+': '\\dotsb',
15349 '=': '\\dotsb',
15350 '<': '\\dotsb',
15351 '>': '\\dotsb',
15352 '-': '\\dotsb',
15353 '*': '\\dotsb',
15354 ':': '\\dotsb',
15355 // Symbols whose definition starts with \DOTSB:
15356 '\\DOTSB': '\\dotsb',
15357 '\\coprod': '\\dotsb',
15358 '\\bigvee': '\\dotsb',
15359 '\\bigwedge': '\\dotsb',
15360 '\\biguplus': '\\dotsb',
15361 '\\bigcap': '\\dotsb',
15362 '\\bigcup': '\\dotsb',
15363 '\\prod': '\\dotsb',
15364 '\\sum': '\\dotsb',
15365 '\\bigotimes': '\\dotsb',
15366 '\\bigoplus': '\\dotsb',
15367 '\\bigodot': '\\dotsb',
15368 '\\bigsqcup': '\\dotsb',
15369 '\\And': '\\dotsb',
15370 '\\longrightarrow': '\\dotsb',
15371 '\\Longrightarrow': '\\dotsb',
15372 '\\longleftarrow': '\\dotsb',
15373 '\\Longleftarrow': '\\dotsb',
15374 '\\longleftrightarrow': '\\dotsb',
15375 '\\Longleftrightarrow': '\\dotsb',
15376 '\\mapsto': '\\dotsb',
15377 '\\longmapsto': '\\dotsb',
15378 '\\hookrightarrow': '\\dotsb',
15379 '\\doteq': '\\dotsb',
15380 // Symbols whose definition starts with \mathbin:
15381 '\\mathbin': '\\dotsb',
15382 // Symbols whose definition starts with \mathrel:
15383 '\\mathrel': '\\dotsb',
15384 '\\relbar': '\\dotsb',
15385 '\\Relbar': '\\dotsb',
15386 '\\xrightarrow': '\\dotsb',
15387 '\\xleftarrow': '\\dotsb',
15388 // Symbols whose definition starts with \DOTSI:
15389 '\\DOTSI': '\\dotsi',
15390 '\\int': '\\dotsi',
15391 '\\oint': '\\dotsi',
15392 '\\iint': '\\dotsi',
15393 '\\iiint': '\\dotsi',
15394 '\\iiiint': '\\dotsi',
15395 '\\idotsint': '\\dotsi',
15396 // Symbols whose definition starts with \DOTSX:
15397 '\\DOTSX': '\\dotsx'
15398};
15399defineMacro("\\dots", function (context) {
15400 // TODO: If used in text mode, should expand to \textellipsis.
15401 // However, in KaTeX, \textellipsis and \ldots behave the same
15402 // (in text mode), and it's unlikely we'd see any of the math commands
15403 // that affect the behavior of \dots when in text mode. So fine for now
15404 // (until we support \ifmmode ... \else ... \fi).
15405 var thedots = '\\dotso';
15406 var next = context.expandAfterFuture().text;
15407
15408 if (next in dotsByToken) {
15409 thedots = dotsByToken[next];
15410 } else if (next.substr(0, 4) === '\\not') {
15411 thedots = '\\dotsb';
15412 } else if (next in symbols.math) {
15413 if (utils.contains(['bin', 'rel'], symbols.math[next].group)) {
15414 thedots = '\\dotsb';
15415 }
15416 }
15417
15418 return thedots;
15419});
15420var spaceAfterDots = {
15421 // \rightdelim@ checks for the following:
15422 ')': true,
15423 ']': true,
15424 '\\rbrack': true,
15425 '\\}': true,
15426 '\\rbrace': true,
15427 '\\rangle': true,
15428 '\\rceil': true,
15429 '\\rfloor': true,
15430 '\\rgroup': true,
15431 '\\rmoustache': true,
15432 '\\right': true,
15433 '\\bigr': true,
15434 '\\biggr': true,
15435 '\\Bigr': true,
15436 '\\Biggr': true,
15437 // \extra@ also tests for the following:
15438 '$': true,
15439 // \extrap@ checks for the following:
15440 ';': true,
15441 '.': true,
15442 ',': true
15443};
15444defineMacro("\\dotso", function (context) {
15445 var next = context.future().text;
15446
15447 if (next in spaceAfterDots) {
15448 return "\\ldots\\,";
15449 } else {
15450 return "\\ldots";
15451 }
15452});
15453defineMacro("\\dotsc", function (context) {
15454 var next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for
15455 // ';' and '.', but doesn't check for ','.
15456
15457 if (next in spaceAfterDots && next !== ',') {
15458 return "\\ldots\\,";
15459 } else {
15460 return "\\ldots";
15461 }
15462});
15463defineMacro("\\cdots", function (context) {
15464 var next = context.future().text;
15465
15466 if (next in spaceAfterDots) {
15467 return "\\@cdots\\,";
15468 } else {
15469 return "\\@cdots";
15470 }
15471});
15472defineMacro("\\dotsb", "\\cdots");
15473defineMacro("\\dotsm", "\\cdots");
15474defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro
15475// starting with \DOTSX implies \dotso, and then \extra@ detects this case
15476// and forces the added `\,`.
15477
15478defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax
15479// \let\DOTSB\relax
15480// \let\DOTSX\relax
15481
15482defineMacro("\\DOTSI", "\\relax");
15483defineMacro("\\DOTSB", "\\relax");
15484defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults
15485// \DeclareRobustCommand{\tmspace}[3]{%
15486// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax}
15487
15488defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}}
15489// TODO: math mode should use \thinmuskip
15490
15491defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\,
15492
15493defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip}
15494// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}}
15495// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu
15496
15497defineMacro("\\>", "\\mskip{4mu}");
15498defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\:
15499
15500defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}}
15501// TODO: math mode should use \thickmuskip = 5mu plus 5mu
15502
15503defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\;
15504
15505defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}}
15506// TODO: math mode should use \thinmuskip
15507
15508defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\!
15509
15510defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}}
15511// TODO: math mode should use \medmuskip
15512
15513defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}}
15514// TODO: math mode should use \thickmuskip
15515
15516defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em }
15517
15518defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax}
15519
15520defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax}
15521
15522defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax}
15523
15524defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag
15525
15526defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
15527defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
15528defineMacro("\\tag@literal", context => {
15529 if (context.macros.get("\\df@tag")) {
15530 throw new ParseError("Multiple \\tag");
15531 }
15532
15533 return "\\gdef\\df@tag{\\text{#1}}";
15534}); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
15535// {\operator@font mod}\penalty900
15536// \mkern5mu\nonscript\mskip-\medmuskip}
15537// \newcommand{\pod}[1]{\allowbreak
15538// \if@display\mkern18mu\else\mkern8mu\fi(#1)}
15539// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
15540// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu
15541// \else\mkern12mu\fi{\operator@font mod}\,\,#1}
15542// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu
15543
15544defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");
15545defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");
15546defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
15547defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); // \pmb -- A simulation of bold.
15548// The version in ambsy.sty works by typesetting three copies of the argument
15549// with small offsets. We use two copies. We omit the vertical offset because
15550// of rendering problems that makeVList encounters in Safari.
15551
15552defineMacro("\\pmb", "\\html@mathml{" + "\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" + "{\\mathbf{#1}}"); //////////////////////////////////////////////////////////////////////
15553// LaTeX source2e
15554// \expandafter\let\expandafter\@normalcr
15555// \csname\expandafter\@gobble\string\\ \endcsname
15556// \DeclareRobustCommand\newline{\@normalcr\relax}
15557
15558defineMacro("\\newline", "\\\\\\relax"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
15559// TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't
15560// support \@ yet, so that's omitted, and we add \text so that the result
15561// doesn't look funny in math mode.
15562
15563defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em%
15564// {\sbox\z@ T%
15565// \vbox to\ht\z@{\hbox{\check@mathfonts
15566// \fontsize\sf@size\z@
15567// \math@fontsfalse\selectfont
15568// A}%
15569// \vss}%
15570// }%
15571// \kern-.15em%
15572// \TeX}
15573// This code aligns the top of the A with the T (from the perspective of TeX's
15574// boxes, though visually the A appears to extend above slightly).
15575// We compute the corresponding \raisebox when A is rendered in \normalsize
15576// \scriptstyle, which has a scale factor of 0.7 (see Options.js).
15577
15578var latexRaiseA = makeEm(fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1]);
15579defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo
15580
15581defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
15582// \def\@hspace#1{\hskip #1\relax}
15583// \def\@hspacer#1{\vrule \@width\z@\nobreak
15584// \hskip #1\hskip \z@skip}
15585
15586defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace");
15587defineMacro("\\@hspace", "\\hskip #1\\relax");
15588defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); //////////////////////////////////////////////////////////////////////
15589// mathtools.sty
15590//\providecommand\ordinarycolon{:}
15591
15592defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}}
15593//TODO(edemaine): Not yet centered. Fix via \raisebox or #726
15594
15595defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon}
15596
15597defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=}
15598
15599defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔
15600// \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=}
15601
15602defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
15603
15604defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
15605
15606defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon}
15607
15608defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕
15609// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon}
15610
15611defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon}
15612
15613defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon}
15614
15615defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx}
15616
15617defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx}
15618
15619defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim}
15620
15621defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim}
15622
15623defineMacro("\\Colonsim", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"2237\\char\"223c}}"); // Some Unicode characters are implemented with macros to mathtools functions.
15624
15625defineMacro("\u2237", "\\dblcolon"); // ::
15626
15627defineMacro("\u2239", "\\eqcolon"); // -:
15628
15629defineMacro("\u2254", "\\coloneqq"); // :=
15630
15631defineMacro("\u2255", "\\eqqcolon"); // =:
15632
15633defineMacro("\u2A74", "\\Coloneqq"); // ::=
15634//////////////////////////////////////////////////////////////////////
15635// colonequals.sty
15636// Alternate names for mathtools's macros:
15637
15638defineMacro("\\ratio", "\\vcentcolon");
15639defineMacro("\\coloncolon", "\\dblcolon");
15640defineMacro("\\colonequals", "\\coloneqq");
15641defineMacro("\\coloncolonequals", "\\Coloneqq");
15642defineMacro("\\equalscolon", "\\eqqcolon");
15643defineMacro("\\equalscoloncolon", "\\Eqqcolon");
15644defineMacro("\\colonminus", "\\coloneq");
15645defineMacro("\\coloncolonminus", "\\Coloneq");
15646defineMacro("\\minuscolon", "\\eqcolon");
15647defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals.
15648
15649defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals.
15650
15651defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions:
15652
15653defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
15654defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}");
15655defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
15656defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts
15657
15658defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
15659defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
15660defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); //////////////////////////////////////////////////////////////////////
15661// From amsopn.sty
15662
15663defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}");
15664defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}");
15665defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}");
15666defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}");
15667defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}");
15668defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"); //////////////////////////////////////////////////////////////////////
15669// MathML alternates for KaTeX glyphs in the Unicode private area
15670
15671defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}");
15672defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}");
15673defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}");
15674defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}");
15675defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}");
15676defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}");
15677defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}");
15678defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}");
15679defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}");
15680defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}");
15681defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}");
15682defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}");
15683defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}");
15684defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}");
15685defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}");
15686defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"); //////////////////////////////////////////////////////////////////////
15687// stmaryrd and semantic
15688// The stmaryrd and semantic packages render the next four items by calling a
15689// glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros.
15690
15691defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}");
15692defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}");
15693defineMacro("\u27e6", "\\llbracket"); // blackboard bold [
15694
15695defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ]
15696
15697defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}");
15698defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}");
15699defineMacro("\u2983", "\\lBrace"); // blackboard bold {
15700
15701defineMacro("\u2984", "\\rBrace"); // blackboard bold }
15702// TODO: Create variable sized versions of the last two items. I believe that
15703// will require new font glyphs.
15704// The stmaryrd function `\minuso` provides a "Plimsoll" symbol that
15705// superimposes the characters \circ and \mathminus. Used in chemistry.
15706
15707defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}");
15708defineMacro("⦵", "\\minuso"); //////////////////////////////////////////////////////////////////////
15709// texvc.sty
15710// The texvc package contains macros available in mediawiki pages.
15711// We omit the functions deprecated at
15712// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax
15713// We also omit texvc's \O, which conflicts with \text{\O}
15714
15715defineMacro("\\darr", "\\downarrow");
15716defineMacro("\\dArr", "\\Downarrow");
15717defineMacro("\\Darr", "\\Downarrow");
15718defineMacro("\\lang", "\\langle");
15719defineMacro("\\rang", "\\rangle");
15720defineMacro("\\uarr", "\\uparrow");
15721defineMacro("\\uArr", "\\Uparrow");
15722defineMacro("\\Uarr", "\\Uparrow");
15723defineMacro("\\N", "\\mathbb{N}");
15724defineMacro("\\R", "\\mathbb{R}");
15725defineMacro("\\Z", "\\mathbb{Z}");
15726defineMacro("\\alef", "\\aleph");
15727defineMacro("\\alefsym", "\\aleph");
15728defineMacro("\\Alpha", "\\mathrm{A}");
15729defineMacro("\\Beta", "\\mathrm{B}");
15730defineMacro("\\bull", "\\bullet");
15731defineMacro("\\Chi", "\\mathrm{X}");
15732defineMacro("\\clubs", "\\clubsuit");
15733defineMacro("\\cnums", "\\mathbb{C}");
15734defineMacro("\\Complex", "\\mathbb{C}");
15735defineMacro("\\Dagger", "\\ddagger");
15736defineMacro("\\diamonds", "\\diamondsuit");
15737defineMacro("\\empty", "\\emptyset");
15738defineMacro("\\Epsilon", "\\mathrm{E}");
15739defineMacro("\\Eta", "\\mathrm{H}");
15740defineMacro("\\exist", "\\exists");
15741defineMacro("\\harr", "\\leftrightarrow");
15742defineMacro("\\hArr", "\\Leftrightarrow");
15743defineMacro("\\Harr", "\\Leftrightarrow");
15744defineMacro("\\hearts", "\\heartsuit");
15745defineMacro("\\image", "\\Im");
15746defineMacro("\\infin", "\\infty");
15747defineMacro("\\Iota", "\\mathrm{I}");
15748defineMacro("\\isin", "\\in");
15749defineMacro("\\Kappa", "\\mathrm{K}");
15750defineMacro("\\larr", "\\leftarrow");
15751defineMacro("\\lArr", "\\Leftarrow");
15752defineMacro("\\Larr", "\\Leftarrow");
15753defineMacro("\\lrarr", "\\leftrightarrow");
15754defineMacro("\\lrArr", "\\Leftrightarrow");
15755defineMacro("\\Lrarr", "\\Leftrightarrow");
15756defineMacro("\\Mu", "\\mathrm{M}");
15757defineMacro("\\natnums", "\\mathbb{N}");
15758defineMacro("\\Nu", "\\mathrm{N}");
15759defineMacro("\\Omicron", "\\mathrm{O}");
15760defineMacro("\\plusmn", "\\pm");
15761defineMacro("\\rarr", "\\rightarrow");
15762defineMacro("\\rArr", "\\Rightarrow");
15763defineMacro("\\Rarr", "\\Rightarrow");
15764defineMacro("\\real", "\\Re");
15765defineMacro("\\reals", "\\mathbb{R}");
15766defineMacro("\\Reals", "\\mathbb{R}");
15767defineMacro("\\Rho", "\\mathrm{P}");
15768defineMacro("\\sdot", "\\cdot");
15769defineMacro("\\sect", "\\S");
15770defineMacro("\\spades", "\\spadesuit");
15771defineMacro("\\sub", "\\subset");
15772defineMacro("\\sube", "\\subseteq");
15773defineMacro("\\supe", "\\supseteq");
15774defineMacro("\\Tau", "\\mathrm{T}");
15775defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}");
15776
15777defineMacro("\\weierp", "\\wp");
15778defineMacro("\\Zeta", "\\mathrm{Z}"); //////////////////////////////////////////////////////////////////////
15779// statmath.sty
15780// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf
15781
15782defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
15783defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
15784defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); //////////////////////////////////////////////////////////////////////
15785// braket.sty
15786// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
15787
15788defineMacro("\\bra", "\\mathinner{\\langle{#1}|}");
15789defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
15790defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
15791defineMacro("\\Bra", "\\left\\langle#1\\right|");
15792defineMacro("\\Ket", "\\left|#1\\right\\rangle"); //////////////////////////////////////////////////////////////////////
15793// actuarialangle.dtx
15794
15795defineMacro("\\angln", "{\\angl n}"); // Custom Khan Academy colors, should be moved to an optional package
15796
15797defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
15798defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
15799defineMacro("\\pink", "\\textcolor{##ff00af}{#1}");
15800defineMacro("\\red", "\\textcolor{##df0030}{#1}");
15801defineMacro("\\green", "\\textcolor{##28ae7b}{#1}");
15802defineMacro("\\gray", "\\textcolor{gray}{#1}");
15803defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}");
15804defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}");
15805defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}");
15806defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}");
15807defineMacro("\\blueD", "\\textcolor{##11accd}{#1}");
15808defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}");
15809defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}");
15810defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}");
15811defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}");
15812defineMacro("\\tealD", "\\textcolor{##01a995}{#1}");
15813defineMacro("\\tealE", "\\textcolor{##208170}{#1}");
15814defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}");
15815defineMacro("\\greenB", "\\textcolor{##8af281}{#1}");
15816defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}");
15817defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}");
15818defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}");
15819defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}");
15820defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}");
15821defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}");
15822defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}");
15823defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}");
15824defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}");
15825defineMacro("\\redB", "\\textcolor{##ff8482}{#1}");
15826defineMacro("\\redC", "\\textcolor{##f9685d}{#1}");
15827defineMacro("\\redD", "\\textcolor{##e84d39}{#1}");
15828defineMacro("\\redE", "\\textcolor{##bc2612}{#1}");
15829defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}");
15830defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}");
15831defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}");
15832defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}");
15833defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}");
15834defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}");
15835defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}");
15836defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}");
15837defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}");
15838defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}");
15839defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}");
15840defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}");
15841defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}");
15842defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}");
15843defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}");
15844defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}");
15845defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}");
15846defineMacro("\\grayE", "\\textcolor{##babec2}{#1}");
15847defineMacro("\\grayF", "\\textcolor{##888d93}{#1}");
15848defineMacro("\\grayG", "\\textcolor{##626569}{#1}");
15849defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}");
15850defineMacro("\\grayI", "\\textcolor{##21242c}{#1}");
15851defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}");
15852defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}");
15853
15854/**
15855 * This file contains the “gullet” where macros are expanded
15856 * until only non-macro tokens remain.
15857 */
15858// List of commands that act like macros but aren't defined as a macro,
15859// function, or symbol. Used in `isDefined`.
15860var implicitCommands = {
15861 "^": true,
15862 // Parser.js
15863 "_": true,
15864 // Parser.js
15865 "\\limits": true,
15866 // Parser.js
15867 "\\nolimits": true // Parser.js
15868
15869};
15870class MacroExpander {
15871 constructor(input, settings, mode) {
15872 this.settings = void 0;
15873 this.expansionCount = void 0;
15874 this.lexer = void 0;
15875 this.macros = void 0;
15876 this.stack = void 0;
15877 this.mode = void 0;
15878 this.settings = settings;
15879 this.expansionCount = 0;
15880 this.feed(input); // Make new global namespace
15881
15882 this.macros = new Namespace(macros, settings.macros);
15883 this.mode = mode;
15884 this.stack = []; // contains tokens in REVERSE order
15885 }
15886 /**
15887 * Feed a new input string to the same MacroExpander
15888 * (with existing macros etc.).
15889 */
15890
15891
15892 feed(input) {
15893 this.lexer = new Lexer(input, this.settings);
15894 }
15895 /**
15896 * Switches between "text" and "math" modes.
15897 */
15898
15899
15900 switchMode(newMode) {
15901 this.mode = newMode;
15902 }
15903 /**
15904 * Start a new group nesting within all namespaces.
15905 */
15906
15907
15908 beginGroup() {
15909 this.macros.beginGroup();
15910 }
15911 /**
15912 * End current group nesting within all namespaces.
15913 */
15914
15915
15916 endGroup() {
15917 this.macros.endGroup();
15918 }
15919 /**
15920 * Ends all currently nested groups (if any), restoring values before the
15921 * groups began. Useful in case of an error in the middle of parsing.
15922 */
15923
15924
15925 endGroups() {
15926 this.macros.endGroups();
15927 }
15928 /**
15929 * Returns the topmost token on the stack, without expanding it.
15930 * Similar in behavior to TeX's `\futurelet`.
15931 */
15932
15933
15934 future() {
15935 if (this.stack.length === 0) {
15936 this.pushToken(this.lexer.lex());
15937 }
15938
15939 return this.stack[this.stack.length - 1];
15940 }
15941 /**
15942 * Remove and return the next unexpanded token.
15943 */
15944
15945
15946 popToken() {
15947 this.future(); // ensure non-empty stack
15948
15949 return this.stack.pop();
15950 }
15951 /**
15952 * Add a given token to the token stack. In particular, this get be used
15953 * to put back a token returned from one of the other methods.
15954 */
15955
15956
15957 pushToken(token) {
15958 this.stack.push(token);
15959 }
15960 /**
15961 * Append an array of tokens to the token stack.
15962 */
15963
15964
15965 pushTokens(tokens) {
15966 this.stack.push(...tokens);
15967 }
15968 /**
15969 * Find an macro argument without expanding tokens and append the array of
15970 * tokens to the token stack. Uses Token as a container for the result.
15971 */
15972
15973
15974 scanArgument(isOptional) {
15975 var start;
15976 var end;
15977 var tokens;
15978
15979 if (isOptional) {
15980 this.consumeSpaces(); // \@ifnextchar gobbles any space following it
15981
15982 if (this.future().text !== "[") {
15983 return null;
15984 }
15985
15986 start = this.popToken(); // don't include [ in tokens
15987
15988 ({
15989 tokens,
15990 end
15991 } = this.consumeArg(["]"]));
15992 } else {
15993 ({
15994 tokens,
15995 start,
15996 end
15997 } = this.consumeArg());
15998 } // indicate the end of an argument
15999
16000
16001 this.pushToken(new Token("EOF", end.loc));
16002 this.pushTokens(tokens);
16003 return start.range(end, "");
16004 }
16005 /**
16006 * Consume all following space tokens, without expansion.
16007 */
16008
16009
16010 consumeSpaces() {
16011 for (;;) {
16012 var token = this.future();
16013
16014 if (token.text === " ") {
16015 this.stack.pop();
16016 } else {
16017 break;
16018 }
16019 }
16020 }
16021 /**
16022 * Consume an argument from the token stream, and return the resulting array
16023 * of tokens and start/end token.
16024 */
16025
16026
16027 consumeArg(delims) {
16028 // The argument for a delimited parameter is the shortest (possibly
16029 // empty) sequence of tokens with properly nested {...} groups that is
16030 // followed ... by this particular list of non-parameter tokens.
16031 // The argument for an undelimited parameter is the next nonblank
16032 // token, unless that token is ‘{’, when the argument will be the
16033 // entire {...} group that follows.
16034 var tokens = [];
16035 var isDelimited = delims && delims.length > 0;
16036
16037 if (!isDelimited) {
16038 // Ignore spaces between arguments. As the TeXbook says:
16039 // "After you have said ‘\def\row#1#2{...}’, you are allowed to
16040 // put spaces between the arguments (e.g., ‘\row x n’), because
16041 // TeX doesn’t use single spaces as undelimited arguments."
16042 this.consumeSpaces();
16043 }
16044
16045 var start = this.future();
16046 var tok;
16047 var depth = 0;
16048 var match = 0;
16049
16050 do {
16051 tok = this.popToken();
16052 tokens.push(tok);
16053
16054 if (tok.text === "{") {
16055 ++depth;
16056 } else if (tok.text === "}") {
16057 --depth;
16058
16059 if (depth === -1) {
16060 throw new ParseError("Extra }", tok);
16061 }
16062 } else if (tok.text === "EOF") {
16063 throw new ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok);
16064 }
16065
16066 if (delims && isDelimited) {
16067 if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) {
16068 ++match;
16069
16070 if (match === delims.length) {
16071 // don't include delims in tokens
16072 tokens.splice(-match, match);
16073 break;
16074 }
16075 } else {
16076 match = 0;
16077 }
16078 }
16079 } while (depth !== 0 || isDelimited); // If the argument found ... has the form ‘{<nested tokens>}’,
16080 // ... the outermost braces enclosing the argument are removed
16081
16082
16083 if (start.text === "{" && tokens[tokens.length - 1].text === "}") {
16084 tokens.pop();
16085 tokens.shift();
16086 }
16087
16088 tokens.reverse(); // to fit in with stack order
16089
16090 return {
16091 tokens,
16092 start,
16093 end: tok
16094 };
16095 }
16096 /**
16097 * Consume the specified number of (delimited) arguments from the token
16098 * stream and return the resulting array of arguments.
16099 */
16100
16101
16102 consumeArgs(numArgs, delimiters) {
16103 if (delimiters) {
16104 if (delimiters.length !== numArgs + 1) {
16105 throw new ParseError("The length of delimiters doesn't match the number of args!");
16106 }
16107
16108 var delims = delimiters[0];
16109
16110 for (var i = 0; i < delims.length; i++) {
16111 var tok = this.popToken();
16112
16113 if (delims[i] !== tok.text) {
16114 throw new ParseError("Use of the macro doesn't match its definition", tok);
16115 }
16116 }
16117 }
16118
16119 var args = [];
16120
16121 for (var _i = 0; _i < numArgs; _i++) {
16122 args.push(this.consumeArg(delimiters && delimiters[_i + 1]).tokens);
16123 }
16124
16125 return args;
16126 }
16127 /**
16128 * Expand the next token only once if possible.
16129 *
16130 * If the token is expanded, the resulting tokens will be pushed onto
16131 * the stack in reverse order and will be returned as an array,
16132 * also in reverse order.
16133 *
16134 * If not, the next token will be returned without removing it
16135 * from the stack. This case can be detected by a `Token` return value
16136 * instead of an `Array` return value.
16137 *
16138 * In either case, the next token will be on the top of the stack,
16139 * or the stack will be empty.
16140 *
16141 * Used to implement `expandAfterFuture` and `expandNextToken`.
16142 *
16143 * If expandableOnly, only expandable tokens are expanded and
16144 * an undefined control sequence results in an error.
16145 */
16146
16147
16148 expandOnce(expandableOnly) {
16149 var topToken = this.popToken();
16150 var name = topToken.text;
16151 var expansion = !topToken.noexpand ? this._getExpansion(name) : null;
16152
16153 if (expansion == null || expandableOnly && expansion.unexpandable) {
16154 if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) {
16155 throw new ParseError("Undefined control sequence: " + name);
16156 }
16157
16158 this.pushToken(topToken);
16159 return topToken;
16160 }
16161
16162 this.expansionCount++;
16163
16164 if (this.expansionCount > this.settings.maxExpand) {
16165 throw new ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting");
16166 }
16167
16168 var tokens = expansion.tokens;
16169 var args = this.consumeArgs(expansion.numArgs, expansion.delimiters);
16170
16171 if (expansion.numArgs) {
16172 // paste arguments in place of the placeholders
16173 tokens = tokens.slice(); // make a shallow copy
16174
16175 for (var i = tokens.length - 1; i >= 0; --i) {
16176 var tok = tokens[i];
16177
16178 if (tok.text === "#") {
16179 if (i === 0) {
16180 throw new ParseError("Incomplete placeholder at end of macro body", tok);
16181 }
16182
16183 tok = tokens[--i]; // next token on stack
16184
16185 if (tok.text === "#") {
16186 // ## → #
16187 tokens.splice(i + 1, 1); // drop first #
16188 } else if (/^[1-9]$/.test(tok.text)) {
16189 // replace the placeholder with the indicated argument
16190 tokens.splice(i, 2, ...args[+tok.text - 1]);
16191 } else {
16192 throw new ParseError("Not a valid argument number", tok);
16193 }
16194 }
16195 }
16196 } // Concatenate expansion onto top of stack.
16197
16198
16199 this.pushTokens(tokens);
16200 return tokens;
16201 }
16202 /**
16203 * Expand the next token only once (if possible), and return the resulting
16204 * top token on the stack (without removing anything from the stack).
16205 * Similar in behavior to TeX's `\expandafter\futurelet`.
16206 * Equivalent to expandOnce() followed by future().
16207 */
16208
16209
16210 expandAfterFuture() {
16211 this.expandOnce();
16212 return this.future();
16213 }
16214 /**
16215 * Recursively expand first token, then return first non-expandable token.
16216 */
16217
16218
16219 expandNextToken() {
16220 for (;;) {
16221 var expanded = this.expandOnce(); // expandOnce returns Token if and only if it's fully expanded.
16222
16223 if (expanded instanceof Token) {
16224 // the token after \noexpand is interpreted as if its meaning
16225 // were ‘\relax’
16226 if (expanded.treatAsRelax) {
16227 expanded.text = "\\relax";
16228 }
16229
16230 return this.stack.pop(); // === expanded
16231 }
16232 } // Flow unable to figure out that this pathway is impossible.
16233 // https://github.com/facebook/flow/issues/4808
16234
16235
16236 throw new Error(); // eslint-disable-line no-unreachable
16237 }
16238 /**
16239 * Fully expand the given macro name and return the resulting list of
16240 * tokens, or return `undefined` if no such macro is defined.
16241 */
16242
16243
16244 expandMacro(name) {
16245 return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined;
16246 }
16247 /**
16248 * Fully expand the given token stream and return the resulting list of tokens
16249 */
16250
16251
16252 expandTokens(tokens) {
16253 var output = [];
16254 var oldStackLength = this.stack.length;
16255 this.pushTokens(tokens);
16256
16257 while (this.stack.length > oldStackLength) {
16258 var expanded = this.expandOnce(true); // expand only expandable tokens
16259 // expandOnce returns Token if and only if it's fully expanded.
16260
16261 if (expanded instanceof Token) {
16262 if (expanded.treatAsRelax) {
16263 // the expansion of \noexpand is the token itself
16264 expanded.noexpand = false;
16265 expanded.treatAsRelax = false;
16266 }
16267
16268 output.push(this.stack.pop());
16269 }
16270 }
16271
16272 return output;
16273 }
16274 /**
16275 * Fully expand the given macro name and return the result as a string,
16276 * or return `undefined` if no such macro is defined.
16277 */
16278
16279
16280 expandMacroAsText(name) {
16281 var tokens = this.expandMacro(name);
16282
16283 if (tokens) {
16284 return tokens.map(token => token.text).join("");
16285 } else {
16286 return tokens;
16287 }
16288 }
16289 /**
16290 * Returns the expanded macro as a reversed array of tokens and a macro
16291 * argument count. Or returns `null` if no such macro.
16292 */
16293
16294
16295 _getExpansion(name) {
16296 var definition = this.macros.get(name);
16297
16298 if (definition == null) {
16299 // mainly checking for undefined here
16300 return definition;
16301 } // If a single character has an associated catcode other than 13
16302 // (active character), then don't expand it.
16303
16304
16305 if (name.length === 1) {
16306 var catcode = this.lexer.catcodes[name];
16307
16308 if (catcode != null && catcode !== 13) {
16309 return;
16310 }
16311 }
16312
16313 var expansion = typeof definition === "function" ? definition(this) : definition;
16314
16315 if (typeof expansion === "string") {
16316 var numArgs = 0;
16317
16318 if (expansion.indexOf("#") !== -1) {
16319 var stripped = expansion.replace(/##/g, "");
16320
16321 while (stripped.indexOf("#" + (numArgs + 1)) !== -1) {
16322 ++numArgs;
16323 }
16324 }
16325
16326 var bodyLexer = new Lexer(expansion, this.settings);
16327 var tokens = [];
16328 var tok = bodyLexer.lex();
16329
16330 while (tok.text !== "EOF") {
16331 tokens.push(tok);
16332 tok = bodyLexer.lex();
16333 }
16334
16335 tokens.reverse(); // to fit in with stack using push and pop
16336
16337 var expanded = {
16338 tokens,
16339 numArgs
16340 };
16341 return expanded;
16342 }
16343
16344 return expansion;
16345 }
16346 /**
16347 * Determine whether a command is currently "defined" (has some
16348 * functionality), meaning that it's a macro (in the current group),
16349 * a function, a symbol, or one of the special commands listed in
16350 * `implicitCommands`.
16351 */
16352
16353
16354 isDefined(name) {
16355 return this.macros.has(name) || functions.hasOwnProperty(name) || symbols.math.hasOwnProperty(name) || symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name);
16356 }
16357 /**
16358 * Determine whether a command is expandable.
16359 */
16360
16361
16362 isExpandable(name) {
16363 var macro = this.macros.get(name);
16364 return macro != null ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable : functions.hasOwnProperty(name) && !functions[name].primitive;
16365 }
16366
16367}
16368
16369/* eslint no-constant-condition:0 */
16370
16371var unicodeAccents = {
16372 "́": {
16373 "text": "\\'",
16374 "math": "\\acute"
16375 },
16376 "̀": {
16377 "text": "\\`",
16378 "math": "\\grave"
16379 },
16380 "̈": {
16381 "text": "\\\"",
16382 "math": "\\ddot"
16383 },
16384 "̃": {
16385 "text": "\\~",
16386 "math": "\\tilde"
16387 },
16388 "̄": {
16389 "text": "\\=",
16390 "math": "\\bar"
16391 },
16392 "̆": {
16393 "text": "\\u",
16394 "math": "\\breve"
16395 },
16396 "̌": {
16397 "text": "\\v",
16398 "math": "\\check"
16399 },
16400 "̂": {
16401 "text": "\\^",
16402 "math": "\\hat"
16403 },
16404 "̇": {
16405 "text": "\\.",
16406 "math": "\\dot"
16407 },
16408 "̊": {
16409 "text": "\\r",
16410 "math": "\\mathring"
16411 },
16412 "̋": {
16413 "text": "\\H"
16414 },
16415 "̧": {
16416 "text": "\\c"
16417 }
16418};
16419var unicodeSymbols = {
16420 "á": "á",
16421 "à": "à",
16422 "ä": "ä",
16423 "ǟ": "ǟ",
16424 "ã": "ã",
16425 "ā": "ā",
16426 "ă": "ă",
16427 "ắ": "ắ",
16428 "ằ": "ằ",
16429 "ẵ": "ẵ",
16430 "ǎ": "ǎ",
16431 "â": "â",
16432 "ấ": "ấ",
16433 "ầ": "ầ",
16434 "ẫ": "ẫ",
16435 "ȧ": "ȧ",
16436 "ǡ": "ǡ",
16437 "å": "å",
16438 "ǻ": "ǻ",
16439 "ḃ": "ḃ",
16440 "ć": "ć",
16441 "ḉ": "ḉ",
16442 "č": "č",
16443 "ĉ": "ĉ",
16444 "ċ": "ċ",
16445 "ç": "ç",
16446 "ď": "ď",
16447 "ḋ": "ḋ",
16448 "ḑ": "ḑ",
16449 "é": "é",
16450 "è": "è",
16451 "ë": "ë",
16452 "ẽ": "ẽ",
16453 "ē": "ē",
16454 "ḗ": "ḗ",
16455 "ḕ": "ḕ",
16456 "ĕ": "ĕ",
16457 "ḝ": "ḝ",
16458 "ě": "ě",
16459 "ê": "ê",
16460 "ế": "ế",
16461 "ề": "ề",
16462 "ễ": "ễ",
16463 "ė": "ė",
16464 "ȩ": "ȩ",
16465 "ḟ": "ḟ",
16466 "ǵ": "ǵ",
16467 "ḡ": "ḡ",
16468 "ğ": "ğ",
16469 "ǧ": "ǧ",
16470 "ĝ": "ĝ",
16471 "ġ": "ġ",
16472 "ģ": "ģ",
16473 "ḧ": "ḧ",
16474 "ȟ": "ȟ",
16475 "ĥ": "ĥ",
16476 "ḣ": "ḣ",
16477 "ḩ": "ḩ",
16478 "í": "í",
16479 "ì": "ì",
16480 "ï": "ï",
16481 "ḯ": "ḯ",
16482 "ĩ": "ĩ",
16483 "ī": "ī",
16484 "ĭ": "ĭ",
16485 "ǐ": "ǐ",
16486 "î": "î",
16487 "ǰ": "ǰ",
16488 "ĵ": "ĵ",
16489 "ḱ": "ḱ",
16490 "ǩ": "ǩ",
16491 "ķ": "ķ",
16492 "ĺ": "ĺ",
16493 "ľ": "ľ",
16494 "ļ": "ļ",
16495 "ḿ": "ḿ",
16496 "ṁ": "ṁ",
16497 "ń": "ń",
16498 "ǹ": "ǹ",
16499 "ñ": "ñ",
16500 "ň": "ň",
16501 "ṅ": "ṅ",
16502 "ņ": "ņ",
16503 "ó": "ó",
16504 "ò": "ò",
16505 "ö": "ö",
16506 "ȫ": "ȫ",
16507 "õ": "õ",
16508 "ṍ": "ṍ",
16509 "ṏ": "ṏ",
16510 "ȭ": "ȭ",
16511 "ō": "ō",
16512 "ṓ": "ṓ",
16513 "ṑ": "ṑ",
16514 "ŏ": "ŏ",
16515 "ǒ": "ǒ",
16516 "ô": "ô",
16517 "ố": "ố",
16518 "ồ": "ồ",
16519 "ỗ": "ỗ",
16520 "ȯ": "ȯ",
16521 "ȱ": "ȱ",
16522 "ő": "ő",
16523 "ṕ": "ṕ",
16524 "ṗ": "ṗ",
16525 "ŕ": "ŕ",
16526 "ř": "ř",
16527 "ṙ": "ṙ",
16528 "ŗ": "ŗ",
16529 "ś": "ś",
16530 "ṥ": "ṥ",
16531 "š": "š",
16532 "ṧ": "ṧ",
16533 "ŝ": "ŝ",
16534 "ṡ": "ṡ",
16535 "ş": "ş",
16536 "ẗ": "ẗ",
16537 "ť": "ť",
16538 "ṫ": "ṫ",
16539 "ţ": "ţ",
16540 "ú": "ú",
16541 "ù": "ù",
16542 "ü": "ü",
16543 "ǘ": "ǘ",
16544 "ǜ": "ǜ",
16545 "ǖ": "ǖ",
16546 "ǚ": "ǚ",
16547 "ũ": "ũ",
16548 "ṹ": "ṹ",
16549 "ū": "ū",
16550 "ṻ": "ṻ",
16551 "ŭ": "ŭ",
16552 "ǔ": "ǔ",
16553 "û": "û",
16554 "ů": "ů",
16555 "ű": "ű",
16556 "ṽ": "ṽ",
16557 "ẃ": "ẃ",
16558 "ẁ": "ẁ",
16559 "ẅ": "ẅ",
16560 "ŵ": "ŵ",
16561 "ẇ": "ẇ",
16562 "ẘ": "ẘ",
16563 "ẍ": "ẍ",
16564 "ẋ": "ẋ",
16565 "ý": "ý",
16566 "ỳ": "ỳ",
16567 "ÿ": "ÿ",
16568 "ỹ": "ỹ",
16569 "ȳ": "ȳ",
16570 "ŷ": "ŷ",
16571 "ẏ": "ẏ",
16572 "ẙ": "ẙ",
16573 "ź": "ź",
16574 "ž": "ž",
16575 "ẑ": "ẑ",
16576 "ż": "ż",
16577 "Á": "Á",
16578 "À": "À",
16579 "Ä": "Ä",
16580 "Ǟ": "Ǟ",
16581 "Ã": "Ã",
16582 "Ā": "Ā",
16583 "Ă": "Ă",
16584 "Ắ": "Ắ",
16585 "Ằ": "Ằ",
16586 "Ẵ": "Ẵ",
16587 "Ǎ": "Ǎ",
16588 "Â": "Â",
16589 "Ấ": "Ấ",
16590 "Ầ": "Ầ",
16591 "Ẫ": "Ẫ",
16592 "Ȧ": "Ȧ",
16593 "Ǡ": "Ǡ",
16594 "Å": "Å",
16595 "Ǻ": "Ǻ",
16596 "Ḃ": "Ḃ",
16597 "Ć": "Ć",
16598 "Ḉ": "Ḉ",
16599 "Č": "Č",
16600 "Ĉ": "Ĉ",
16601 "Ċ": "Ċ",
16602 "Ç": "Ç",
16603 "Ď": "Ď",
16604 "Ḋ": "Ḋ",
16605 "Ḑ": "Ḑ",
16606 "É": "É",
16607 "È": "È",
16608 "Ë": "Ë",
16609 "Ẽ": "Ẽ",
16610 "Ē": "Ē",
16611 "Ḗ": "Ḗ",
16612 "Ḕ": "Ḕ",
16613 "Ĕ": "Ĕ",
16614 "Ḝ": "Ḝ",
16615 "Ě": "Ě",
16616 "Ê": "Ê",
16617 "Ế": "Ế",
16618 "Ề": "Ề",
16619 "Ễ": "Ễ",
16620 "Ė": "Ė",
16621 "Ȩ": "Ȩ",
16622 "Ḟ": "Ḟ",
16623 "Ǵ": "Ǵ",
16624 "Ḡ": "Ḡ",
16625 "Ğ": "Ğ",
16626 "Ǧ": "Ǧ",
16627 "Ĝ": "Ĝ",
16628 "Ġ": "Ġ",
16629 "Ģ": "Ģ",
16630 "Ḧ": "Ḧ",
16631 "Ȟ": "Ȟ",
16632 "Ĥ": "Ĥ",
16633 "Ḣ": "Ḣ",
16634 "Ḩ": "Ḩ",
16635 "Í": "Í",
16636 "Ì": "Ì",
16637 "Ï": "Ï",
16638 "Ḯ": "Ḯ",
16639 "Ĩ": "Ĩ",
16640 "Ī": "Ī",
16641 "Ĭ": "Ĭ",
16642 "Ǐ": "Ǐ",
16643 "Î": "Î",
16644 "İ": "İ",
16645 "Ĵ": "Ĵ",
16646 "Ḱ": "Ḱ",
16647 "Ǩ": "Ǩ",
16648 "Ķ": "Ķ",
16649 "Ĺ": "Ĺ",
16650 "Ľ": "Ľ",
16651 "Ļ": "Ļ",
16652 "Ḿ": "Ḿ",
16653 "Ṁ": "Ṁ",
16654 "Ń": "Ń",
16655 "Ǹ": "Ǹ",
16656 "Ñ": "Ñ",
16657 "Ň": "Ň",
16658 "Ṅ": "Ṅ",
16659 "Ņ": "Ņ",
16660 "Ó": "Ó",
16661 "Ò": "Ò",
16662 "Ö": "Ö",
16663 "Ȫ": "Ȫ",
16664 "Õ": "Õ",
16665 "Ṍ": "Ṍ",
16666 "Ṏ": "Ṏ",
16667 "Ȭ": "Ȭ",
16668 "Ō": "Ō",
16669 "Ṓ": "Ṓ",
16670 "Ṑ": "Ṑ",
16671 "Ŏ": "Ŏ",
16672 "Ǒ": "Ǒ",
16673 "Ô": "Ô",
16674 "Ố": "Ố",
16675 "Ồ": "Ồ",
16676 "Ỗ": "Ỗ",
16677 "Ȯ": "Ȯ",
16678 "Ȱ": "Ȱ",
16679 "Ő": "Ő",
16680 "Ṕ": "Ṕ",
16681 "Ṗ": "Ṗ",
16682 "Ŕ": "Ŕ",
16683 "Ř": "Ř",
16684 "Ṙ": "Ṙ",
16685 "Ŗ": "Ŗ",
16686 "Ś": "Ś",
16687 "Ṥ": "Ṥ",
16688 "Š": "Š",
16689 "Ṧ": "Ṧ",
16690 "Ŝ": "Ŝ",
16691 "Ṡ": "Ṡ",
16692 "Ş": "Ş",
16693 "Ť": "Ť",
16694 "Ṫ": "Ṫ",
16695 "Ţ": "Ţ",
16696 "Ú": "Ú",
16697 "Ù": "Ù",
16698 "Ü": "Ü",
16699 "Ǘ": "Ǘ",
16700 "Ǜ": "Ǜ",
16701 "Ǖ": "Ǖ",
16702 "Ǚ": "Ǚ",
16703 "Ũ": "Ũ",
16704 "Ṹ": "Ṹ",
16705 "Ū": "Ū",
16706 "Ṻ": "Ṻ",
16707 "Ŭ": "Ŭ",
16708 "Ǔ": "Ǔ",
16709 "Û": "Û",
16710 "Ů": "Ů",
16711 "Ű": "Ű",
16712 "Ṽ": "Ṽ",
16713 "Ẃ": "Ẃ",
16714 "Ẁ": "Ẁ",
16715 "Ẅ": "Ẅ",
16716 "Ŵ": "Ŵ",
16717 "Ẇ": "Ẇ",
16718 "Ẍ": "Ẍ",
16719 "Ẋ": "Ẋ",
16720 "Ý": "Ý",
16721 "Ỳ": "Ỳ",
16722 "Ÿ": "Ÿ",
16723 "Ỹ": "Ỹ",
16724 "Ȳ": "Ȳ",
16725 "Ŷ": "Ŷ",
16726 "Ẏ": "Ẏ",
16727 "Ź": "Ź",
16728 "Ž": "Ž",
16729 "Ẑ": "Ẑ",
16730 "Ż": "Ż",
16731 "ά": "ά",
16732 "ὰ": "ὰ",
16733 "ᾱ": "ᾱ",
16734 "ᾰ": "ᾰ",
16735 "έ": "έ",
16736 "ὲ": "ὲ",
16737 "ή": "ή",
16738 "ὴ": "ὴ",
16739 "ί": "ί",
16740 "ὶ": "ὶ",
16741 "ϊ": "ϊ",
16742 "ΐ": "ΐ",
16743 "ῒ": "ῒ",
16744 "ῑ": "ῑ",
16745 "ῐ": "ῐ",
16746 "ό": "ό",
16747 "ὸ": "ὸ",
16748 "ύ": "ύ",
16749 "ὺ": "ὺ",
16750 "ϋ": "ϋ",
16751 "ΰ": "ΰ",
16752 "ῢ": "ῢ",
16753 "ῡ": "ῡ",
16754 "ῠ": "ῠ",
16755 "ώ": "ώ",
16756 "ὼ": "ὼ",
16757 "Ύ": "Ύ",
16758 "Ὺ": "Ὺ",
16759 "Ϋ": "Ϋ",
16760 "Ῡ": "Ῡ",
16761 "Ῠ": "Ῠ",
16762 "Ώ": "Ώ",
16763 "Ὼ": "Ὼ"
16764};
16765
16766/**
16767 * This file contains the parser used to parse out a TeX expression from the
16768 * input. Since TeX isn't context-free, standard parsers don't work particularly
16769 * well.
16770 *
16771 * The strategy of this parser is as such:
16772 *
16773 * The main functions (the `.parse...` ones) take a position in the current
16774 * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
16775 * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When
16776 * individual tokens are needed at a position, the lexer is called to pull out a
16777 * token, which is then used.
16778 *
16779 * The parser has a property called "mode" indicating the mode that
16780 * the parser is currently in. Currently it has to be one of "math" or
16781 * "text", which denotes whether the current environment is a math-y
16782 * one or a text-y one (e.g. inside \text). Currently, this serves to
16783 * limit the functions which can be used in text mode.
16784 *
16785 * The main functions then return an object which contains the useful data that
16786 * was parsed at its given point, and a new position at the end of the parsed
16787 * data. The main functions can call each other and continue the parsing by
16788 * using the returned position as a new starting point.
16789 *
16790 * There are also extra `.handle...` functions, which pull out some reused
16791 * functionality into self-contained functions.
16792 *
16793 * The functions return ParseNodes.
16794 */
16795class Parser {
16796 constructor(input, settings) {
16797 this.mode = void 0;
16798 this.gullet = void 0;
16799 this.settings = void 0;
16800 this.leftrightDepth = void 0;
16801 this.nextToken = void 0;
16802 // Start in math mode
16803 this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a
16804 // new lexer (mouth) for this parser (stomach, in the language of TeX)
16805
16806 this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing
16807
16808 this.settings = settings; // Count leftright depth (for \middle errors)
16809
16810 this.leftrightDepth = 0;
16811 }
16812 /**
16813 * Checks a result to make sure it has the right type, and throws an
16814 * appropriate error otherwise.
16815 */
16816
16817
16818 expect(text, consume) {
16819 if (consume === void 0) {
16820 consume = true;
16821 }
16822
16823 if (this.fetch().text !== text) {
16824 throw new ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch());
16825 }
16826
16827 if (consume) {
16828 this.consume();
16829 }
16830 }
16831 /**
16832 * Discards the current lookahead token, considering it consumed.
16833 */
16834
16835
16836 consume() {
16837 this.nextToken = null;
16838 }
16839 /**
16840 * Return the current lookahead token, or if there isn't one (at the
16841 * beginning, or if the previous lookahead token was consume()d),
16842 * fetch the next token as the new lookahead token and return it.
16843 */
16844
16845
16846 fetch() {
16847 if (this.nextToken == null) {
16848 this.nextToken = this.gullet.expandNextToken();
16849 }
16850
16851 return this.nextToken;
16852 }
16853 /**
16854 * Switches between "text" and "math" modes.
16855 */
16856
16857
16858 switchMode(newMode) {
16859 this.mode = newMode;
16860 this.gullet.switchMode(newMode);
16861 }
16862 /**
16863 * Main parsing function, which parses an entire input.
16864 */
16865
16866
16867 parse() {
16868 if (!this.settings.globalGroup) {
16869 // Create a group namespace for the math expression.
16870 // (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
16871 this.gullet.beginGroup();
16872 } // Use old \color behavior (same as LaTeX's \textcolor) if requested.
16873 // We do this within the group for the math expression, so it doesn't
16874 // pollute settings.macros.
16875
16876
16877 if (this.settings.colorIsTextColor) {
16878 this.gullet.macros.set("\\color", "\\textcolor");
16879 }
16880
16881 try {
16882 // Try to parse the input
16883 var parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end
16884
16885 this.expect("EOF"); // End the group namespace for the expression
16886
16887 if (!this.settings.globalGroup) {
16888 this.gullet.endGroup();
16889 }
16890
16891 return parse; // Close any leftover groups in case of a parse error.
16892 } finally {
16893 this.gullet.endGroups();
16894 }
16895 }
16896 /**
16897 * Fully parse a separate sequence of tokens as a separate job.
16898 * Tokens should be specified in reverse order, as in a MacroDefinition.
16899 */
16900
16901
16902 subparse(tokens) {
16903 // Save the next token from the current job.
16904 var oldToken = this.nextToken;
16905 this.consume(); // Run the new job, terminating it with an excess '}'
16906
16907 this.gullet.pushToken(new Token("}"));
16908 this.gullet.pushTokens(tokens);
16909 var parse = this.parseExpression(false);
16910 this.expect("}"); // Restore the next token from the current job.
16911
16912 this.nextToken = oldToken;
16913 return parse;
16914 }
16915
16916 /**
16917 * Parses an "expression", which is a list of atoms.
16918 *
16919 * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
16920 * happens when functions have higher precendence han infix
16921 * nodes in implicit parses.
16922 *
16923 * `breakOnTokenText`: The text of the token that the expression should end
16924 * with, or `null` if something else should end the
16925 * expression.
16926 */
16927 parseExpression(breakOnInfix, breakOnTokenText) {
16928 var body = []; // Keep adding atoms to the body until we can't parse any more atoms (either
16929 // we reached the end, a }, or a \right)
16930
16931 while (true) {
16932 // Ignore spaces in math mode
16933 if (this.mode === "math") {
16934 this.consumeSpaces();
16935 }
16936
16937 var lex = this.fetch();
16938
16939 if (Parser.endOfExpression.indexOf(lex.text) !== -1) {
16940 break;
16941 }
16942
16943 if (breakOnTokenText && lex.text === breakOnTokenText) {
16944 break;
16945 }
16946
16947 if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
16948 break;
16949 }
16950
16951 var atom = this.parseAtom(breakOnTokenText);
16952
16953 if (!atom) {
16954 break;
16955 } else if (atom.type === "internal") {
16956 continue;
16957 }
16958
16959 body.push(atom);
16960 }
16961
16962 if (this.mode === "text") {
16963 this.formLigatures(body);
16964 }
16965
16966 return this.handleInfixNodes(body);
16967 }
16968 /**
16969 * Rewrites infix operators such as \over with corresponding commands such
16970 * as \frac.
16971 *
16972 * There can only be one infix operator per group. If there's more than one
16973 * then the expression is ambiguous. This can be resolved by adding {}.
16974 */
16975
16976
16977 handleInfixNodes(body) {
16978 var overIndex = -1;
16979 var funcName;
16980
16981 for (var i = 0; i < body.length; i++) {
16982 if (body[i].type === "infix") {
16983 if (overIndex !== -1) {
16984 throw new ParseError("only one infix operator per group", body[i].token);
16985 }
16986
16987 overIndex = i;
16988 funcName = body[i].replaceWith;
16989 }
16990 }
16991
16992 if (overIndex !== -1 && funcName) {
16993 var numerNode;
16994 var denomNode;
16995 var numerBody = body.slice(0, overIndex);
16996 var denomBody = body.slice(overIndex + 1);
16997
16998 if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
16999 numerNode = numerBody[0];
17000 } else {
17001 numerNode = {
17002 type: "ordgroup",
17003 mode: this.mode,
17004 body: numerBody
17005 };
17006 }
17007
17008 if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
17009 denomNode = denomBody[0];
17010 } else {
17011 denomNode = {
17012 type: "ordgroup",
17013 mode: this.mode,
17014 body: denomBody
17015 };
17016 }
17017
17018 var node;
17019
17020 if (funcName === "\\\\abovefrac") {
17021 node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []);
17022 } else {
17023 node = this.callFunction(funcName, [numerNode, denomNode], []);
17024 }
17025
17026 return [node];
17027 } else {
17028 return body;
17029 }
17030 }
17031 /**
17032 * Handle a subscript or superscript with nice errors.
17033 */
17034
17035
17036 handleSupSubscript(name // For error reporting.
17037 ) {
17038 var symbolToken = this.fetch();
17039 var symbol = symbolToken.text;
17040 this.consume();
17041 this.consumeSpaces(); // ignore spaces before sup/subscript argument
17042
17043 var group = this.parseGroup(name);
17044
17045 if (!group) {
17046 throw new ParseError("Expected group after '" + symbol + "'", symbolToken);
17047 }
17048
17049 return group;
17050 }
17051 /**
17052 * Converts the textual input of an unsupported command into a text node
17053 * contained within a color node whose color is determined by errorColor
17054 */
17055
17056
17057 formatUnsupportedCmd(text) {
17058 var textordArray = [];
17059
17060 for (var i = 0; i < text.length; i++) {
17061 textordArray.push({
17062 type: "textord",
17063 mode: "text",
17064 text: text[i]
17065 });
17066 }
17067
17068 var textNode = {
17069 type: "text",
17070 mode: this.mode,
17071 body: textordArray
17072 };
17073 var colorNode = {
17074 type: "color",
17075 mode: this.mode,
17076 color: this.settings.errorColor,
17077 body: [textNode]
17078 };
17079 return colorNode;
17080 }
17081 /**
17082 * Parses a group with optional super/subscripts.
17083 */
17084
17085
17086 parseAtom(breakOnTokenText) {
17087 // The body of an atom is an implicit group, so that things like
17088 // \left(x\right)^2 work correctly.
17089 var base = this.parseGroup("atom", breakOnTokenText); // In text mode, we don't have superscripts or subscripts
17090
17091 if (this.mode === "text") {
17092 return base;
17093 } // Note that base may be empty (i.e. null) at this point.
17094
17095
17096 var superscript;
17097 var subscript;
17098
17099 while (true) {
17100 // Guaranteed in math mode, so eat any spaces first.
17101 this.consumeSpaces(); // Lex the first token
17102
17103 var lex = this.fetch();
17104
17105 if (lex.text === "\\limits" || lex.text === "\\nolimits") {
17106 // We got a limit control
17107 if (base && base.type === "op") {
17108 var limits = lex.text === "\\limits";
17109 base.limits = limits;
17110 base.alwaysHandleSupSub = true;
17111 } else if (base && base.type === "operatorname") {
17112 if (base.alwaysHandleSupSub) {
17113 base.limits = lex.text === "\\limits";
17114 }
17115 } else {
17116 throw new ParseError("Limit controls must follow a math operator", lex);
17117 }
17118
17119 this.consume();
17120 } else if (lex.text === "^") {
17121 // We got a superscript start
17122 if (superscript) {
17123 throw new ParseError("Double superscript", lex);
17124 }
17125
17126 superscript = this.handleSupSubscript("superscript");
17127 } else if (lex.text === "_") {
17128 // We got a subscript start
17129 if (subscript) {
17130 throw new ParseError("Double subscript", lex);
17131 }
17132
17133 subscript = this.handleSupSubscript("subscript");
17134 } else if (lex.text === "'") {
17135 // We got a prime
17136 if (superscript) {
17137 throw new ParseError("Double superscript", lex);
17138 }
17139
17140 var prime = {
17141 type: "textord",
17142 mode: this.mode,
17143 text: "\\prime"
17144 }; // Many primes can be grouped together, so we handle this here
17145
17146 var primes = [prime];
17147 this.consume(); // Keep lexing tokens until we get something that's not a prime
17148
17149 while (this.fetch().text === "'") {
17150 // For each one, add another prime to the list
17151 primes.push(prime);
17152 this.consume();
17153 } // If there's a superscript following the primes, combine that
17154 // superscript in with the primes.
17155
17156
17157 if (this.fetch().text === "^") {
17158 primes.push(this.handleSupSubscript("superscript"));
17159 } // Put everything into an ordgroup as the superscript
17160
17161
17162 superscript = {
17163 type: "ordgroup",
17164 mode: this.mode,
17165 body: primes
17166 };
17167 } else {
17168 // If it wasn't ^, _, or ', stop parsing super/subscripts
17169 break;
17170 }
17171 } // Base must be set if superscript or subscript are set per logic above,
17172 // but need to check here for type check to pass.
17173
17174
17175 if (superscript || subscript) {
17176 // If we got either a superscript or subscript, create a supsub
17177 return {
17178 type: "supsub",
17179 mode: this.mode,
17180 base: base,
17181 sup: superscript,
17182 sub: subscript
17183 };
17184 } else {
17185 // Otherwise return the original body
17186 return base;
17187 }
17188 }
17189 /**
17190 * Parses an entire function, including its base and all of its arguments.
17191 */
17192
17193
17194 parseFunction(breakOnTokenText, name // For determining its context
17195 ) {
17196 var token = this.fetch();
17197 var func = token.text;
17198 var funcData = functions[func];
17199
17200 if (!funcData) {
17201 return null;
17202 }
17203
17204 this.consume(); // consume command token
17205
17206 if (name && name !== "atom" && !funcData.allowedInArgument) {
17207 throw new ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token);
17208 } else if (this.mode === "text" && !funcData.allowedInText) {
17209 throw new ParseError("Can't use function '" + func + "' in text mode", token);
17210 } else if (this.mode === "math" && funcData.allowedInMath === false) {
17211 throw new ParseError("Can't use function '" + func + "' in math mode", token);
17212 }
17213
17214 var {
17215 args,
17216 optArgs
17217 } = this.parseArguments(func, funcData);
17218 return this.callFunction(func, args, optArgs, token, breakOnTokenText);
17219 }
17220 /**
17221 * Call a function handler with a suitable context and arguments.
17222 */
17223
17224
17225 callFunction(name, args, optArgs, token, breakOnTokenText) {
17226 var context = {
17227 funcName: name,
17228 parser: this,
17229 token,
17230 breakOnTokenText
17231 };
17232 var func = functions[name];
17233
17234 if (func && func.handler) {
17235 return func.handler(context, args, optArgs);
17236 } else {
17237 throw new ParseError("No function handler for " + name);
17238 }
17239 }
17240 /**
17241 * Parses the arguments of a function or environment
17242 */
17243
17244
17245 parseArguments(func, // Should look like "\name" or "\begin{name}".
17246 funcData) {
17247 var totalArgs = funcData.numArgs + funcData.numOptionalArgs;
17248
17249 if (totalArgs === 0) {
17250 return {
17251 args: [],
17252 optArgs: []
17253 };
17254 }
17255
17256 var args = [];
17257 var optArgs = [];
17258
17259 for (var i = 0; i < totalArgs; i++) {
17260 var argType = funcData.argTypes && funcData.argTypes[i];
17261 var isOptional = i < funcData.numOptionalArgs;
17262
17263 if (funcData.primitive && argType == null || // \sqrt expands into primitive if optional argument doesn't exist
17264 funcData.type === "sqrt" && i === 1 && optArgs[0] == null) {
17265 argType = "primitive";
17266 }
17267
17268 var arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional);
17269
17270 if (isOptional) {
17271 optArgs.push(arg);
17272 } else if (arg != null) {
17273 args.push(arg);
17274 } else {
17275 // should be unreachable
17276 throw new ParseError("Null argument, please report this as a bug");
17277 }
17278 }
17279
17280 return {
17281 args,
17282 optArgs
17283 };
17284 }
17285 /**
17286 * Parses a group when the mode is changing.
17287 */
17288
17289
17290 parseGroupOfType(name, type, optional) {
17291 switch (type) {
17292 case "color":
17293 return this.parseColorGroup(optional);
17294
17295 case "size":
17296 return this.parseSizeGroup(optional);
17297
17298 case "url":
17299 return this.parseUrlGroup(optional);
17300
17301 case "math":
17302 case "text":
17303 return this.parseArgumentGroup(optional, type);
17304
17305 case "hbox":
17306 {
17307 // hbox argument type wraps the argument in the equivalent of
17308 // \hbox, which is like \text but switching to \textstyle size.
17309 var group = this.parseArgumentGroup(optional, "text");
17310 return group != null ? {
17311 type: "styling",
17312 mode: group.mode,
17313 body: [group],
17314 style: "text" // simulate \textstyle
17315
17316 } : null;
17317 }
17318
17319 case "raw":
17320 {
17321 var token = this.parseStringGroup("raw", optional);
17322 return token != null ? {
17323 type: "raw",
17324 mode: "text",
17325 string: token.text
17326 } : null;
17327 }
17328
17329 case "primitive":
17330 {
17331 if (optional) {
17332 throw new ParseError("A primitive argument cannot be optional");
17333 }
17334
17335 var _group = this.parseGroup(name);
17336
17337 if (_group == null) {
17338 throw new ParseError("Expected group as " + name, this.fetch());
17339 }
17340
17341 return _group;
17342 }
17343
17344 case "original":
17345 case null:
17346 case undefined:
17347 return this.parseArgumentGroup(optional);
17348
17349 default:
17350 throw new ParseError("Unknown group type as " + name, this.fetch());
17351 }
17352 }
17353 /**
17354 * Discard any space tokens, fetching the next non-space token.
17355 */
17356
17357
17358 consumeSpaces() {
17359 while (this.fetch().text === " ") {
17360 this.consume();
17361 }
17362 }
17363 /**
17364 * Parses a group, essentially returning the string formed by the
17365 * brace-enclosed tokens plus some position information.
17366 */
17367
17368
17369 parseStringGroup(modeName, // Used to describe the mode in error messages.
17370 optional) {
17371 var argToken = this.gullet.scanArgument(optional);
17372
17373 if (argToken == null) {
17374 return null;
17375 }
17376
17377 var str = "";
17378 var nextToken;
17379
17380 while ((nextToken = this.fetch()).text !== "EOF") {
17381 str += nextToken.text;
17382 this.consume();
17383 }
17384
17385 this.consume(); // consume the end of the argument
17386
17387 argToken.text = str;
17388 return argToken;
17389 }
17390 /**
17391 * Parses a regex-delimited group: the largest sequence of tokens
17392 * whose concatenated strings match `regex`. Returns the string
17393 * formed by the tokens plus some position information.
17394 */
17395
17396
17397 parseRegexGroup(regex, modeName // Used to describe the mode in error messages.
17398 ) {
17399 var firstToken = this.fetch();
17400 var lastToken = firstToken;
17401 var str = "";
17402 var nextToken;
17403
17404 while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) {
17405 lastToken = nextToken;
17406 str += lastToken.text;
17407 this.consume();
17408 }
17409
17410 if (str === "") {
17411 throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken);
17412 }
17413
17414 return firstToken.range(lastToken, str);
17415 }
17416 /**
17417 * Parses a color description.
17418 */
17419
17420
17421 parseColorGroup(optional) {
17422 var res = this.parseStringGroup("color", optional);
17423
17424 if (res == null) {
17425 return null;
17426 }
17427
17428 var match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text);
17429
17430 if (!match) {
17431 throw new ParseError("Invalid color: '" + res.text + "'", res);
17432 }
17433
17434 var color = match[0];
17435
17436 if (/^[0-9a-f]{6}$/i.test(color)) {
17437 // We allow a 6-digit HTML color spec without a leading "#".
17438 // This follows the xcolor package's HTML color model.
17439 // Predefined color names are all missed by this RegEx pattern.
17440 color = "#" + color;
17441 }
17442
17443 return {
17444 type: "color-token",
17445 mode: this.mode,
17446 color
17447 };
17448 }
17449 /**
17450 * Parses a size specification, consisting of magnitude and unit.
17451 */
17452
17453
17454 parseSizeGroup(optional) {
17455 var res;
17456 var isBlank = false; // don't expand before parseStringGroup
17457
17458 this.gullet.consumeSpaces();
17459
17460 if (!optional && this.gullet.future().text !== "{") {
17461 res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size");
17462 } else {
17463 res = this.parseStringGroup("size", optional);
17464 }
17465
17466 if (!res) {
17467 return null;
17468 }
17469
17470 if (!optional && res.text.length === 0) {
17471 // Because we've tested for what is !optional, this block won't
17472 // affect \kern, \hspace, etc. It will capture the mandatory arguments
17473 // to \genfrac and \above.
17474 res.text = "0pt"; // Enable \above{}
17475
17476 isBlank = true; // This is here specifically for \genfrac
17477 }
17478
17479 var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text);
17480
17481 if (!match) {
17482 throw new ParseError("Invalid size: '" + res.text + "'", res);
17483 }
17484
17485 var data = {
17486 number: +(match[1] + match[2]),
17487 // sign + magnitude, cast to number
17488 unit: match[3]
17489 };
17490
17491 if (!validUnit(data)) {
17492 throw new ParseError("Invalid unit: '" + data.unit + "'", res);
17493 }
17494
17495 return {
17496 type: "size",
17497 mode: this.mode,
17498 value: data,
17499 isBlank
17500 };
17501 }
17502 /**
17503 * Parses an URL, checking escaped letters and allowed protocols,
17504 * and setting the catcode of % as an active character (as in \hyperref).
17505 */
17506
17507
17508 parseUrlGroup(optional) {
17509 this.gullet.lexer.setCatcode("%", 13); // active character
17510
17511 this.gullet.lexer.setCatcode("~", 12); // other character
17512
17513 var res = this.parseStringGroup("url", optional);
17514 this.gullet.lexer.setCatcode("%", 14); // comment character
17515
17516 this.gullet.lexer.setCatcode("~", 13); // active character
17517
17518 if (res == null) {
17519 return null;
17520 } // hyperref package allows backslashes alone in href, but doesn't
17521 // generate valid links in such cases; we interpret this as
17522 // "undefined" behaviour, and keep them as-is. Some browser will
17523 // replace backslashes with forward slashes.
17524
17525
17526 var url = res.text.replace(/\\([#$%&~_^{}])/g, '$1');
17527 return {
17528 type: "url",
17529 mode: this.mode,
17530 url
17531 };
17532 }
17533 /**
17534 * Parses an argument with the mode specified.
17535 */
17536
17537
17538 parseArgumentGroup(optional, mode) {
17539 var argToken = this.gullet.scanArgument(optional);
17540
17541 if (argToken == null) {
17542 return null;
17543 }
17544
17545 var outerMode = this.mode;
17546
17547 if (mode) {
17548 // Switch to specified mode
17549 this.switchMode(mode);
17550 }
17551
17552 this.gullet.beginGroup();
17553 var expression = this.parseExpression(false, "EOF"); // TODO: find an alternative way to denote the end
17554
17555 this.expect("EOF"); // expect the end of the argument
17556
17557 this.gullet.endGroup();
17558 var result = {
17559 type: "ordgroup",
17560 mode: this.mode,
17561 loc: argToken.loc,
17562 body: expression
17563 };
17564
17565 if (mode) {
17566 // Switch mode back
17567 this.switchMode(outerMode);
17568 }
17569
17570 return result;
17571 }
17572 /**
17573 * Parses an ordinary group, which is either a single nucleus (like "x")
17574 * or an expression in braces (like "{x+y}") or an implicit group, a group
17575 * that starts at the current position, and ends right before a higher explicit
17576 * group ends, or at EOF.
17577 */
17578
17579
17580 parseGroup(name, // For error reporting.
17581 breakOnTokenText) {
17582 var firstToken = this.fetch();
17583 var text = firstToken.text;
17584 var result; // Try to parse an open brace or \begingroup
17585
17586 if (text === "{" || text === "\\begingroup") {
17587 this.consume();
17588 var groupEnd = text === "{" ? "}" : "\\endgroup";
17589 this.gullet.beginGroup(); // If we get a brace, parse an expression
17590
17591 var expression = this.parseExpression(false, groupEnd);
17592 var lastToken = this.fetch();
17593 this.expect(groupEnd); // Check that we got a matching closing brace
17594
17595 this.gullet.endGroup();
17596 result = {
17597 type: "ordgroup",
17598 mode: this.mode,
17599 loc: SourceLocation.range(firstToken, lastToken),
17600 body: expression,
17601 // A group formed by \begingroup...\endgroup is a semi-simple group
17602 // which doesn't affect spacing in math mode, i.e., is transparent.
17603 // https://tex.stackexchange.com/questions/1930/when-should-one-
17604 // use-begingroup-instead-of-bgroup
17605 semisimple: text === "\\begingroup" || undefined
17606 };
17607 } else {
17608 // If there exists a function with this name, parse the function.
17609 // Otherwise, just return a nucleus
17610 result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol();
17611
17612 if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) {
17613 if (this.settings.throwOnError) {
17614 throw new ParseError("Undefined control sequence: " + text, firstToken);
17615 }
17616
17617 result = this.formatUnsupportedCmd(text);
17618 this.consume();
17619 }
17620 }
17621
17622 return result;
17623 }
17624 /**
17625 * Form ligature-like combinations of characters for text mode.
17626 * This includes inputs like "--", "---", "``" and "''".
17627 * The result will simply replace multiple textord nodes with a single
17628 * character in each value by a single textord node having multiple
17629 * characters in its value. The representation is still ASCII source.
17630 * The group will be modified in place.
17631 */
17632
17633
17634 formLigatures(group) {
17635 var n = group.length - 1;
17636
17637 for (var i = 0; i < n; ++i) {
17638 var a = group[i]; // $FlowFixMe: Not every node type has a `text` property.
17639
17640 var v = a.text;
17641
17642 if (v === "-" && group[i + 1].text === "-") {
17643 if (i + 1 < n && group[i + 2].text === "-") {
17644 group.splice(i, 3, {
17645 type: "textord",
17646 mode: "text",
17647 loc: SourceLocation.range(a, group[i + 2]),
17648 text: "---"
17649 });
17650 n -= 2;
17651 } else {
17652 group.splice(i, 2, {
17653 type: "textord",
17654 mode: "text",
17655 loc: SourceLocation.range(a, group[i + 1]),
17656 text: "--"
17657 });
17658 n -= 1;
17659 }
17660 }
17661
17662 if ((v === "'" || v === "`") && group[i + 1].text === v) {
17663 group.splice(i, 2, {
17664 type: "textord",
17665 mode: "text",
17666 loc: SourceLocation.range(a, group[i + 1]),
17667 text: v + v
17668 });
17669 n -= 1;
17670 }
17671 }
17672 }
17673 /**
17674 * Parse a single symbol out of the string. Here, we handle single character
17675 * symbols and special functions like \verb.
17676 */
17677
17678
17679 parseSymbol() {
17680 var nucleus = this.fetch();
17681 var text = nucleus.text;
17682
17683 if (/^\\verb[^a-zA-Z]/.test(text)) {
17684 this.consume();
17685 var arg = text.slice(5);
17686 var star = arg.charAt(0) === "*";
17687
17688 if (star) {
17689 arg = arg.slice(1);
17690 } // Lexer's tokenRegex is constructed to always have matching
17691 // first/last characters.
17692
17693
17694 if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) {
17695 throw new ParseError("\\verb assertion failed --\n please report what input caused this bug");
17696 }
17697
17698 arg = arg.slice(1, -1); // remove first and last char
17699
17700 return {
17701 type: "verb",
17702 mode: "text",
17703 body: arg,
17704 star
17705 };
17706 } // At this point, we should have a symbol, possibly with accents.
17707 // First expand any accented base symbol according to unicodeSymbols.
17708
17709
17710 if (unicodeSymbols.hasOwnProperty(text[0]) && !symbols[this.mode][text[0]]) {
17711 // This behavior is not strict (XeTeX-compatible) in math mode.
17712 if (this.settings.strict && this.mode === "math") {
17713 this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
17714 }
17715
17716 text = unicodeSymbols[text[0]] + text.substr(1);
17717 } // Strip off any combining characters
17718
17719
17720 var match = combiningDiacriticalMarksEndRegex.exec(text);
17721
17722 if (match) {
17723 text = text.substring(0, match.index);
17724
17725 if (text === 'i') {
17726 text = '\u0131'; // dotless i, in math and text mode
17727 } else if (text === 'j') {
17728 text = '\u0237'; // dotless j, in math and text mode
17729 }
17730 } // Recognize base symbol
17731
17732
17733 var symbol;
17734
17735 if (symbols[this.mode][text]) {
17736 if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) {
17737 this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
17738 }
17739
17740 var group = symbols[this.mode][text].group;
17741 var loc = SourceLocation.range(nucleus);
17742 var s;
17743
17744 if (ATOMS.hasOwnProperty(group)) {
17745 // $FlowFixMe
17746 var family = group;
17747 s = {
17748 type: "atom",
17749 mode: this.mode,
17750 family,
17751 loc,
17752 text
17753 };
17754 } else {
17755 // $FlowFixMe
17756 s = {
17757 type: group,
17758 mode: this.mode,
17759 loc,
17760 text
17761 };
17762 } // $FlowFixMe
17763
17764
17765 symbol = s;
17766 } else if (text.charCodeAt(0) >= 0x80) {
17767 // no symbol for e.g. ^
17768 if (this.settings.strict) {
17769 if (!supportedCodepoint(text.charCodeAt(0))) {
17770 this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus);
17771 } else if (this.mode === "math") {
17772 this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus);
17773 }
17774 } // All nonmathematical Unicode characters are rendered as if they
17775 // are in text mode (wrapped in \text) because that's what it
17776 // takes to render them in LaTeX. Setting `mode: this.mode` is
17777 // another natural choice (the user requested math mode), but
17778 // this makes it more difficult for getCharacterMetrics() to
17779 // distinguish Unicode characters without metrics and those for
17780 // which we want to simulate the letter M.
17781
17782
17783 symbol = {
17784 type: "textord",
17785 mode: "text",
17786 loc: SourceLocation.range(nucleus),
17787 text
17788 };
17789 } else {
17790 return null; // EOF, ^, _, {, }, etc.
17791 }
17792
17793 this.consume(); // Transform combining characters into accents
17794
17795 if (match) {
17796 for (var i = 0; i < match[0].length; i++) {
17797 var accent = match[0][i];
17798
17799 if (!unicodeAccents[accent]) {
17800 throw new ParseError("Unknown accent ' " + accent + "'", nucleus);
17801 }
17802
17803 var command = unicodeAccents[accent][this.mode] || unicodeAccents[accent].text;
17804
17805 if (!command) {
17806 throw new ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus);
17807 }
17808
17809 symbol = {
17810 type: "accent",
17811 mode: this.mode,
17812 loc: SourceLocation.range(nucleus),
17813 label: command,
17814 isStretchy: false,
17815 isShifty: true,
17816 // $FlowFixMe
17817 base: symbol
17818 };
17819 }
17820 } // $FlowFixMe
17821
17822
17823 return symbol;
17824 }
17825
17826}
17827Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"];
17828
17829/**
17830 * Provides a single function for parsing an expression using a Parser
17831 * TODO(emily): Remove this
17832 */
17833
17834/**
17835 * Parses an expression using a Parser, then returns the parsed result.
17836 */
17837var parseTree = function parseTree(toParse, settings) {
17838 if (!(typeof toParse === 'string' || toParse instanceof String)) {
17839 throw new TypeError('KaTeX can only parse string typed expression');
17840 }
17841
17842 var parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
17843
17844 delete parser.gullet.macros.current["\\df@tag"];
17845 var tree = parser.parse(); // Prevent a color definition from persisting between calls to katex.render().
17846
17847 delete parser.gullet.macros.current["\\current@color"];
17848 delete parser.gullet.macros.current["\\color"]; // If the input used \tag, it will set the \df@tag macro to the tag.
17849 // In this case, we separately parse the tag and wrap the tree.
17850
17851 if (parser.gullet.macros.get("\\df@tag")) {
17852 if (!settings.displayMode) {
17853 throw new ParseError("\\tag works only in display equations");
17854 }
17855
17856 tree = [{
17857 type: "tag",
17858 mode: "text",
17859 body: tree,
17860 tag: parser.subparse([new Token("\\df@tag")])
17861 }];
17862 }
17863
17864 return tree;
17865};
17866
17867/* eslint no-console:0 */
17868
17869/**
17870 * Parse and build an expression, and place that expression in the DOM node
17871 * given.
17872 */
17873var render = function render(expression, baseNode, options) {
17874 baseNode.textContent = "";
17875 var node = renderToDomTree(expression, options).toNode();
17876 baseNode.appendChild(node);
17877}; // KaTeX's styles don't work properly in quirks mode. Print out an error, and
17878// disable rendering.
17879
17880
17881if (typeof document !== "undefined") {
17882 if (document.compatMode !== "CSS1Compat") {
17883 typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype.");
17884
17885 render = function render() {
17886 throw new ParseError("KaTeX doesn't work in quirks mode.");
17887 };
17888 }
17889}
17890/**
17891 * Parse and build an expression, and return the markup for that.
17892 */
17893
17894
17895var renderToString = function renderToString(expression, options) {
17896 var markup = renderToDomTree(expression, options).toMarkup();
17897 return markup;
17898};
17899/**
17900 * Parse an expression and return the parse tree.
17901 */
17902
17903
17904var generateParseTree = function generateParseTree(expression, options) {
17905 var settings = new Settings(options);
17906 return parseTree(expression, settings);
17907};
17908/**
17909 * If the given error is a KaTeX ParseError and options.throwOnError is false,
17910 * renders the invalid LaTeX as a span with hover title giving the KaTeX
17911 * error message. Otherwise, simply throws the error.
17912 */
17913
17914
17915var renderError = function renderError(error, expression, options) {
17916 if (options.throwOnError || !(error instanceof ParseError)) {
17917 throw error;
17918 }
17919
17920 var node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]);
17921 node.setAttribute("title", error.toString());
17922 node.setAttribute("style", "color:" + options.errorColor);
17923 return node;
17924};
17925/**
17926 * Generates and returns the katex build tree. This is used for advanced
17927 * use cases (like rendering to custom output).
17928 */
17929
17930
17931var renderToDomTree = function renderToDomTree(expression, options) {
17932 var settings = new Settings(options);
17933
17934 try {
17935 var tree = parseTree(expression, settings);
17936 return buildTree(tree, expression, settings);
17937 } catch (error) {
17938 return renderError(error, expression, settings);
17939 }
17940};
17941/**
17942 * Generates and returns the katex build tree, with just HTML (no MathML).
17943 * This is used for advanced use cases (like rendering to custom output).
17944 */
17945
17946
17947var renderToHTMLTree = function renderToHTMLTree(expression, options) {
17948 var settings = new Settings(options);
17949
17950 try {
17951 var tree = parseTree(expression, settings);
17952 return buildHTMLTree(tree, expression, settings);
17953 } catch (error) {
17954 return renderError(error, expression, settings);
17955 }
17956};
17957
17958var katex = {
17959 /**
17960 * Current KaTeX version
17961 */
17962 version: "0.15.3",
17963
17964 /**
17965 * Renders the given LaTeX into an HTML+MathML combination, and adds
17966 * it as a child to the specified DOM node.
17967 */
17968 render,
17969
17970 /**
17971 * Renders the given LaTeX into an HTML+MathML combination string,
17972 * for sending to the client.
17973 */
17974 renderToString,
17975
17976 /**
17977 * KaTeX error, usually during parsing.
17978 */
17979 ParseError,
17980
17981 /**
17982 * The shema of Settings
17983 */
17984 SETTINGS_SCHEMA,
17985
17986 /**
17987 * Parses the given LaTeX into KaTeX's internal parse tree structure,
17988 * without rendering to HTML or MathML.
17989 *
17990 * NOTE: This method is not currently recommended for public use.
17991 * The internal tree representation is unstable and is very likely
17992 * to change. Use at your own risk.
17993 */
17994 __parse: generateParseTree,
17995
17996 /**
17997 * Renders the given LaTeX into an HTML+MathML internal DOM tree
17998 * representation, without flattening that representation to a string.
17999 *
18000 * NOTE: This method is not currently recommended for public use.
18001 * The internal tree representation is unstable and is very likely
18002 * to change. Use at your own risk.
18003 */
18004 __renderToDomTree: renderToDomTree,
18005
18006 /**
18007 * Renders the given LaTeX into an HTML internal DOM tree representation,
18008 * without MathML and without flattening that representation to a string.
18009 *
18010 * NOTE: This method is not currently recommended for public use.
18011 * The internal tree representation is unstable and is very likely
18012 * to change. Use at your own risk.
18013 */
18014 __renderToHTMLTree: renderToHTMLTree,
18015
18016 /**
18017 * extends internal font metrics object with a new object
18018 * each key in the new object represents a font name
18019 */
18020 __setFontMetrics: setFontMetrics,
18021
18022 /**
18023 * adds a new symbol to builtin symbols table
18024 */
18025 __defineSymbol: defineSymbol,
18026
18027 /**
18028 * adds a new macro to builtin macro list
18029 */
18030 __defineMacro: defineMacro,
18031
18032 /**
18033 * Expose the dom tree node types, which can be useful for type checking nodes.
18034 *
18035 * NOTE: This method is not currently recommended for public use.
18036 * The internal tree representation is unstable and is very likely
18037 * to change. Use at your own risk.
18038 */
18039 __domTree: {
18040 Span,
18041 Anchor,
18042 SymbolNode,
18043 SvgNode,
18044 PathNode,
18045 LineNode
18046 }
18047};
18048
18049export { katex as default };