katex.mjs (583216B)
1 /** 2 * Lexing or parsing positional information for error reporting. 3 * This object is immutable. 4 */ 5 class SourceLocation { 6 // The + prefix indicates that these fields aren't writeable 7 // Lexer holding the input string. 8 // Start offset, zero-based inclusive. 9 // End offset, zero-based exclusive. 10 constructor(lexer, start, end) { 11 this.lexer = void 0; 12 this.start = void 0; 13 this.end = void 0; 14 this.lexer = lexer; 15 this.start = start; 16 this.end = end; 17 } 18 /** 19 * Merges two `SourceLocation`s from location providers, given they are 20 * provided in order of appearance. 21 * - Returns the first one's location if only the first is provided. 22 * - Returns a merged range of the first and the last if both are provided 23 * and their lexers match. 24 * - Otherwise, returns null. 25 */ 26 27 28 static range(first, second) { 29 if (!second) { 30 return first && first.loc; 31 } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { 32 return null; 33 } else { 34 return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); 35 } 36 } 37 38 } 39 40 /** 41 * Interface required to break circular dependency between Token, Lexer, and 42 * ParseError. 43 */ 44 45 /** 46 * The resulting token returned from `lex`. 47 * 48 * It consists of the token text plus some position information. 49 * The position information is essentially a range in an input string, 50 * but instead of referencing the bare input string, we refer to the lexer. 51 * That way it is possible to attach extra metadata to the input string, 52 * like for example a file name or similar. 53 * 54 * The position information is optional, so it is OK to construct synthetic 55 * tokens if appropriate. Not providing available position information may 56 * lead to degraded error reporting, though. 57 */ 58 class Token { 59 // don't expand the token 60 // used in \noexpand 61 constructor(text, // the text of this token 62 loc) { 63 this.text = void 0; 64 this.loc = void 0; 65 this.noexpand = void 0; 66 this.treatAsRelax = void 0; 67 this.text = text; 68 this.loc = loc; 69 } 70 /** 71 * Given a pair of tokens (this and endToken), compute a `Token` encompassing 72 * the whole input range enclosed by these two. 73 */ 74 75 76 range(endToken, // last token of the range, inclusive 77 text) { 78 return new Token(text, SourceLocation.range(this, endToken)); 79 } 80 81 } 82 83 /** 84 * This is the ParseError class, which is the main error thrown by KaTeX 85 * functions when something has gone wrong. This is used to distinguish internal 86 * errors from errors in the expression that the user provided. 87 * 88 * If possible, a caller should provide a Token or ParseNode with information 89 * about where in the source string the problem occurred. 90 */ 91 class ParseError { 92 // Error position based on passed-in Token or ParseNode. 93 constructor(message, // The error message 94 token) { 95 this.position = void 0; 96 var error = "KaTeX parse error: " + message; 97 var start; 98 var loc = token && token.loc; 99 100 if (loc && loc.start <= loc.end) { 101 // If we have the input and a position, make the error a bit fancier 102 // Get the input 103 var input = loc.lexer.input; // Prepend some information 104 105 start = loc.start; 106 var end = loc.end; 107 108 if (start === input.length) { 109 error += " at end of input: "; 110 } else { 111 error += " at position " + (start + 1) + ": "; 112 } // Underline token in question using combining underscores 113 114 115 var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error 116 117 var left; 118 119 if (start > 15) { 120 left = "…" + input.slice(start - 15, start); 121 } else { 122 left = input.slice(0, start); 123 } 124 125 var right; 126 127 if (end + 15 < input.length) { 128 right = input.slice(end, end + 15) + "…"; 129 } else { 130 right = input.slice(end); 131 } 132 133 error += left + underlined + right; 134 } // Some hackery to make ParseError a prototype of Error 135 // See http://stackoverflow.com/a/8460753 136 137 138 var self = new Error(error); 139 self.name = "ParseError"; // $FlowFixMe 140 141 self.__proto__ = ParseError.prototype; // $FlowFixMe 142 143 self.position = start; 144 return self; 145 } 146 147 } // $FlowFixMe More hackery 148 149 150 ParseError.prototype.__proto__ = Error.prototype; 151 152 /** 153 * This file contains a list of utility functions which are useful in other 154 * files. 155 */ 156 157 /** 158 * Return whether an element is contained in a list 159 */ 160 var contains = function contains(list, elem) { 161 return list.indexOf(elem) !== -1; 162 }; 163 /** 164 * Provide a default value if a setting is undefined 165 * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022. 166 */ 167 168 169 var deflt = function deflt(setting, defaultIfUndefined) { 170 return setting === undefined ? defaultIfUndefined : setting; 171 }; // hyphenate and escape adapted from Facebook's React under Apache 2 license 172 173 174 var uppercase = /([A-Z])/g; 175 176 var hyphenate = function hyphenate(str) { 177 return str.replace(uppercase, "-$1").toLowerCase(); 178 }; 179 180 var ESCAPE_LOOKUP = { 181 "&": "&", 182 ">": ">", 183 "<": "<", 184 "\"": """, 185 "'": "'" 186 }; 187 var ESCAPE_REGEX = /[&><"']/g; 188 /** 189 * Escapes text to prevent scripting attacks. 190 */ 191 192 function escape(text) { 193 return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]); 194 } 195 /** 196 * Sometimes we want to pull out the innermost element of a group. In most 197 * cases, this will just be the group itself, but when ordgroups and colors have 198 * a single element, we want to pull that out. 199 */ 200 201 202 var getBaseElem = function getBaseElem(group) { 203 if (group.type === "ordgroup") { 204 if (group.body.length === 1) { 205 return getBaseElem(group.body[0]); 206 } else { 207 return group; 208 } 209 } else if (group.type === "color") { 210 if (group.body.length === 1) { 211 return getBaseElem(group.body[0]); 212 } else { 213 return group; 214 } 215 } else if (group.type === "font") { 216 return getBaseElem(group.body); 217 } else { 218 return group; 219 } 220 }; 221 /** 222 * TeXbook algorithms often reference "character boxes", which are simply groups 223 * with a single character in them. To decide if something is a character box, 224 * we find its innermost group, and see if it is a single character. 225 */ 226 227 228 var isCharacterBox = function isCharacterBox(group) { 229 var baseElem = getBaseElem(group); // These are all they types of groups which hold single characters 230 231 return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom"; 232 }; 233 234 var assert = function assert(value) { 235 if (!value) { 236 throw new Error('Expected non-null, but got ' + String(value)); 237 } 238 239 return value; 240 }; 241 /** 242 * Return the protocol of a URL, or "_relative" if the URL does not specify a 243 * protocol (and thus is relative). 244 */ 245 246 var protocolFromUrl = function protocolFromUrl(url) { 247 var protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); 248 return protocol != null ? protocol[1] : "_relative"; 249 }; 250 var utils = { 251 contains, 252 deflt, 253 escape, 254 hyphenate, 255 getBaseElem, 256 isCharacterBox, 257 protocolFromUrl 258 }; 259 260 /* eslint no-console:0 */ 261 262 /** 263 * The main Settings object 264 * 265 * The current options stored are: 266 * - displayMode: Whether the expression should be typeset as inline math 267 * (false, the default), meaning that the math starts in 268 * \textstyle and is placed in an inline-block); or as display 269 * math (true), meaning that the math starts in \displaystyle 270 * and is placed in a block with vertical margin. 271 */ 272 class Settings { 273 constructor(options) { 274 this.displayMode = void 0; 275 this.output = void 0; 276 this.leqno = void 0; 277 this.fleqn = void 0; 278 this.throwOnError = void 0; 279 this.errorColor = void 0; 280 this.macros = void 0; 281 this.minRuleThickness = void 0; 282 this.colorIsTextColor = void 0; 283 this.strict = void 0; 284 this.trust = void 0; 285 this.maxSize = void 0; 286 this.maxExpand = void 0; 287 this.globalGroup = void 0; 288 // allow null options 289 options = options || {}; 290 this.displayMode = utils.deflt(options.displayMode, false); 291 this.output = utils.deflt(options.output, "htmlAndMathml"); 292 this.leqno = utils.deflt(options.leqno, false); 293 this.fleqn = utils.deflt(options.fleqn, false); 294 this.throwOnError = utils.deflt(options.throwOnError, true); 295 this.errorColor = utils.deflt(options.errorColor, "#cc0000"); 296 this.macros = options.macros || {}; 297 this.minRuleThickness = Math.max(0, utils.deflt(options.minRuleThickness, 0)); 298 this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); 299 this.strict = utils.deflt(options.strict, "warn"); 300 this.trust = utils.deflt(options.trust, false); 301 this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity)); 302 this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); 303 this.globalGroup = utils.deflt(options.globalGroup, false); 304 } 305 /** 306 * Report nonstrict (non-LaTeX-compatible) input. 307 * Can safely not be called if `this.strict` is false in JavaScript. 308 */ 309 310 311 reportNonstrict(errorCode, errorMsg, token) { 312 var strict = this.strict; 313 314 if (typeof strict === "function") { 315 // Allow return value of strict function to be boolean or string 316 // (or null/undefined, meaning no further processing). 317 strict = strict(errorCode, errorMsg, token); 318 } 319 320 if (!strict || strict === "ignore") { 321 return; 322 } else if (strict === true || strict === "error") { 323 throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token); 324 } else if (strict === "warn") { 325 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]")); 326 } else { 327 // won't happen in type-safe code 328 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]")); 329 } 330 } 331 /** 332 * Check whether to apply strict (LaTeX-adhering) behavior for unusual 333 * input (like `\\`). Unlike `nonstrict`, will not throw an error; 334 * instead, "error" translates to a return value of `true`, while "ignore" 335 * translates to a return value of `false`. May still print a warning: 336 * "warn" prints a warning and returns `false`. 337 * This is for the second category of `errorCode`s listed in the README. 338 */ 339 340 341 useStrictBehavior(errorCode, errorMsg, token) { 342 var strict = this.strict; 343 344 if (typeof strict === "function") { 345 // Allow return value of strict function to be boolean or string 346 // (or null/undefined, meaning no further processing). 347 // But catch any exceptions thrown by function, treating them 348 // like "error". 349 try { 350 strict = strict(errorCode, errorMsg, token); 351 } catch (error) { 352 strict = "error"; 353 } 354 } 355 356 if (!strict || strict === "ignore") { 357 return false; 358 } else if (strict === true || strict === "error") { 359 return true; 360 } else if (strict === "warn") { 361 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]")); 362 return false; 363 } else { 364 // won't happen in type-safe code 365 typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]")); 366 return false; 367 } 368 } 369 /** 370 * Check whether to test potentially dangerous input, and return 371 * `true` (trusted) or `false` (untrusted). The sole argument `context` 372 * should be an object with `command` field specifying the relevant LaTeX 373 * command (as a string starting with `\`), and any other arguments, etc. 374 * If `context` has a `url` field, a `protocol` field will automatically 375 * get added by this function (changing the specified object). 376 */ 377 378 379 isTrusted(context) { 380 if (context.url && !context.protocol) { 381 context.protocol = utils.protocolFromUrl(context.url); 382 } 383 384 var trust = typeof this.trust === "function" ? this.trust(context) : this.trust; 385 return Boolean(trust); 386 } 387 388 } 389 390 /** 391 * This file contains information and classes for the various kinds of styles 392 * used in TeX. It provides a generic `Style` class, which holds information 393 * about a specific style. It then provides instances of all the different kinds 394 * of styles possible, and provides functions to move between them and get 395 * information about them. 396 */ 397 398 /** 399 * The main style class. Contains a unique id for the style, a size (which is 400 * the same for cramped and uncramped version of a style), and a cramped flag. 401 */ 402 class Style { 403 constructor(id, size, cramped) { 404 this.id = void 0; 405 this.size = void 0; 406 this.cramped = void 0; 407 this.id = id; 408 this.size = size; 409 this.cramped = cramped; 410 } 411 /** 412 * Get the style of a superscript given a base in the current style. 413 */ 414 415 416 sup() { 417 return styles[sup[this.id]]; 418 } 419 /** 420 * Get the style of a subscript given a base in the current style. 421 */ 422 423 424 sub() { 425 return styles[sub[this.id]]; 426 } 427 /** 428 * Get the style of a fraction numerator given the fraction in the current 429 * style. 430 */ 431 432 433 fracNum() { 434 return styles[fracNum[this.id]]; 435 } 436 /** 437 * Get the style of a fraction denominator given the fraction in the current 438 * style. 439 */ 440 441 442 fracDen() { 443 return styles[fracDen[this.id]]; 444 } 445 /** 446 * Get the cramped version of a style (in particular, cramping a cramped style 447 * doesn't change the style). 448 */ 449 450 451 cramp() { 452 return styles[cramp[this.id]]; 453 } 454 /** 455 * Get a text or display version of this style. 456 */ 457 458 459 text() { 460 return styles[text[this.id]]; 461 } 462 /** 463 * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle) 464 */ 465 466 467 isTight() { 468 return this.size >= 2; 469 } 470 471 } // Export an interface for type checking, but don't expose the implementation. 472 // This way, no more styles can be generated. 473 474 475 // IDs of the different styles 476 var D = 0; 477 var Dc = 1; 478 var T = 2; 479 var Tc = 3; 480 var S = 4; 481 var Sc = 5; 482 var SS = 6; 483 var SSc = 7; // Instances of the different styles 484 485 var styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)]; // Lookup tables for switching from one style to another 486 487 var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; 488 var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; 489 var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; 490 var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; 491 var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; 492 var text = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles. 493 494 var Style$1 = { 495 DISPLAY: styles[D], 496 TEXT: styles[T], 497 SCRIPT: styles[S], 498 SCRIPTSCRIPT: styles[SS] 499 }; 500 501 /* 502 * This file defines the Unicode scripts and script families that we 503 * support. To add new scripts or families, just add a new entry to the 504 * scriptData array below. Adding scripts to the scriptData array allows 505 * characters from that script to appear in \text{} environments. 506 */ 507 508 /** 509 * Each script or script family has a name and an array of blocks. 510 * Each block is an array of two numbers which specify the start and 511 * end points (inclusive) of a block of Unicode codepoints. 512 */ 513 514 /** 515 * Unicode block data for the families of scripts we support in \text{}. 516 * Scripts only need to appear here if they do not have font metrics. 517 */ 518 var scriptData = [{ 519 // Latin characters beyond the Latin-1 characters we have metrics for. 520 // Needed for Czech, Hungarian and Turkish text, for example. 521 name: 'latin', 522 blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B 523 [0x0300, 0x036f] // Combining Diacritical marks 524 ] 525 }, { 526 // The Cyrillic script used by Russian and related languages. 527 // A Cyrillic subset used to be supported as explicitly defined 528 // symbols in symbols.js 529 name: 'cyrillic', 530 blocks: [[0x0400, 0x04ff]] 531 }, { 532 // Armenian 533 name: 'armenian', 534 blocks: [[0x0530, 0x058F]] 535 }, { 536 // The Brahmic scripts of South and Southeast Asia 537 // Devanagari (0900–097F) 538 // Bengali (0980–09FF) 539 // Gurmukhi (0A00–0A7F) 540 // Gujarati (0A80–0AFF) 541 // Oriya (0B00–0B7F) 542 // Tamil (0B80–0BFF) 543 // Telugu (0C00–0C7F) 544 // Kannada (0C80–0CFF) 545 // Malayalam (0D00–0D7F) 546 // Sinhala (0D80–0DFF) 547 // Thai (0E00–0E7F) 548 // Lao (0E80–0EFF) 549 // Tibetan (0F00–0FFF) 550 // Myanmar (1000–109F) 551 name: 'brahmic', 552 blocks: [[0x0900, 0x109F]] 553 }, { 554 name: 'georgian', 555 blocks: [[0x10A0, 0x10ff]] 556 }, { 557 // Chinese and Japanese. 558 // The "k" in cjk is for Korean, but we've separated Korean out 559 name: "cjk", 560 blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana 561 [0x4E00, 0x9FAF], // CJK ideograms 562 [0xFF00, 0xFF60] // Fullwidth punctuation 563 // TODO: add halfwidth Katakana and Romanji glyphs 564 ] 565 }, { 566 // Korean 567 name: 'hangul', 568 blocks: [[0xAC00, 0xD7AF]] 569 }]; 570 /** 571 * Given a codepoint, return the name of the script or script family 572 * it is from, or null if it is not part of a known block 573 */ 574 575 function scriptFromCodepoint(codepoint) { 576 for (var i = 0; i < scriptData.length; i++) { 577 var script = scriptData[i]; 578 579 for (var _i = 0; _i < script.blocks.length; _i++) { 580 var block = script.blocks[_i]; 581 582 if (codepoint >= block[0] && codepoint <= block[1]) { 583 return script.name; 584 } 585 } 586 } 587 588 return null; 589 } 590 /** 591 * A flattened version of all the supported blocks in a single array. 592 * This is an optimization to make supportedCodepoint() fast. 593 */ 594 595 var allBlocks = []; 596 scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b))); 597 /** 598 * Given a codepoint, return true if it falls within one of the 599 * scripts or script families defined above and false otherwise. 600 * 601 * Micro benchmarks shows that this is faster than 602 * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() 603 * in Firefox, Chrome and Node. 604 */ 605 606 function supportedCodepoint(codepoint) { 607 for (var i = 0; i < allBlocks.length; i += 2) { 608 if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { 609 return true; 610 } 611 } 612 613 return false; 614 } 615 616 /** 617 * This file provides support to domTree.js and delimiter.js. 618 * It's a storehouse of path geometry for SVG images. 619 */ 620 // In all paths below, the viewBox-to-em scale is 1000:1. 621 var hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping. 622 // The viniculum of a \sqrt can be made thicker by a KaTeX rendering option. 623 // Think of variable extraViniculum as two detours in the SVG path. 624 // The detour begins at the lower left of the area labeled extraViniculum below. 625 // The detour proceeds one extraViniculum distance up and slightly to the right, 626 // displacing the radiused corner between surd and viniculum. The radius is 627 // traversed as usual, then the detour resumes. It goes right, to the end of 628 // the very long viniculumn, then down one extraViniculum distance, 629 // after which it resumes regular path geometry for the radical. 630 631 /* viniculum 632 / 633 /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum 634 / █████████████████████←0.04em (40 unit) std viniculum thickness 635 / / 636 / / 637 / /\ 638 / / surd 639 */ 640 641 var sqrtMain = function sqrtMain(extraViniculum, hLinePad) { 642 // sqrtMain path geometry is from glyph U221A in the font KaTeX Main 643 return "M95," + (622 + extraViniculum + hLinePad) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + extraViniculum / 2.075 + " -" + extraViniculum + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + extraViniculum) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z"; 644 }; 645 646 var sqrtSize1 = function sqrtSize1(extraViniculum, hLinePad) { 647 // size1 is from glyph U221A in the font KaTeX_Size1-Regular 648 return "M263," + (601 + extraViniculum + hLinePad) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + extraViniculum / 2.084 + " -" + extraViniculum + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + extraViniculum) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z"; 649 }; 650 651 var sqrtSize2 = function sqrtSize2(extraViniculum, hLinePad) { 652 // size2 is from glyph U221A in the font KaTeX_Size2-Regular 653 return "M983 " + (10 + extraViniculum + hLinePad) + "\nl" + extraViniculum / 3.13 + " -" + extraViniculum + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + extraViniculum) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z"; 654 }; 655 656 var sqrtSize3 = function sqrtSize3(extraViniculum, hLinePad) { 657 // size3 is from glyph U221A in the font KaTeX_Size3-Regular 658 return "M424," + (2398 + extraViniculum + hLinePad) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + extraViniculum / 4.223 + " -" + extraViniculum + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + extraViniculum) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + extraViniculum) + " " + hLinePad + "\nh400000v" + (40 + extraViniculum) + "h-400000z"; 659 }; 660 661 var sqrtSize4 = function sqrtSize4(extraViniculum, hLinePad) { 662 // size4 is from glyph U221A in the font KaTeX_Size4-Regular 663 return "M473," + (2713 + extraViniculum + hLinePad) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + extraViniculum / 5.298 + " -" + extraViniculum + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + extraViniculum) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "H1017.7z"; 664 }; 665 666 var phasePath = function phasePath(y) { 667 var x = y / 2; // x coordinate at top of angle 668 669 return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z"; 670 }; 671 672 var sqrtTall = function sqrtTall(extraViniculum, hLinePad, viewBoxHeight) { 673 // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular 674 // One path edge has a variable length. It runs vertically from the viniculumn 675 // to a point near (14 units) the bottom of the surd. The viniculum 676 // is normally 40 units thick. So the length of the line in question is: 677 var vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum; 678 return "M702 " + (extraViniculum + hLinePad) + "H400000" + (40 + extraViniculum) + "\nH742v" + vertSegment + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + hLinePad + "H400000v" + (40 + extraViniculum) + "H742z"; 679 }; 680 681 var sqrtPath = function sqrtPath(size, extraViniculum, viewBoxHeight) { 682 extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox. 683 684 var path = ""; 685 686 switch (size) { 687 case "sqrtMain": 688 path = sqrtMain(extraViniculum, hLinePad); 689 break; 690 691 case "sqrtSize1": 692 path = sqrtSize1(extraViniculum, hLinePad); 693 break; 694 695 case "sqrtSize2": 696 path = sqrtSize2(extraViniculum, hLinePad); 697 break; 698 699 case "sqrtSize3": 700 path = sqrtSize3(extraViniculum, hLinePad); 701 break; 702 703 case "sqrtSize4": 704 path = sqrtSize4(extraViniculum, hLinePad); 705 break; 706 707 case "sqrtTall": 708 path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight); 709 } 710 711 return path; 712 }; 713 var innerPath = function innerPath(name, height) { 714 // The inner part of stretchy tall delimiters 715 switch (name) { 716 case "\u239c": 717 return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z"; 718 719 case "\u2223": 720 return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z"; 721 722 case "\u2225": 723 return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z" + ("M367 0 H410 V" + height + " H367z M367 0 H410 V" + height + " H367z"); 724 725 case "\u239f": 726 return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z"; 727 728 case "\u23a2": 729 return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z"; 730 731 case "\u23a5": 732 return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z"; 733 734 case "\u23aa": 735 return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z"; 736 737 case "\u23d0": 738 return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z"; 739 740 case "\u2016": 741 return "M257 0 H300 V" + height + " H257z M257 0 H300 V" + height + " H257z" + ("M478 0 H521 V" + height + " H478z M478 0 H521 V" + height + " H478z"); 742 743 default: 744 return ""; 745 } 746 }; 747 var path = { 748 // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main 749 doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z", 750 // doublerightarrow is from glyph U+21D2 in font KaTeX Main 751 doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z", 752 // leftarrow is from glyph U+2190 in font KaTeX Main 753 leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z", 754 // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular 755 leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z", 756 leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z", 757 // overgroup is from the MnSymbol package (public domain) 758 leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z", 759 leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z", 760 // Harpoons are from glyph U+21BD in font KaTeX Main 761 leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z", 762 leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z", 763 leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z", 764 leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z", 765 // hook is from glyph U+21A9 in font KaTeX Main 766 lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z", 767 leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z", 768 leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z", 769 // tofrom is from glyph U+21C4 in font KaTeX AMS Regular 770 leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z", 771 longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z", 772 midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z", 773 midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z", 774 oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z", 775 oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z", 776 oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z", 777 oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z", 778 rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z", 779 rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z", 780 rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z", 781 rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z", 782 rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z", 783 rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z", 784 rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z", 785 rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z", 786 rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z", 787 righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z", 788 rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z", 789 rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z", 790 // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular 791 twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z", 792 twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z", 793 // tilde1 is a modified version of a glyph from the MnSymbol package 794 tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z", 795 // ditto tilde2, tilde3, & tilde4 796 tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z", 797 tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z", 798 tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z", 799 // vec is from glyph U+20D7 in font KaTeX Main 800 vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z", 801 // widehat1 is a modified version of a glyph from the MnSymbol package 802 widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z", 803 // ditto widehat2, widehat3, & widehat4 804 widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", 805 widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", 806 widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z", 807 // widecheck paths are all inverted versions of widehat 808 widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z", 809 widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", 810 widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", 811 widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z", 812 // The next ten paths support reaction arrows from the mhchem package. 813 // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX 814 // baraboveleftarrow is mostly from from glyph U+2190 in font KaTeX Main 815 baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z", 816 // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main 817 rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z", 818 // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end. 819 // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em 820 baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z", 821 rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z", 822 shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z", 823 shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z" 824 }; 825 826 /** 827 * This node represents a document fragment, which contains elements, but when 828 * placed into the DOM doesn't have any representation itself. It only contains 829 * children and doesn't have any DOM node properties. 830 */ 831 class DocumentFragment { 832 // HtmlDomNode 833 // Never used; needed for satisfying interface. 834 constructor(children) { 835 this.children = void 0; 836 this.classes = void 0; 837 this.height = void 0; 838 this.depth = void 0; 839 this.maxFontSize = void 0; 840 this.style = void 0; 841 this.children = children; 842 this.classes = []; 843 this.height = 0; 844 this.depth = 0; 845 this.maxFontSize = 0; 846 this.style = {}; 847 } 848 849 hasClass(className) { 850 return utils.contains(this.classes, className); 851 } 852 /** Convert the fragment into a node. */ 853 854 855 toNode() { 856 var frag = document.createDocumentFragment(); 857 858 for (var i = 0; i < this.children.length; i++) { 859 frag.appendChild(this.children[i].toNode()); 860 } 861 862 return frag; 863 } 864 /** Convert the fragment into HTML markup. */ 865 866 867 toMarkup() { 868 var markup = ""; // Simply concatenate the markup for the children together. 869 870 for (var i = 0; i < this.children.length; i++) { 871 markup += this.children[i].toMarkup(); 872 } 873 874 return markup; 875 } 876 /** 877 * Converts the math node into a string, similar to innerText. Applies to 878 * MathDomNode's only. 879 */ 880 881 882 toText() { 883 // To avoid this, we would subclass documentFragment separately for 884 // MathML, but polyfills for subclassing is expensive per PR 1469. 885 // $FlowFixMe: Only works for ChildType = MathDomNode. 886 var toText = child => child.toText(); 887 888 return this.children.map(toText).join(""); 889 } 890 891 } 892 893 /** 894 * These objects store the data about the DOM nodes we create, as well as some 895 * extra data. They can then be transformed into real DOM nodes with the 896 * `toNode` function or HTML markup using `toMarkup`. They are useful for both 897 * storing extra properties on the nodes, as well as providing a way to easily 898 * work with the DOM. 899 * 900 * Similar functions for working with MathML nodes exist in mathMLTree.js. 901 * 902 * TODO: refactor `span` and `anchor` into common superclass when 903 * target environments support class inheritance 904 */ 905 906 /** 907 * Create an HTML className based on a list of classes. In addition to joining 908 * with spaces, we also remove empty classes. 909 */ 910 var createClass = function createClass(classes) { 911 return classes.filter(cls => cls).join(" "); 912 }; 913 914 var initNode = function initNode(classes, options, style) { 915 this.classes = classes || []; 916 this.attributes = {}; 917 this.height = 0; 918 this.depth = 0; 919 this.maxFontSize = 0; 920 this.style = style || {}; 921 922 if (options) { 923 if (options.style.isTight()) { 924 this.classes.push("mtight"); 925 } 926 927 var color = options.getColor(); 928 929 if (color) { 930 this.style.color = color; 931 } 932 } 933 }; 934 /** 935 * Convert into an HTML node 936 */ 937 938 939 var toNode = function toNode(tagName) { 940 var node = document.createElement(tagName); // Apply the class 941 942 node.className = createClass(this.classes); // Apply inline styles 943 944 for (var style in this.style) { 945 if (this.style.hasOwnProperty(style)) { 946 // $FlowFixMe Flow doesn't seem to understand span.style's type. 947 node.style[style] = this.style[style]; 948 } 949 } // Apply attributes 950 951 952 for (var attr in this.attributes) { 953 if (this.attributes.hasOwnProperty(attr)) { 954 node.setAttribute(attr, this.attributes[attr]); 955 } 956 } // Append the children, also as HTML nodes 957 958 959 for (var i = 0; i < this.children.length; i++) { 960 node.appendChild(this.children[i].toNode()); 961 } 962 963 return node; 964 }; 965 /** 966 * Convert into an HTML markup string 967 */ 968 969 970 var toMarkup = function toMarkup(tagName) { 971 var markup = "<" + tagName; // Add the class 972 973 if (this.classes.length) { 974 markup += " class=\"" + utils.escape(createClass(this.classes)) + "\""; 975 } 976 977 var styles = ""; // Add the styles, after hyphenation 978 979 for (var style in this.style) { 980 if (this.style.hasOwnProperty(style)) { 981 styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; 982 } 983 } 984 985 if (styles) { 986 markup += " style=\"" + utils.escape(styles) + "\""; 987 } // Add the attributes 988 989 990 for (var attr in this.attributes) { 991 if (this.attributes.hasOwnProperty(attr)) { 992 markup += " " + attr + "=\"" + utils.escape(this.attributes[attr]) + "\""; 993 } 994 } 995 996 markup += ">"; // Add the markup of the children, also as markup 997 998 for (var i = 0; i < this.children.length; i++) { 999 markup += this.children[i].toMarkup(); 1000 } 1001 1002 markup += "</" + tagName + ">"; 1003 return markup; 1004 }; // Making the type below exact with all optional fields doesn't work due to 1005 // - https://github.com/facebook/flow/issues/4582 1006 // - https://github.com/facebook/flow/issues/5688 1007 // However, since *all* fields are optional, $Shape<> works as suggested in 5688 1008 // above. 1009 // This type does not include all CSS properties. Additional properties should 1010 // be added as needed. 1011 1012 1013 /** 1014 * This node represents a span node, with a className, a list of children, and 1015 * an inline style. It also contains information about its height, depth, and 1016 * maxFontSize. 1017 * 1018 * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan 1019 * otherwise. This typesafety is important when HTML builders access a span's 1020 * children. 1021 */ 1022 class Span { 1023 constructor(classes, children, options, style) { 1024 this.children = void 0; 1025 this.attributes = void 0; 1026 this.classes = void 0; 1027 this.height = void 0; 1028 this.depth = void 0; 1029 this.width = void 0; 1030 this.maxFontSize = void 0; 1031 this.style = void 0; 1032 initNode.call(this, classes, options, style); 1033 this.children = children || []; 1034 } 1035 /** 1036 * Sets an arbitrary attribute on the span. Warning: use this wisely. Not 1037 * all browsers support attributes the same, and having too many custom 1038 * attributes is probably bad. 1039 */ 1040 1041 1042 setAttribute(attribute, value) { 1043 this.attributes[attribute] = value; 1044 } 1045 1046 hasClass(className) { 1047 return utils.contains(this.classes, className); 1048 } 1049 1050 toNode() { 1051 return toNode.call(this, "span"); 1052 } 1053 1054 toMarkup() { 1055 return toMarkup.call(this, "span"); 1056 } 1057 1058 } 1059 /** 1060 * This node represents an anchor (<a>) element with a hyperlink. See `span` 1061 * for further details. 1062 */ 1063 1064 class Anchor { 1065 constructor(href, classes, children, options) { 1066 this.children = void 0; 1067 this.attributes = void 0; 1068 this.classes = void 0; 1069 this.height = void 0; 1070 this.depth = void 0; 1071 this.maxFontSize = void 0; 1072 this.style = void 0; 1073 initNode.call(this, classes, options); 1074 this.children = children || []; 1075 this.setAttribute('href', href); 1076 } 1077 1078 setAttribute(attribute, value) { 1079 this.attributes[attribute] = value; 1080 } 1081 1082 hasClass(className) { 1083 return utils.contains(this.classes, className); 1084 } 1085 1086 toNode() { 1087 return toNode.call(this, "a"); 1088 } 1089 1090 toMarkup() { 1091 return toMarkup.call(this, "a"); 1092 } 1093 1094 } 1095 /** 1096 * This node represents an image embed (<img>) element. 1097 */ 1098 1099 class Img { 1100 constructor(src, alt, style) { 1101 this.src = void 0; 1102 this.alt = void 0; 1103 this.classes = void 0; 1104 this.height = void 0; 1105 this.depth = void 0; 1106 this.maxFontSize = void 0; 1107 this.style = void 0; 1108 this.alt = alt; 1109 this.src = src; 1110 this.classes = ["mord"]; 1111 this.style = style; 1112 } 1113 1114 hasClass(className) { 1115 return utils.contains(this.classes, className); 1116 } 1117 1118 toNode() { 1119 var node = document.createElement("img"); 1120 node.src = this.src; 1121 node.alt = this.alt; 1122 node.className = "mord"; // Apply inline styles 1123 1124 for (var style in this.style) { 1125 if (this.style.hasOwnProperty(style)) { 1126 // $FlowFixMe 1127 node.style[style] = this.style[style]; 1128 } 1129 } 1130 1131 return node; 1132 } 1133 1134 toMarkup() { 1135 var markup = "<img src='" + this.src + " 'alt='" + this.alt + "' "; // Add the styles, after hyphenation 1136 1137 var styles = ""; 1138 1139 for (var style in this.style) { 1140 if (this.style.hasOwnProperty(style)) { 1141 styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; 1142 } 1143 } 1144 1145 if (styles) { 1146 markup += " style=\"" + utils.escape(styles) + "\""; 1147 } 1148 1149 markup += "'/>"; 1150 return markup; 1151 } 1152 1153 } 1154 var iCombinations = { 1155 'î': '\u0131\u0302', 1156 'ï': '\u0131\u0308', 1157 'í': '\u0131\u0301', 1158 // 'ī': '\u0131\u0304', // enable when we add Extended Latin 1159 'ì': '\u0131\u0300' 1160 }; 1161 /** 1162 * A symbol node contains information about a single symbol. It either renders 1163 * to a single text node, or a span with a single text node in it, depending on 1164 * whether it has CSS classes, styles, or needs italic correction. 1165 */ 1166 1167 class SymbolNode { 1168 constructor(text, height, depth, italic, skew, width, classes, style) { 1169 this.text = void 0; 1170 this.height = void 0; 1171 this.depth = void 0; 1172 this.italic = void 0; 1173 this.skew = void 0; 1174 this.width = void 0; 1175 this.maxFontSize = void 0; 1176 this.classes = void 0; 1177 this.style = void 0; 1178 this.text = text; 1179 this.height = height || 0; 1180 this.depth = depth || 0; 1181 this.italic = italic || 0; 1182 this.skew = skew || 0; 1183 this.width = width || 0; 1184 this.classes = classes || []; 1185 this.style = style || {}; 1186 this.maxFontSize = 0; // Mark text from non-Latin scripts with specific classes so that we 1187 // can specify which fonts to use. This allows us to render these 1188 // characters with a serif font in situations where the browser would 1189 // either default to a sans serif or render a placeholder character. 1190 // We use CSS class names like cjk_fallback, hangul_fallback and 1191 // brahmic_fallback. See ./unicodeScripts.js for the set of possible 1192 // script names 1193 1194 var script = scriptFromCodepoint(this.text.charCodeAt(0)); 1195 1196 if (script) { 1197 this.classes.push(script + "_fallback"); 1198 } 1199 1200 if (/[îïíì]/.test(this.text)) { 1201 // add ī when we add Extended Latin 1202 this.text = iCombinations[this.text]; 1203 } 1204 } 1205 1206 hasClass(className) { 1207 return utils.contains(this.classes, className); 1208 } 1209 /** 1210 * Creates a text node or span from a symbol node. Note that a span is only 1211 * created if it is needed. 1212 */ 1213 1214 1215 toNode() { 1216 var node = document.createTextNode(this.text); 1217 var span = null; 1218 1219 if (this.italic > 0) { 1220 span = document.createElement("span"); 1221 span.style.marginRight = this.italic + "em"; 1222 } 1223 1224 if (this.classes.length > 0) { 1225 span = span || document.createElement("span"); 1226 span.className = createClass(this.classes); 1227 } 1228 1229 for (var style in this.style) { 1230 if (this.style.hasOwnProperty(style)) { 1231 span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type. 1232 1233 span.style[style] = this.style[style]; 1234 } 1235 } 1236 1237 if (span) { 1238 span.appendChild(node); 1239 return span; 1240 } else { 1241 return node; 1242 } 1243 } 1244 /** 1245 * Creates markup for a symbol node. 1246 */ 1247 1248 1249 toMarkup() { 1250 // TODO(alpert): More duplication than I'd like from 1251 // span.prototype.toMarkup and symbolNode.prototype.toNode... 1252 var needsSpan = false; 1253 var markup = "<span"; 1254 1255 if (this.classes.length) { 1256 needsSpan = true; 1257 markup += " class=\""; 1258 markup += utils.escape(createClass(this.classes)); 1259 markup += "\""; 1260 } 1261 1262 var styles = ""; 1263 1264 if (this.italic > 0) { 1265 styles += "margin-right:" + this.italic + "em;"; 1266 } 1267 1268 for (var style in this.style) { 1269 if (this.style.hasOwnProperty(style)) { 1270 styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; 1271 } 1272 } 1273 1274 if (styles) { 1275 needsSpan = true; 1276 markup += " style=\"" + utils.escape(styles) + "\""; 1277 } 1278 1279 var escaped = utils.escape(this.text); 1280 1281 if (needsSpan) { 1282 markup += ">"; 1283 markup += escaped; 1284 markup += "</span>"; 1285 return markup; 1286 } else { 1287 return escaped; 1288 } 1289 } 1290 1291 } 1292 /** 1293 * SVG nodes are used to render stretchy wide elements. 1294 */ 1295 1296 class SvgNode { 1297 constructor(children, attributes) { 1298 this.children = void 0; 1299 this.attributes = void 0; 1300 this.children = children || []; 1301 this.attributes = attributes || {}; 1302 } 1303 1304 toNode() { 1305 var svgNS = "http://www.w3.org/2000/svg"; 1306 var node = document.createElementNS(svgNS, "svg"); // Apply attributes 1307 1308 for (var attr in this.attributes) { 1309 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 1310 node.setAttribute(attr, this.attributes[attr]); 1311 } 1312 } 1313 1314 for (var i = 0; i < this.children.length; i++) { 1315 node.appendChild(this.children[i].toNode()); 1316 } 1317 1318 return node; 1319 } 1320 1321 toMarkup() { 1322 var markup = "<svg"; // Apply attributes 1323 1324 for (var attr in this.attributes) { 1325 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 1326 markup += " " + attr + "='" + this.attributes[attr] + "'"; 1327 } 1328 } 1329 1330 markup += ">"; 1331 1332 for (var i = 0; i < this.children.length; i++) { 1333 markup += this.children[i].toMarkup(); 1334 } 1335 1336 markup += "</svg>"; 1337 return markup; 1338 } 1339 1340 } 1341 class PathNode { 1342 constructor(pathName, alternate) { 1343 this.pathName = void 0; 1344 this.alternate = void 0; 1345 this.pathName = pathName; 1346 this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims 1347 } 1348 1349 toNode() { 1350 var svgNS = "http://www.w3.org/2000/svg"; 1351 var node = document.createElementNS(svgNS, "path"); 1352 1353 if (this.alternate) { 1354 node.setAttribute("d", this.alternate); 1355 } else { 1356 node.setAttribute("d", path[this.pathName]); 1357 } 1358 1359 return node; 1360 } 1361 1362 toMarkup() { 1363 if (this.alternate) { 1364 return "<path d='" + this.alternate + "'/>"; 1365 } else { 1366 return "<path d='" + path[this.pathName] + "'/>"; 1367 } 1368 } 1369 1370 } 1371 class LineNode { 1372 constructor(attributes) { 1373 this.attributes = void 0; 1374 this.attributes = attributes || {}; 1375 } 1376 1377 toNode() { 1378 var svgNS = "http://www.w3.org/2000/svg"; 1379 var node = document.createElementNS(svgNS, "line"); // Apply attributes 1380 1381 for (var attr in this.attributes) { 1382 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 1383 node.setAttribute(attr, this.attributes[attr]); 1384 } 1385 } 1386 1387 return node; 1388 } 1389 1390 toMarkup() { 1391 var markup = "<line"; 1392 1393 for (var attr in this.attributes) { 1394 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 1395 markup += " " + attr + "='" + this.attributes[attr] + "'"; 1396 } 1397 } 1398 1399 markup += "/>"; 1400 return markup; 1401 } 1402 1403 } 1404 function assertSymbolDomNode(group) { 1405 if (group instanceof SymbolNode) { 1406 return group; 1407 } else { 1408 throw new Error("Expected symbolNode but got " + String(group) + "."); 1409 } 1410 } 1411 function assertSpan(group) { 1412 if (group instanceof Span) { 1413 return group; 1414 } else { 1415 throw new Error("Expected span<HtmlDomNode> but got " + String(group) + "."); 1416 } 1417 } 1418 1419 // This file is GENERATED by buildMetrics.sh. DO NOT MODIFY. 1420 var fontMetricsData = { 1421 "AMS-Regular": { 1422 "32": [0, 0, 0, 0, 0.25], 1423 "65": [0, 0.68889, 0, 0, 0.72222], 1424 "66": [0, 0.68889, 0, 0, 0.66667], 1425 "67": [0, 0.68889, 0, 0, 0.72222], 1426 "68": [0, 0.68889, 0, 0, 0.72222], 1427 "69": [0, 0.68889, 0, 0, 0.66667], 1428 "70": [0, 0.68889, 0, 0, 0.61111], 1429 "71": [0, 0.68889, 0, 0, 0.77778], 1430 "72": [0, 0.68889, 0, 0, 0.77778], 1431 "73": [0, 0.68889, 0, 0, 0.38889], 1432 "74": [0.16667, 0.68889, 0, 0, 0.5], 1433 "75": [0, 0.68889, 0, 0, 0.77778], 1434 "76": [0, 0.68889, 0, 0, 0.66667], 1435 "77": [0, 0.68889, 0, 0, 0.94445], 1436 "78": [0, 0.68889, 0, 0, 0.72222], 1437 "79": [0.16667, 0.68889, 0, 0, 0.77778], 1438 "80": [0, 0.68889, 0, 0, 0.61111], 1439 "81": [0.16667, 0.68889, 0, 0, 0.77778], 1440 "82": [0, 0.68889, 0, 0, 0.72222], 1441 "83": [0, 0.68889, 0, 0, 0.55556], 1442 "84": [0, 0.68889, 0, 0, 0.66667], 1443 "85": [0, 0.68889, 0, 0, 0.72222], 1444 "86": [0, 0.68889, 0, 0, 0.72222], 1445 "87": [0, 0.68889, 0, 0, 1.0], 1446 "88": [0, 0.68889, 0, 0, 0.72222], 1447 "89": [0, 0.68889, 0, 0, 0.72222], 1448 "90": [0, 0.68889, 0, 0, 0.66667], 1449 "107": [0, 0.68889, 0, 0, 0.55556], 1450 "160": [0, 0, 0, 0, 0.25], 1451 "165": [0, 0.675, 0.025, 0, 0.75], 1452 "174": [0.15559, 0.69224, 0, 0, 0.94666], 1453 "240": [0, 0.68889, 0, 0, 0.55556], 1454 "295": [0, 0.68889, 0, 0, 0.54028], 1455 "710": [0, 0.825, 0, 0, 2.33334], 1456 "732": [0, 0.9, 0, 0, 2.33334], 1457 "770": [0, 0.825, 0, 0, 2.33334], 1458 "771": [0, 0.9, 0, 0, 2.33334], 1459 "989": [0.08167, 0.58167, 0, 0, 0.77778], 1460 "1008": [0, 0.43056, 0.04028, 0, 0.66667], 1461 "8245": [0, 0.54986, 0, 0, 0.275], 1462 "8463": [0, 0.68889, 0, 0, 0.54028], 1463 "8487": [0, 0.68889, 0, 0, 0.72222], 1464 "8498": [0, 0.68889, 0, 0, 0.55556], 1465 "8502": [0, 0.68889, 0, 0, 0.66667], 1466 "8503": [0, 0.68889, 0, 0, 0.44445], 1467 "8504": [0, 0.68889, 0, 0, 0.66667], 1468 "8513": [0, 0.68889, 0, 0, 0.63889], 1469 "8592": [-0.03598, 0.46402, 0, 0, 0.5], 1470 "8594": [-0.03598, 0.46402, 0, 0, 0.5], 1471 "8602": [-0.13313, 0.36687, 0, 0, 1.0], 1472 "8603": [-0.13313, 0.36687, 0, 0, 1.0], 1473 "8606": [0.01354, 0.52239, 0, 0, 1.0], 1474 "8608": [0.01354, 0.52239, 0, 0, 1.0], 1475 "8610": [0.01354, 0.52239, 0, 0, 1.11111], 1476 "8611": [0.01354, 0.52239, 0, 0, 1.11111], 1477 "8619": [0, 0.54986, 0, 0, 1.0], 1478 "8620": [0, 0.54986, 0, 0, 1.0], 1479 "8621": [-0.13313, 0.37788, 0, 0, 1.38889], 1480 "8622": [-0.13313, 0.36687, 0, 0, 1.0], 1481 "8624": [0, 0.69224, 0, 0, 0.5], 1482 "8625": [0, 0.69224, 0, 0, 0.5], 1483 "8630": [0, 0.43056, 0, 0, 1.0], 1484 "8631": [0, 0.43056, 0, 0, 1.0], 1485 "8634": [0.08198, 0.58198, 0, 0, 0.77778], 1486 "8635": [0.08198, 0.58198, 0, 0, 0.77778], 1487 "8638": [0.19444, 0.69224, 0, 0, 0.41667], 1488 "8639": [0.19444, 0.69224, 0, 0, 0.41667], 1489 "8642": [0.19444, 0.69224, 0, 0, 0.41667], 1490 "8643": [0.19444, 0.69224, 0, 0, 0.41667], 1491 "8644": [0.1808, 0.675, 0, 0, 1.0], 1492 "8646": [0.1808, 0.675, 0, 0, 1.0], 1493 "8647": [0.1808, 0.675, 0, 0, 1.0], 1494 "8648": [0.19444, 0.69224, 0, 0, 0.83334], 1495 "8649": [0.1808, 0.675, 0, 0, 1.0], 1496 "8650": [0.19444, 0.69224, 0, 0, 0.83334], 1497 "8651": [0.01354, 0.52239, 0, 0, 1.0], 1498 "8652": [0.01354, 0.52239, 0, 0, 1.0], 1499 "8653": [-0.13313, 0.36687, 0, 0, 1.0], 1500 "8654": [-0.13313, 0.36687, 0, 0, 1.0], 1501 "8655": [-0.13313, 0.36687, 0, 0, 1.0], 1502 "8666": [0.13667, 0.63667, 0, 0, 1.0], 1503 "8667": [0.13667, 0.63667, 0, 0, 1.0], 1504 "8669": [-0.13313, 0.37788, 0, 0, 1.0], 1505 "8672": [-0.064, 0.437, 0, 0, 1.334], 1506 "8674": [-0.064, 0.437, 0, 0, 1.334], 1507 "8705": [0, 0.825, 0, 0, 0.5], 1508 "8708": [0, 0.68889, 0, 0, 0.55556], 1509 "8709": [0.08167, 0.58167, 0, 0, 0.77778], 1510 "8717": [0, 0.43056, 0, 0, 0.42917], 1511 "8722": [-0.03598, 0.46402, 0, 0, 0.5], 1512 "8724": [0.08198, 0.69224, 0, 0, 0.77778], 1513 "8726": [0.08167, 0.58167, 0, 0, 0.77778], 1514 "8733": [0, 0.69224, 0, 0, 0.77778], 1515 "8736": [0, 0.69224, 0, 0, 0.72222], 1516 "8737": [0, 0.69224, 0, 0, 0.72222], 1517 "8738": [0.03517, 0.52239, 0, 0, 0.72222], 1518 "8739": [0.08167, 0.58167, 0, 0, 0.22222], 1519 "8740": [0.25142, 0.74111, 0, 0, 0.27778], 1520 "8741": [0.08167, 0.58167, 0, 0, 0.38889], 1521 "8742": [0.25142, 0.74111, 0, 0, 0.5], 1522 "8756": [0, 0.69224, 0, 0, 0.66667], 1523 "8757": [0, 0.69224, 0, 0, 0.66667], 1524 "8764": [-0.13313, 0.36687, 0, 0, 0.77778], 1525 "8765": [-0.13313, 0.37788, 0, 0, 0.77778], 1526 "8769": [-0.13313, 0.36687, 0, 0, 0.77778], 1527 "8770": [-0.03625, 0.46375, 0, 0, 0.77778], 1528 "8774": [0.30274, 0.79383, 0, 0, 0.77778], 1529 "8776": [-0.01688, 0.48312, 0, 0, 0.77778], 1530 "8778": [0.08167, 0.58167, 0, 0, 0.77778], 1531 "8782": [0.06062, 0.54986, 0, 0, 0.77778], 1532 "8783": [0.06062, 0.54986, 0, 0, 0.77778], 1533 "8785": [0.08198, 0.58198, 0, 0, 0.77778], 1534 "8786": [0.08198, 0.58198, 0, 0, 0.77778], 1535 "8787": [0.08198, 0.58198, 0, 0, 0.77778], 1536 "8790": [0, 0.69224, 0, 0, 0.77778], 1537 "8791": [0.22958, 0.72958, 0, 0, 0.77778], 1538 "8796": [0.08198, 0.91667, 0, 0, 0.77778], 1539 "8806": [0.25583, 0.75583, 0, 0, 0.77778], 1540 "8807": [0.25583, 0.75583, 0, 0, 0.77778], 1541 "8808": [0.25142, 0.75726, 0, 0, 0.77778], 1542 "8809": [0.25142, 0.75726, 0, 0, 0.77778], 1543 "8812": [0.25583, 0.75583, 0, 0, 0.5], 1544 "8814": [0.20576, 0.70576, 0, 0, 0.77778], 1545 "8815": [0.20576, 0.70576, 0, 0, 0.77778], 1546 "8816": [0.30274, 0.79383, 0, 0, 0.77778], 1547 "8817": [0.30274, 0.79383, 0, 0, 0.77778], 1548 "8818": [0.22958, 0.72958, 0, 0, 0.77778], 1549 "8819": [0.22958, 0.72958, 0, 0, 0.77778], 1550 "8822": [0.1808, 0.675, 0, 0, 0.77778], 1551 "8823": [0.1808, 0.675, 0, 0, 0.77778], 1552 "8828": [0.13667, 0.63667, 0, 0, 0.77778], 1553 "8829": [0.13667, 0.63667, 0, 0, 0.77778], 1554 "8830": [0.22958, 0.72958, 0, 0, 0.77778], 1555 "8831": [0.22958, 0.72958, 0, 0, 0.77778], 1556 "8832": [0.20576, 0.70576, 0, 0, 0.77778], 1557 "8833": [0.20576, 0.70576, 0, 0, 0.77778], 1558 "8840": [0.30274, 0.79383, 0, 0, 0.77778], 1559 "8841": [0.30274, 0.79383, 0, 0, 0.77778], 1560 "8842": [0.13597, 0.63597, 0, 0, 0.77778], 1561 "8843": [0.13597, 0.63597, 0, 0, 0.77778], 1562 "8847": [0.03517, 0.54986, 0, 0, 0.77778], 1563 "8848": [0.03517, 0.54986, 0, 0, 0.77778], 1564 "8858": [0.08198, 0.58198, 0, 0, 0.77778], 1565 "8859": [0.08198, 0.58198, 0, 0, 0.77778], 1566 "8861": [0.08198, 0.58198, 0, 0, 0.77778], 1567 "8862": [0, 0.675, 0, 0, 0.77778], 1568 "8863": [0, 0.675, 0, 0, 0.77778], 1569 "8864": [0, 0.675, 0, 0, 0.77778], 1570 "8865": [0, 0.675, 0, 0, 0.77778], 1571 "8872": [0, 0.69224, 0, 0, 0.61111], 1572 "8873": [0, 0.69224, 0, 0, 0.72222], 1573 "8874": [0, 0.69224, 0, 0, 0.88889], 1574 "8876": [0, 0.68889, 0, 0, 0.61111], 1575 "8877": [0, 0.68889, 0, 0, 0.61111], 1576 "8878": [0, 0.68889, 0, 0, 0.72222], 1577 "8879": [0, 0.68889, 0, 0, 0.72222], 1578 "8882": [0.03517, 0.54986, 0, 0, 0.77778], 1579 "8883": [0.03517, 0.54986, 0, 0, 0.77778], 1580 "8884": [0.13667, 0.63667, 0, 0, 0.77778], 1581 "8885": [0.13667, 0.63667, 0, 0, 0.77778], 1582 "8888": [0, 0.54986, 0, 0, 1.11111], 1583 "8890": [0.19444, 0.43056, 0, 0, 0.55556], 1584 "8891": [0.19444, 0.69224, 0, 0, 0.61111], 1585 "8892": [0.19444, 0.69224, 0, 0, 0.61111], 1586 "8901": [0, 0.54986, 0, 0, 0.27778], 1587 "8903": [0.08167, 0.58167, 0, 0, 0.77778], 1588 "8905": [0.08167, 0.58167, 0, 0, 0.77778], 1589 "8906": [0.08167, 0.58167, 0, 0, 0.77778], 1590 "8907": [0, 0.69224, 0, 0, 0.77778], 1591 "8908": [0, 0.69224, 0, 0, 0.77778], 1592 "8909": [-0.03598, 0.46402, 0, 0, 0.77778], 1593 "8910": [0, 0.54986, 0, 0, 0.76042], 1594 "8911": [0, 0.54986, 0, 0, 0.76042], 1595 "8912": [0.03517, 0.54986, 0, 0, 0.77778], 1596 "8913": [0.03517, 0.54986, 0, 0, 0.77778], 1597 "8914": [0, 0.54986, 0, 0, 0.66667], 1598 "8915": [0, 0.54986, 0, 0, 0.66667], 1599 "8916": [0, 0.69224, 0, 0, 0.66667], 1600 "8918": [0.0391, 0.5391, 0, 0, 0.77778], 1601 "8919": [0.0391, 0.5391, 0, 0, 0.77778], 1602 "8920": [0.03517, 0.54986, 0, 0, 1.33334], 1603 "8921": [0.03517, 0.54986, 0, 0, 1.33334], 1604 "8922": [0.38569, 0.88569, 0, 0, 0.77778], 1605 "8923": [0.38569, 0.88569, 0, 0, 0.77778], 1606 "8926": [0.13667, 0.63667, 0, 0, 0.77778], 1607 "8927": [0.13667, 0.63667, 0, 0, 0.77778], 1608 "8928": [0.30274, 0.79383, 0, 0, 0.77778], 1609 "8929": [0.30274, 0.79383, 0, 0, 0.77778], 1610 "8934": [0.23222, 0.74111, 0, 0, 0.77778], 1611 "8935": [0.23222, 0.74111, 0, 0, 0.77778], 1612 "8936": [0.23222, 0.74111, 0, 0, 0.77778], 1613 "8937": [0.23222, 0.74111, 0, 0, 0.77778], 1614 "8938": [0.20576, 0.70576, 0, 0, 0.77778], 1615 "8939": [0.20576, 0.70576, 0, 0, 0.77778], 1616 "8940": [0.30274, 0.79383, 0, 0, 0.77778], 1617 "8941": [0.30274, 0.79383, 0, 0, 0.77778], 1618 "8994": [0.19444, 0.69224, 0, 0, 0.77778], 1619 "8995": [0.19444, 0.69224, 0, 0, 0.77778], 1620 "9416": [0.15559, 0.69224, 0, 0, 0.90222], 1621 "9484": [0, 0.69224, 0, 0, 0.5], 1622 "9488": [0, 0.69224, 0, 0, 0.5], 1623 "9492": [0, 0.37788, 0, 0, 0.5], 1624 "9496": [0, 0.37788, 0, 0, 0.5], 1625 "9585": [0.19444, 0.68889, 0, 0, 0.88889], 1626 "9586": [0.19444, 0.74111, 0, 0, 0.88889], 1627 "9632": [0, 0.675, 0, 0, 0.77778], 1628 "9633": [0, 0.675, 0, 0, 0.77778], 1629 "9650": [0, 0.54986, 0, 0, 0.72222], 1630 "9651": [0, 0.54986, 0, 0, 0.72222], 1631 "9654": [0.03517, 0.54986, 0, 0, 0.77778], 1632 "9660": [0, 0.54986, 0, 0, 0.72222], 1633 "9661": [0, 0.54986, 0, 0, 0.72222], 1634 "9664": [0.03517, 0.54986, 0, 0, 0.77778], 1635 "9674": [0.11111, 0.69224, 0, 0, 0.66667], 1636 "9733": [0.19444, 0.69224, 0, 0, 0.94445], 1637 "10003": [0, 0.69224, 0, 0, 0.83334], 1638 "10016": [0, 0.69224, 0, 0, 0.83334], 1639 "10731": [0.11111, 0.69224, 0, 0, 0.66667], 1640 "10846": [0.19444, 0.75583, 0, 0, 0.61111], 1641 "10877": [0.13667, 0.63667, 0, 0, 0.77778], 1642 "10878": [0.13667, 0.63667, 0, 0, 0.77778], 1643 "10885": [0.25583, 0.75583, 0, 0, 0.77778], 1644 "10886": [0.25583, 0.75583, 0, 0, 0.77778], 1645 "10887": [0.13597, 0.63597, 0, 0, 0.77778], 1646 "10888": [0.13597, 0.63597, 0, 0, 0.77778], 1647 "10889": [0.26167, 0.75726, 0, 0, 0.77778], 1648 "10890": [0.26167, 0.75726, 0, 0, 0.77778], 1649 "10891": [0.48256, 0.98256, 0, 0, 0.77778], 1650 "10892": [0.48256, 0.98256, 0, 0, 0.77778], 1651 "10901": [0.13667, 0.63667, 0, 0, 0.77778], 1652 "10902": [0.13667, 0.63667, 0, 0, 0.77778], 1653 "10933": [0.25142, 0.75726, 0, 0, 0.77778], 1654 "10934": [0.25142, 0.75726, 0, 0, 0.77778], 1655 "10935": [0.26167, 0.75726, 0, 0, 0.77778], 1656 "10936": [0.26167, 0.75726, 0, 0, 0.77778], 1657 "10937": [0.26167, 0.75726, 0, 0, 0.77778], 1658 "10938": [0.26167, 0.75726, 0, 0, 0.77778], 1659 "10949": [0.25583, 0.75583, 0, 0, 0.77778], 1660 "10950": [0.25583, 0.75583, 0, 0, 0.77778], 1661 "10955": [0.28481, 0.79383, 0, 0, 0.77778], 1662 "10956": [0.28481, 0.79383, 0, 0, 0.77778], 1663 "57350": [0.08167, 0.58167, 0, 0, 0.22222], 1664 "57351": [0.08167, 0.58167, 0, 0, 0.38889], 1665 "57352": [0.08167, 0.58167, 0, 0, 0.77778], 1666 "57353": [0, 0.43056, 0.04028, 0, 0.66667], 1667 "57356": [0.25142, 0.75726, 0, 0, 0.77778], 1668 "57357": [0.25142, 0.75726, 0, 0, 0.77778], 1669 "57358": [0.41951, 0.91951, 0, 0, 0.77778], 1670 "57359": [0.30274, 0.79383, 0, 0, 0.77778], 1671 "57360": [0.30274, 0.79383, 0, 0, 0.77778], 1672 "57361": [0.41951, 0.91951, 0, 0, 0.77778], 1673 "57366": [0.25142, 0.75726, 0, 0, 0.77778], 1674 "57367": [0.25142, 0.75726, 0, 0, 0.77778], 1675 "57368": [0.25142, 0.75726, 0, 0, 0.77778], 1676 "57369": [0.25142, 0.75726, 0, 0, 0.77778], 1677 "57370": [0.13597, 0.63597, 0, 0, 0.77778], 1678 "57371": [0.13597, 0.63597, 0, 0, 0.77778] 1679 }, 1680 "Caligraphic-Regular": { 1681 "32": [0, 0, 0, 0, 0.25], 1682 "65": [0, 0.68333, 0, 0.19445, 0.79847], 1683 "66": [0, 0.68333, 0.03041, 0.13889, 0.65681], 1684 "67": [0, 0.68333, 0.05834, 0.13889, 0.52653], 1685 "68": [0, 0.68333, 0.02778, 0.08334, 0.77139], 1686 "69": [0, 0.68333, 0.08944, 0.11111, 0.52778], 1687 "70": [0, 0.68333, 0.09931, 0.11111, 0.71875], 1688 "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487], 1689 "72": [0, 0.68333, 0.00965, 0.11111, 0.84452], 1690 "73": [0, 0.68333, 0.07382, 0, 0.54452], 1691 "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778], 1692 "75": [0, 0.68333, 0.01445, 0.05556, 0.76195], 1693 "76": [0, 0.68333, 0, 0.13889, 0.68972], 1694 "77": [0, 0.68333, 0, 0.13889, 1.2009], 1695 "78": [0, 0.68333, 0.14736, 0.08334, 0.82049], 1696 "79": [0, 0.68333, 0.02778, 0.11111, 0.79611], 1697 "80": [0, 0.68333, 0.08222, 0.08334, 0.69556], 1698 "81": [0.09722, 0.68333, 0, 0.11111, 0.81667], 1699 "82": [0, 0.68333, 0, 0.08334, 0.8475], 1700 "83": [0, 0.68333, 0.075, 0.13889, 0.60556], 1701 "84": [0, 0.68333, 0.25417, 0, 0.54464], 1702 "85": [0, 0.68333, 0.09931, 0.08334, 0.62583], 1703 "86": [0, 0.68333, 0.08222, 0, 0.61278], 1704 "87": [0, 0.68333, 0.08222, 0.08334, 0.98778], 1705 "88": [0, 0.68333, 0.14643, 0.13889, 0.7133], 1706 "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834], 1707 "90": [0, 0.68333, 0.07944, 0.13889, 0.72473], 1708 "160": [0, 0, 0, 0, 0.25] 1709 }, 1710 "Fraktur-Regular": { 1711 "32": [0, 0, 0, 0, 0.25], 1712 "33": [0, 0.69141, 0, 0, 0.29574], 1713 "34": [0, 0.69141, 0, 0, 0.21471], 1714 "38": [0, 0.69141, 0, 0, 0.73786], 1715 "39": [0, 0.69141, 0, 0, 0.21201], 1716 "40": [0.24982, 0.74947, 0, 0, 0.38865], 1717 "41": [0.24982, 0.74947, 0, 0, 0.38865], 1718 "42": [0, 0.62119, 0, 0, 0.27764], 1719 "43": [0.08319, 0.58283, 0, 0, 0.75623], 1720 "44": [0, 0.10803, 0, 0, 0.27764], 1721 "45": [0.08319, 0.58283, 0, 0, 0.75623], 1722 "46": [0, 0.10803, 0, 0, 0.27764], 1723 "47": [0.24982, 0.74947, 0, 0, 0.50181], 1724 "48": [0, 0.47534, 0, 0, 0.50181], 1725 "49": [0, 0.47534, 0, 0, 0.50181], 1726 "50": [0, 0.47534, 0, 0, 0.50181], 1727 "51": [0.18906, 0.47534, 0, 0, 0.50181], 1728 "52": [0.18906, 0.47534, 0, 0, 0.50181], 1729 "53": [0.18906, 0.47534, 0, 0, 0.50181], 1730 "54": [0, 0.69141, 0, 0, 0.50181], 1731 "55": [0.18906, 0.47534, 0, 0, 0.50181], 1732 "56": [0, 0.69141, 0, 0, 0.50181], 1733 "57": [0.18906, 0.47534, 0, 0, 0.50181], 1734 "58": [0, 0.47534, 0, 0, 0.21606], 1735 "59": [0.12604, 0.47534, 0, 0, 0.21606], 1736 "61": [-0.13099, 0.36866, 0, 0, 0.75623], 1737 "63": [0, 0.69141, 0, 0, 0.36245], 1738 "65": [0, 0.69141, 0, 0, 0.7176], 1739 "66": [0, 0.69141, 0, 0, 0.88397], 1740 "67": [0, 0.69141, 0, 0, 0.61254], 1741 "68": [0, 0.69141, 0, 0, 0.83158], 1742 "69": [0, 0.69141, 0, 0, 0.66278], 1743 "70": [0.12604, 0.69141, 0, 0, 0.61119], 1744 "71": [0, 0.69141, 0, 0, 0.78539], 1745 "72": [0.06302, 0.69141, 0, 0, 0.7203], 1746 "73": [0, 0.69141, 0, 0, 0.55448], 1747 "74": [0.12604, 0.69141, 0, 0, 0.55231], 1748 "75": [0, 0.69141, 0, 0, 0.66845], 1749 "76": [0, 0.69141, 0, 0, 0.66602], 1750 "77": [0, 0.69141, 0, 0, 1.04953], 1751 "78": [0, 0.69141, 0, 0, 0.83212], 1752 "79": [0, 0.69141, 0, 0, 0.82699], 1753 "80": [0.18906, 0.69141, 0, 0, 0.82753], 1754 "81": [0.03781, 0.69141, 0, 0, 0.82699], 1755 "82": [0, 0.69141, 0, 0, 0.82807], 1756 "83": [0, 0.69141, 0, 0, 0.82861], 1757 "84": [0, 0.69141, 0, 0, 0.66899], 1758 "85": [0, 0.69141, 0, 0, 0.64576], 1759 "86": [0, 0.69141, 0, 0, 0.83131], 1760 "87": [0, 0.69141, 0, 0, 1.04602], 1761 "88": [0, 0.69141, 0, 0, 0.71922], 1762 "89": [0.18906, 0.69141, 0, 0, 0.83293], 1763 "90": [0.12604, 0.69141, 0, 0, 0.60201], 1764 "91": [0.24982, 0.74947, 0, 0, 0.27764], 1765 "93": [0.24982, 0.74947, 0, 0, 0.27764], 1766 "94": [0, 0.69141, 0, 0, 0.49965], 1767 "97": [0, 0.47534, 0, 0, 0.50046], 1768 "98": [0, 0.69141, 0, 0, 0.51315], 1769 "99": [0, 0.47534, 0, 0, 0.38946], 1770 "100": [0, 0.62119, 0, 0, 0.49857], 1771 "101": [0, 0.47534, 0, 0, 0.40053], 1772 "102": [0.18906, 0.69141, 0, 0, 0.32626], 1773 "103": [0.18906, 0.47534, 0, 0, 0.5037], 1774 "104": [0.18906, 0.69141, 0, 0, 0.52126], 1775 "105": [0, 0.69141, 0, 0, 0.27899], 1776 "106": [0, 0.69141, 0, 0, 0.28088], 1777 "107": [0, 0.69141, 0, 0, 0.38946], 1778 "108": [0, 0.69141, 0, 0, 0.27953], 1779 "109": [0, 0.47534, 0, 0, 0.76676], 1780 "110": [0, 0.47534, 0, 0, 0.52666], 1781 "111": [0, 0.47534, 0, 0, 0.48885], 1782 "112": [0.18906, 0.52396, 0, 0, 0.50046], 1783 "113": [0.18906, 0.47534, 0, 0, 0.48912], 1784 "114": [0, 0.47534, 0, 0, 0.38919], 1785 "115": [0, 0.47534, 0, 0, 0.44266], 1786 "116": [0, 0.62119, 0, 0, 0.33301], 1787 "117": [0, 0.47534, 0, 0, 0.5172], 1788 "118": [0, 0.52396, 0, 0, 0.5118], 1789 "119": [0, 0.52396, 0, 0, 0.77351], 1790 "120": [0.18906, 0.47534, 0, 0, 0.38865], 1791 "121": [0.18906, 0.47534, 0, 0, 0.49884], 1792 "122": [0.18906, 0.47534, 0, 0, 0.39054], 1793 "160": [0, 0, 0, 0, 0.25], 1794 "8216": [0, 0.69141, 0, 0, 0.21471], 1795 "8217": [0, 0.69141, 0, 0, 0.21471], 1796 "58112": [0, 0.62119, 0, 0, 0.49749], 1797 "58113": [0, 0.62119, 0, 0, 0.4983], 1798 "58114": [0.18906, 0.69141, 0, 0, 0.33328], 1799 "58115": [0.18906, 0.69141, 0, 0, 0.32923], 1800 "58116": [0.18906, 0.47534, 0, 0, 0.50343], 1801 "58117": [0, 0.69141, 0, 0, 0.33301], 1802 "58118": [0, 0.62119, 0, 0, 0.33409], 1803 "58119": [0, 0.47534, 0, 0, 0.50073] 1804 }, 1805 "Main-Bold": { 1806 "32": [0, 0, 0, 0, 0.25], 1807 "33": [0, 0.69444, 0, 0, 0.35], 1808 "34": [0, 0.69444, 0, 0, 0.60278], 1809 "35": [0.19444, 0.69444, 0, 0, 0.95833], 1810 "36": [0.05556, 0.75, 0, 0, 0.575], 1811 "37": [0.05556, 0.75, 0, 0, 0.95833], 1812 "38": [0, 0.69444, 0, 0, 0.89444], 1813 "39": [0, 0.69444, 0, 0, 0.31944], 1814 "40": [0.25, 0.75, 0, 0, 0.44722], 1815 "41": [0.25, 0.75, 0, 0, 0.44722], 1816 "42": [0, 0.75, 0, 0, 0.575], 1817 "43": [0.13333, 0.63333, 0, 0, 0.89444], 1818 "44": [0.19444, 0.15556, 0, 0, 0.31944], 1819 "45": [0, 0.44444, 0, 0, 0.38333], 1820 "46": [0, 0.15556, 0, 0, 0.31944], 1821 "47": [0.25, 0.75, 0, 0, 0.575], 1822 "48": [0, 0.64444, 0, 0, 0.575], 1823 "49": [0, 0.64444, 0, 0, 0.575], 1824 "50": [0, 0.64444, 0, 0, 0.575], 1825 "51": [0, 0.64444, 0, 0, 0.575], 1826 "52": [0, 0.64444, 0, 0, 0.575], 1827 "53": [0, 0.64444, 0, 0, 0.575], 1828 "54": [0, 0.64444, 0, 0, 0.575], 1829 "55": [0, 0.64444, 0, 0, 0.575], 1830 "56": [0, 0.64444, 0, 0, 0.575], 1831 "57": [0, 0.64444, 0, 0, 0.575], 1832 "58": [0, 0.44444, 0, 0, 0.31944], 1833 "59": [0.19444, 0.44444, 0, 0, 0.31944], 1834 "60": [0.08556, 0.58556, 0, 0, 0.89444], 1835 "61": [-0.10889, 0.39111, 0, 0, 0.89444], 1836 "62": [0.08556, 0.58556, 0, 0, 0.89444], 1837 "63": [0, 0.69444, 0, 0, 0.54305], 1838 "64": [0, 0.69444, 0, 0, 0.89444], 1839 "65": [0, 0.68611, 0, 0, 0.86944], 1840 "66": [0, 0.68611, 0, 0, 0.81805], 1841 "67": [0, 0.68611, 0, 0, 0.83055], 1842 "68": [0, 0.68611, 0, 0, 0.88194], 1843 "69": [0, 0.68611, 0, 0, 0.75555], 1844 "70": [0, 0.68611, 0, 0, 0.72361], 1845 "71": [0, 0.68611, 0, 0, 0.90416], 1846 "72": [0, 0.68611, 0, 0, 0.9], 1847 "73": [0, 0.68611, 0, 0, 0.43611], 1848 "74": [0, 0.68611, 0, 0, 0.59444], 1849 "75": [0, 0.68611, 0, 0, 0.90138], 1850 "76": [0, 0.68611, 0, 0, 0.69166], 1851 "77": [0, 0.68611, 0, 0, 1.09166], 1852 "78": [0, 0.68611, 0, 0, 0.9], 1853 "79": [0, 0.68611, 0, 0, 0.86388], 1854 "80": [0, 0.68611, 0, 0, 0.78611], 1855 "81": [0.19444, 0.68611, 0, 0, 0.86388], 1856 "82": [0, 0.68611, 0, 0, 0.8625], 1857 "83": [0, 0.68611, 0, 0, 0.63889], 1858 "84": [0, 0.68611, 0, 0, 0.8], 1859 "85": [0, 0.68611, 0, 0, 0.88472], 1860 "86": [0, 0.68611, 0.01597, 0, 0.86944], 1861 "87": [0, 0.68611, 0.01597, 0, 1.18888], 1862 "88": [0, 0.68611, 0, 0, 0.86944], 1863 "89": [0, 0.68611, 0.02875, 0, 0.86944], 1864 "90": [0, 0.68611, 0, 0, 0.70277], 1865 "91": [0.25, 0.75, 0, 0, 0.31944], 1866 "92": [0.25, 0.75, 0, 0, 0.575], 1867 "93": [0.25, 0.75, 0, 0, 0.31944], 1868 "94": [0, 0.69444, 0, 0, 0.575], 1869 "95": [0.31, 0.13444, 0.03194, 0, 0.575], 1870 "97": [0, 0.44444, 0, 0, 0.55902], 1871 "98": [0, 0.69444, 0, 0, 0.63889], 1872 "99": [0, 0.44444, 0, 0, 0.51111], 1873 "100": [0, 0.69444, 0, 0, 0.63889], 1874 "101": [0, 0.44444, 0, 0, 0.52708], 1875 "102": [0, 0.69444, 0.10903, 0, 0.35139], 1876 "103": [0.19444, 0.44444, 0.01597, 0, 0.575], 1877 "104": [0, 0.69444, 0, 0, 0.63889], 1878 "105": [0, 0.69444, 0, 0, 0.31944], 1879 "106": [0.19444, 0.69444, 0, 0, 0.35139], 1880 "107": [0, 0.69444, 0, 0, 0.60694], 1881 "108": [0, 0.69444, 0, 0, 0.31944], 1882 "109": [0, 0.44444, 0, 0, 0.95833], 1883 "110": [0, 0.44444, 0, 0, 0.63889], 1884 "111": [0, 0.44444, 0, 0, 0.575], 1885 "112": [0.19444, 0.44444, 0, 0, 0.63889], 1886 "113": [0.19444, 0.44444, 0, 0, 0.60694], 1887 "114": [0, 0.44444, 0, 0, 0.47361], 1888 "115": [0, 0.44444, 0, 0, 0.45361], 1889 "116": [0, 0.63492, 0, 0, 0.44722], 1890 "117": [0, 0.44444, 0, 0, 0.63889], 1891 "118": [0, 0.44444, 0.01597, 0, 0.60694], 1892 "119": [0, 0.44444, 0.01597, 0, 0.83055], 1893 "120": [0, 0.44444, 0, 0, 0.60694], 1894 "121": [0.19444, 0.44444, 0.01597, 0, 0.60694], 1895 "122": [0, 0.44444, 0, 0, 0.51111], 1896 "123": [0.25, 0.75, 0, 0, 0.575], 1897 "124": [0.25, 0.75, 0, 0, 0.31944], 1898 "125": [0.25, 0.75, 0, 0, 0.575], 1899 "126": [0.35, 0.34444, 0, 0, 0.575], 1900 "160": [0, 0, 0, 0, 0.25], 1901 "163": [0, 0.69444, 0, 0, 0.86853], 1902 "168": [0, 0.69444, 0, 0, 0.575], 1903 "172": [0, 0.44444, 0, 0, 0.76666], 1904 "176": [0, 0.69444, 0, 0, 0.86944], 1905 "177": [0.13333, 0.63333, 0, 0, 0.89444], 1906 "184": [0.17014, 0, 0, 0, 0.51111], 1907 "198": [0, 0.68611, 0, 0, 1.04166], 1908 "215": [0.13333, 0.63333, 0, 0, 0.89444], 1909 "216": [0.04861, 0.73472, 0, 0, 0.89444], 1910 "223": [0, 0.69444, 0, 0, 0.59722], 1911 "230": [0, 0.44444, 0, 0, 0.83055], 1912 "247": [0.13333, 0.63333, 0, 0, 0.89444], 1913 "248": [0.09722, 0.54167, 0, 0, 0.575], 1914 "305": [0, 0.44444, 0, 0, 0.31944], 1915 "338": [0, 0.68611, 0, 0, 1.16944], 1916 "339": [0, 0.44444, 0, 0, 0.89444], 1917 "567": [0.19444, 0.44444, 0, 0, 0.35139], 1918 "710": [0, 0.69444, 0, 0, 0.575], 1919 "711": [0, 0.63194, 0, 0, 0.575], 1920 "713": [0, 0.59611, 0, 0, 0.575], 1921 "714": [0, 0.69444, 0, 0, 0.575], 1922 "715": [0, 0.69444, 0, 0, 0.575], 1923 "728": [0, 0.69444, 0, 0, 0.575], 1924 "729": [0, 0.69444, 0, 0, 0.31944], 1925 "730": [0, 0.69444, 0, 0, 0.86944], 1926 "732": [0, 0.69444, 0, 0, 0.575], 1927 "733": [0, 0.69444, 0, 0, 0.575], 1928 "915": [0, 0.68611, 0, 0, 0.69166], 1929 "916": [0, 0.68611, 0, 0, 0.95833], 1930 "920": [0, 0.68611, 0, 0, 0.89444], 1931 "923": [0, 0.68611, 0, 0, 0.80555], 1932 "926": [0, 0.68611, 0, 0, 0.76666], 1933 "928": [0, 0.68611, 0, 0, 0.9], 1934 "931": [0, 0.68611, 0, 0, 0.83055], 1935 "933": [0, 0.68611, 0, 0, 0.89444], 1936 "934": [0, 0.68611, 0, 0, 0.83055], 1937 "936": [0, 0.68611, 0, 0, 0.89444], 1938 "937": [0, 0.68611, 0, 0, 0.83055], 1939 "8211": [0, 0.44444, 0.03194, 0, 0.575], 1940 "8212": [0, 0.44444, 0.03194, 0, 1.14999], 1941 "8216": [0, 0.69444, 0, 0, 0.31944], 1942 "8217": [0, 0.69444, 0, 0, 0.31944], 1943 "8220": [0, 0.69444, 0, 0, 0.60278], 1944 "8221": [0, 0.69444, 0, 0, 0.60278], 1945 "8224": [0.19444, 0.69444, 0, 0, 0.51111], 1946 "8225": [0.19444, 0.69444, 0, 0, 0.51111], 1947 "8242": [0, 0.55556, 0, 0, 0.34444], 1948 "8407": [0, 0.72444, 0.15486, 0, 0.575], 1949 "8463": [0, 0.69444, 0, 0, 0.66759], 1950 "8465": [0, 0.69444, 0, 0, 0.83055], 1951 "8467": [0, 0.69444, 0, 0, 0.47361], 1952 "8472": [0.19444, 0.44444, 0, 0, 0.74027], 1953 "8476": [0, 0.69444, 0, 0, 0.83055], 1954 "8501": [0, 0.69444, 0, 0, 0.70277], 1955 "8592": [-0.10889, 0.39111, 0, 0, 1.14999], 1956 "8593": [0.19444, 0.69444, 0, 0, 0.575], 1957 "8594": [-0.10889, 0.39111, 0, 0, 1.14999], 1958 "8595": [0.19444, 0.69444, 0, 0, 0.575], 1959 "8596": [-0.10889, 0.39111, 0, 0, 1.14999], 1960 "8597": [0.25, 0.75, 0, 0, 0.575], 1961 "8598": [0.19444, 0.69444, 0, 0, 1.14999], 1962 "8599": [0.19444, 0.69444, 0, 0, 1.14999], 1963 "8600": [0.19444, 0.69444, 0, 0, 1.14999], 1964 "8601": [0.19444, 0.69444, 0, 0, 1.14999], 1965 "8636": [-0.10889, 0.39111, 0, 0, 1.14999], 1966 "8637": [-0.10889, 0.39111, 0, 0, 1.14999], 1967 "8640": [-0.10889, 0.39111, 0, 0, 1.14999], 1968 "8641": [-0.10889, 0.39111, 0, 0, 1.14999], 1969 "8656": [-0.10889, 0.39111, 0, 0, 1.14999], 1970 "8657": [0.19444, 0.69444, 0, 0, 0.70277], 1971 "8658": [-0.10889, 0.39111, 0, 0, 1.14999], 1972 "8659": [0.19444, 0.69444, 0, 0, 0.70277], 1973 "8660": [-0.10889, 0.39111, 0, 0, 1.14999], 1974 "8661": [0.25, 0.75, 0, 0, 0.70277], 1975 "8704": [0, 0.69444, 0, 0, 0.63889], 1976 "8706": [0, 0.69444, 0.06389, 0, 0.62847], 1977 "8707": [0, 0.69444, 0, 0, 0.63889], 1978 "8709": [0.05556, 0.75, 0, 0, 0.575], 1979 "8711": [0, 0.68611, 0, 0, 0.95833], 1980 "8712": [0.08556, 0.58556, 0, 0, 0.76666], 1981 "8715": [0.08556, 0.58556, 0, 0, 0.76666], 1982 "8722": [0.13333, 0.63333, 0, 0, 0.89444], 1983 "8723": [0.13333, 0.63333, 0, 0, 0.89444], 1984 "8725": [0.25, 0.75, 0, 0, 0.575], 1985 "8726": [0.25, 0.75, 0, 0, 0.575], 1986 "8727": [-0.02778, 0.47222, 0, 0, 0.575], 1987 "8728": [-0.02639, 0.47361, 0, 0, 0.575], 1988 "8729": [-0.02639, 0.47361, 0, 0, 0.575], 1989 "8730": [0.18, 0.82, 0, 0, 0.95833], 1990 "8733": [0, 0.44444, 0, 0, 0.89444], 1991 "8734": [0, 0.44444, 0, 0, 1.14999], 1992 "8736": [0, 0.69224, 0, 0, 0.72222], 1993 "8739": [0.25, 0.75, 0, 0, 0.31944], 1994 "8741": [0.25, 0.75, 0, 0, 0.575], 1995 "8743": [0, 0.55556, 0, 0, 0.76666], 1996 "8744": [0, 0.55556, 0, 0, 0.76666], 1997 "8745": [0, 0.55556, 0, 0, 0.76666], 1998 "8746": [0, 0.55556, 0, 0, 0.76666], 1999 "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875], 2000 "8764": [-0.10889, 0.39111, 0, 0, 0.89444], 2001 "8768": [0.19444, 0.69444, 0, 0, 0.31944], 2002 "8771": [0.00222, 0.50222, 0, 0, 0.89444], 2003 "8776": [0.02444, 0.52444, 0, 0, 0.89444], 2004 "8781": [0.00222, 0.50222, 0, 0, 0.89444], 2005 "8801": [0.00222, 0.50222, 0, 0, 0.89444], 2006 "8804": [0.19667, 0.69667, 0, 0, 0.89444], 2007 "8805": [0.19667, 0.69667, 0, 0, 0.89444], 2008 "8810": [0.08556, 0.58556, 0, 0, 1.14999], 2009 "8811": [0.08556, 0.58556, 0, 0, 1.14999], 2010 "8826": [0.08556, 0.58556, 0, 0, 0.89444], 2011 "8827": [0.08556, 0.58556, 0, 0, 0.89444], 2012 "8834": [0.08556, 0.58556, 0, 0, 0.89444], 2013 "8835": [0.08556, 0.58556, 0, 0, 0.89444], 2014 "8838": [0.19667, 0.69667, 0, 0, 0.89444], 2015 "8839": [0.19667, 0.69667, 0, 0, 0.89444], 2016 "8846": [0, 0.55556, 0, 0, 0.76666], 2017 "8849": [0.19667, 0.69667, 0, 0, 0.89444], 2018 "8850": [0.19667, 0.69667, 0, 0, 0.89444], 2019 "8851": [0, 0.55556, 0, 0, 0.76666], 2020 "8852": [0, 0.55556, 0, 0, 0.76666], 2021 "8853": [0.13333, 0.63333, 0, 0, 0.89444], 2022 "8854": [0.13333, 0.63333, 0, 0, 0.89444], 2023 "8855": [0.13333, 0.63333, 0, 0, 0.89444], 2024 "8856": [0.13333, 0.63333, 0, 0, 0.89444], 2025 "8857": [0.13333, 0.63333, 0, 0, 0.89444], 2026 "8866": [0, 0.69444, 0, 0, 0.70277], 2027 "8867": [0, 0.69444, 0, 0, 0.70277], 2028 "8868": [0, 0.69444, 0, 0, 0.89444], 2029 "8869": [0, 0.69444, 0, 0, 0.89444], 2030 "8900": [-0.02639, 0.47361, 0, 0, 0.575], 2031 "8901": [-0.02639, 0.47361, 0, 0, 0.31944], 2032 "8902": [-0.02778, 0.47222, 0, 0, 0.575], 2033 "8968": [0.25, 0.75, 0, 0, 0.51111], 2034 "8969": [0.25, 0.75, 0, 0, 0.51111], 2035 "8970": [0.25, 0.75, 0, 0, 0.51111], 2036 "8971": [0.25, 0.75, 0, 0, 0.51111], 2037 "8994": [-0.13889, 0.36111, 0, 0, 1.14999], 2038 "8995": [-0.13889, 0.36111, 0, 0, 1.14999], 2039 "9651": [0.19444, 0.69444, 0, 0, 1.02222], 2040 "9657": [-0.02778, 0.47222, 0, 0, 0.575], 2041 "9661": [0.19444, 0.69444, 0, 0, 1.02222], 2042 "9667": [-0.02778, 0.47222, 0, 0, 0.575], 2043 "9711": [0.19444, 0.69444, 0, 0, 1.14999], 2044 "9824": [0.12963, 0.69444, 0, 0, 0.89444], 2045 "9825": [0.12963, 0.69444, 0, 0, 0.89444], 2046 "9826": [0.12963, 0.69444, 0, 0, 0.89444], 2047 "9827": [0.12963, 0.69444, 0, 0, 0.89444], 2048 "9837": [0, 0.75, 0, 0, 0.44722], 2049 "9838": [0.19444, 0.69444, 0, 0, 0.44722], 2050 "9839": [0.19444, 0.69444, 0, 0, 0.44722], 2051 "10216": [0.25, 0.75, 0, 0, 0.44722], 2052 "10217": [0.25, 0.75, 0, 0, 0.44722], 2053 "10815": [0, 0.68611, 0, 0, 0.9], 2054 "10927": [0.19667, 0.69667, 0, 0, 0.89444], 2055 "10928": [0.19667, 0.69667, 0, 0, 0.89444], 2056 "57376": [0.19444, 0.69444, 0, 0, 0] 2057 }, 2058 "Main-BoldItalic": { 2059 "32": [0, 0, 0, 0, 0.25], 2060 "33": [0, 0.69444, 0.11417, 0, 0.38611], 2061 "34": [0, 0.69444, 0.07939, 0, 0.62055], 2062 "35": [0.19444, 0.69444, 0.06833, 0, 0.94444], 2063 "37": [0.05556, 0.75, 0.12861, 0, 0.94444], 2064 "38": [0, 0.69444, 0.08528, 0, 0.88555], 2065 "39": [0, 0.69444, 0.12945, 0, 0.35555], 2066 "40": [0.25, 0.75, 0.15806, 0, 0.47333], 2067 "41": [0.25, 0.75, 0.03306, 0, 0.47333], 2068 "42": [0, 0.75, 0.14333, 0, 0.59111], 2069 "43": [0.10333, 0.60333, 0.03306, 0, 0.88555], 2070 "44": [0.19444, 0.14722, 0, 0, 0.35555], 2071 "45": [0, 0.44444, 0.02611, 0, 0.41444], 2072 "46": [0, 0.14722, 0, 0, 0.35555], 2073 "47": [0.25, 0.75, 0.15806, 0, 0.59111], 2074 "48": [0, 0.64444, 0.13167, 0, 0.59111], 2075 "49": [0, 0.64444, 0.13167, 0, 0.59111], 2076 "50": [0, 0.64444, 0.13167, 0, 0.59111], 2077 "51": [0, 0.64444, 0.13167, 0, 0.59111], 2078 "52": [0.19444, 0.64444, 0.13167, 0, 0.59111], 2079 "53": [0, 0.64444, 0.13167, 0, 0.59111], 2080 "54": [0, 0.64444, 0.13167, 0, 0.59111], 2081 "55": [0.19444, 0.64444, 0.13167, 0, 0.59111], 2082 "56": [0, 0.64444, 0.13167, 0, 0.59111], 2083 "57": [0, 0.64444, 0.13167, 0, 0.59111], 2084 "58": [0, 0.44444, 0.06695, 0, 0.35555], 2085 "59": [0.19444, 0.44444, 0.06695, 0, 0.35555], 2086 "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555], 2087 "63": [0, 0.69444, 0.11472, 0, 0.59111], 2088 "64": [0, 0.69444, 0.09208, 0, 0.88555], 2089 "65": [0, 0.68611, 0, 0, 0.86555], 2090 "66": [0, 0.68611, 0.0992, 0, 0.81666], 2091 "67": [0, 0.68611, 0.14208, 0, 0.82666], 2092 "68": [0, 0.68611, 0.09062, 0, 0.87555], 2093 "69": [0, 0.68611, 0.11431, 0, 0.75666], 2094 "70": [0, 0.68611, 0.12903, 0, 0.72722], 2095 "71": [0, 0.68611, 0.07347, 0, 0.89527], 2096 "72": [0, 0.68611, 0.17208, 0, 0.8961], 2097 "73": [0, 0.68611, 0.15681, 0, 0.47166], 2098 "74": [0, 0.68611, 0.145, 0, 0.61055], 2099 "75": [0, 0.68611, 0.14208, 0, 0.89499], 2100 "76": [0, 0.68611, 0, 0, 0.69777], 2101 "77": [0, 0.68611, 0.17208, 0, 1.07277], 2102 "78": [0, 0.68611, 0.17208, 0, 0.8961], 2103 "79": [0, 0.68611, 0.09062, 0, 0.85499], 2104 "80": [0, 0.68611, 0.0992, 0, 0.78721], 2105 "81": [0.19444, 0.68611, 0.09062, 0, 0.85499], 2106 "82": [0, 0.68611, 0.02559, 0, 0.85944], 2107 "83": [0, 0.68611, 0.11264, 0, 0.64999], 2108 "84": [0, 0.68611, 0.12903, 0, 0.7961], 2109 "85": [0, 0.68611, 0.17208, 0, 0.88083], 2110 "86": [0, 0.68611, 0.18625, 0, 0.86555], 2111 "87": [0, 0.68611, 0.18625, 0, 1.15999], 2112 "88": [0, 0.68611, 0.15681, 0, 0.86555], 2113 "89": [0, 0.68611, 0.19803, 0, 0.86555], 2114 "90": [0, 0.68611, 0.14208, 0, 0.70888], 2115 "91": [0.25, 0.75, 0.1875, 0, 0.35611], 2116 "93": [0.25, 0.75, 0.09972, 0, 0.35611], 2117 "94": [0, 0.69444, 0.06709, 0, 0.59111], 2118 "95": [0.31, 0.13444, 0.09811, 0, 0.59111], 2119 "97": [0, 0.44444, 0.09426, 0, 0.59111], 2120 "98": [0, 0.69444, 0.07861, 0, 0.53222], 2121 "99": [0, 0.44444, 0.05222, 0, 0.53222], 2122 "100": [0, 0.69444, 0.10861, 0, 0.59111], 2123 "101": [0, 0.44444, 0.085, 0, 0.53222], 2124 "102": [0.19444, 0.69444, 0.21778, 0, 0.4], 2125 "103": [0.19444, 0.44444, 0.105, 0, 0.53222], 2126 "104": [0, 0.69444, 0.09426, 0, 0.59111], 2127 "105": [0, 0.69326, 0.11387, 0, 0.35555], 2128 "106": [0.19444, 0.69326, 0.1672, 0, 0.35555], 2129 "107": [0, 0.69444, 0.11111, 0, 0.53222], 2130 "108": [0, 0.69444, 0.10861, 0, 0.29666], 2131 "109": [0, 0.44444, 0.09426, 0, 0.94444], 2132 "110": [0, 0.44444, 0.09426, 0, 0.64999], 2133 "111": [0, 0.44444, 0.07861, 0, 0.59111], 2134 "112": [0.19444, 0.44444, 0.07861, 0, 0.59111], 2135 "113": [0.19444, 0.44444, 0.105, 0, 0.53222], 2136 "114": [0, 0.44444, 0.11111, 0, 0.50167], 2137 "115": [0, 0.44444, 0.08167, 0, 0.48694], 2138 "116": [0, 0.63492, 0.09639, 0, 0.385], 2139 "117": [0, 0.44444, 0.09426, 0, 0.62055], 2140 "118": [0, 0.44444, 0.11111, 0, 0.53222], 2141 "119": [0, 0.44444, 0.11111, 0, 0.76777], 2142 "120": [0, 0.44444, 0.12583, 0, 0.56055], 2143 "121": [0.19444, 0.44444, 0.105, 0, 0.56166], 2144 "122": [0, 0.44444, 0.13889, 0, 0.49055], 2145 "126": [0.35, 0.34444, 0.11472, 0, 0.59111], 2146 "160": [0, 0, 0, 0, 0.25], 2147 "168": [0, 0.69444, 0.11473, 0, 0.59111], 2148 "176": [0, 0.69444, 0, 0, 0.94888], 2149 "184": [0.17014, 0, 0, 0, 0.53222], 2150 "198": [0, 0.68611, 0.11431, 0, 1.02277], 2151 "216": [0.04861, 0.73472, 0.09062, 0, 0.88555], 2152 "223": [0.19444, 0.69444, 0.09736, 0, 0.665], 2153 "230": [0, 0.44444, 0.085, 0, 0.82666], 2154 "248": [0.09722, 0.54167, 0.09458, 0, 0.59111], 2155 "305": [0, 0.44444, 0.09426, 0, 0.35555], 2156 "338": [0, 0.68611, 0.11431, 0, 1.14054], 2157 "339": [0, 0.44444, 0.085, 0, 0.82666], 2158 "567": [0.19444, 0.44444, 0.04611, 0, 0.385], 2159 "710": [0, 0.69444, 0.06709, 0, 0.59111], 2160 "711": [0, 0.63194, 0.08271, 0, 0.59111], 2161 "713": [0, 0.59444, 0.10444, 0, 0.59111], 2162 "714": [0, 0.69444, 0.08528, 0, 0.59111], 2163 "715": [0, 0.69444, 0, 0, 0.59111], 2164 "728": [0, 0.69444, 0.10333, 0, 0.59111], 2165 "729": [0, 0.69444, 0.12945, 0, 0.35555], 2166 "730": [0, 0.69444, 0, 0, 0.94888], 2167 "732": [0, 0.69444, 0.11472, 0, 0.59111], 2168 "733": [0, 0.69444, 0.11472, 0, 0.59111], 2169 "915": [0, 0.68611, 0.12903, 0, 0.69777], 2170 "916": [0, 0.68611, 0, 0, 0.94444], 2171 "920": [0, 0.68611, 0.09062, 0, 0.88555], 2172 "923": [0, 0.68611, 0, 0, 0.80666], 2173 "926": [0, 0.68611, 0.15092, 0, 0.76777], 2174 "928": [0, 0.68611, 0.17208, 0, 0.8961], 2175 "931": [0, 0.68611, 0.11431, 0, 0.82666], 2176 "933": [0, 0.68611, 0.10778, 0, 0.88555], 2177 "934": [0, 0.68611, 0.05632, 0, 0.82666], 2178 "936": [0, 0.68611, 0.10778, 0, 0.88555], 2179 "937": [0, 0.68611, 0.0992, 0, 0.82666], 2180 "8211": [0, 0.44444, 0.09811, 0, 0.59111], 2181 "8212": [0, 0.44444, 0.09811, 0, 1.18221], 2182 "8216": [0, 0.69444, 0.12945, 0, 0.35555], 2183 "8217": [0, 0.69444, 0.12945, 0, 0.35555], 2184 "8220": [0, 0.69444, 0.16772, 0, 0.62055], 2185 "8221": [0, 0.69444, 0.07939, 0, 0.62055] 2186 }, 2187 "Main-Italic": { 2188 "32": [0, 0, 0, 0, 0.25], 2189 "33": [0, 0.69444, 0.12417, 0, 0.30667], 2190 "34": [0, 0.69444, 0.06961, 0, 0.51444], 2191 "35": [0.19444, 0.69444, 0.06616, 0, 0.81777], 2192 "37": [0.05556, 0.75, 0.13639, 0, 0.81777], 2193 "38": [0, 0.69444, 0.09694, 0, 0.76666], 2194 "39": [0, 0.69444, 0.12417, 0, 0.30667], 2195 "40": [0.25, 0.75, 0.16194, 0, 0.40889], 2196 "41": [0.25, 0.75, 0.03694, 0, 0.40889], 2197 "42": [0, 0.75, 0.14917, 0, 0.51111], 2198 "43": [0.05667, 0.56167, 0.03694, 0, 0.76666], 2199 "44": [0.19444, 0.10556, 0, 0, 0.30667], 2200 "45": [0, 0.43056, 0.02826, 0, 0.35778], 2201 "46": [0, 0.10556, 0, 0, 0.30667], 2202 "47": [0.25, 0.75, 0.16194, 0, 0.51111], 2203 "48": [0, 0.64444, 0.13556, 0, 0.51111], 2204 "49": [0, 0.64444, 0.13556, 0, 0.51111], 2205 "50": [0, 0.64444, 0.13556, 0, 0.51111], 2206 "51": [0, 0.64444, 0.13556, 0, 0.51111], 2207 "52": [0.19444, 0.64444, 0.13556, 0, 0.51111], 2208 "53": [0, 0.64444, 0.13556, 0, 0.51111], 2209 "54": [0, 0.64444, 0.13556, 0, 0.51111], 2210 "55": [0.19444, 0.64444, 0.13556, 0, 0.51111], 2211 "56": [0, 0.64444, 0.13556, 0, 0.51111], 2212 "57": [0, 0.64444, 0.13556, 0, 0.51111], 2213 "58": [0, 0.43056, 0.0582, 0, 0.30667], 2214 "59": [0.19444, 0.43056, 0.0582, 0, 0.30667], 2215 "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666], 2216 "63": [0, 0.69444, 0.1225, 0, 0.51111], 2217 "64": [0, 0.69444, 0.09597, 0, 0.76666], 2218 "65": [0, 0.68333, 0, 0, 0.74333], 2219 "66": [0, 0.68333, 0.10257, 0, 0.70389], 2220 "67": [0, 0.68333, 0.14528, 0, 0.71555], 2221 "68": [0, 0.68333, 0.09403, 0, 0.755], 2222 "69": [0, 0.68333, 0.12028, 0, 0.67833], 2223 "70": [0, 0.68333, 0.13305, 0, 0.65277], 2224 "71": [0, 0.68333, 0.08722, 0, 0.77361], 2225 "72": [0, 0.68333, 0.16389, 0, 0.74333], 2226 "73": [0, 0.68333, 0.15806, 0, 0.38555], 2227 "74": [0, 0.68333, 0.14028, 0, 0.525], 2228 "75": [0, 0.68333, 0.14528, 0, 0.76888], 2229 "76": [0, 0.68333, 0, 0, 0.62722], 2230 "77": [0, 0.68333, 0.16389, 0, 0.89666], 2231 "78": [0, 0.68333, 0.16389, 0, 0.74333], 2232 "79": [0, 0.68333, 0.09403, 0, 0.76666], 2233 "80": [0, 0.68333, 0.10257, 0, 0.67833], 2234 "81": [0.19444, 0.68333, 0.09403, 0, 0.76666], 2235 "82": [0, 0.68333, 0.03868, 0, 0.72944], 2236 "83": [0, 0.68333, 0.11972, 0, 0.56222], 2237 "84": [0, 0.68333, 0.13305, 0, 0.71555], 2238 "85": [0, 0.68333, 0.16389, 0, 0.74333], 2239 "86": [0, 0.68333, 0.18361, 0, 0.74333], 2240 "87": [0, 0.68333, 0.18361, 0, 0.99888], 2241 "88": [0, 0.68333, 0.15806, 0, 0.74333], 2242 "89": [0, 0.68333, 0.19383, 0, 0.74333], 2243 "90": [0, 0.68333, 0.14528, 0, 0.61333], 2244 "91": [0.25, 0.75, 0.1875, 0, 0.30667], 2245 "93": [0.25, 0.75, 0.10528, 0, 0.30667], 2246 "94": [0, 0.69444, 0.06646, 0, 0.51111], 2247 "95": [0.31, 0.12056, 0.09208, 0, 0.51111], 2248 "97": [0, 0.43056, 0.07671, 0, 0.51111], 2249 "98": [0, 0.69444, 0.06312, 0, 0.46], 2250 "99": [0, 0.43056, 0.05653, 0, 0.46], 2251 "100": [0, 0.69444, 0.10333, 0, 0.51111], 2252 "101": [0, 0.43056, 0.07514, 0, 0.46], 2253 "102": [0.19444, 0.69444, 0.21194, 0, 0.30667], 2254 "103": [0.19444, 0.43056, 0.08847, 0, 0.46], 2255 "104": [0, 0.69444, 0.07671, 0, 0.51111], 2256 "105": [0, 0.65536, 0.1019, 0, 0.30667], 2257 "106": [0.19444, 0.65536, 0.14467, 0, 0.30667], 2258 "107": [0, 0.69444, 0.10764, 0, 0.46], 2259 "108": [0, 0.69444, 0.10333, 0, 0.25555], 2260 "109": [0, 0.43056, 0.07671, 0, 0.81777], 2261 "110": [0, 0.43056, 0.07671, 0, 0.56222], 2262 "111": [0, 0.43056, 0.06312, 0, 0.51111], 2263 "112": [0.19444, 0.43056, 0.06312, 0, 0.51111], 2264 "113": [0.19444, 0.43056, 0.08847, 0, 0.46], 2265 "114": [0, 0.43056, 0.10764, 0, 0.42166], 2266 "115": [0, 0.43056, 0.08208, 0, 0.40889], 2267 "116": [0, 0.61508, 0.09486, 0, 0.33222], 2268 "117": [0, 0.43056, 0.07671, 0, 0.53666], 2269 "118": [0, 0.43056, 0.10764, 0, 0.46], 2270 "119": [0, 0.43056, 0.10764, 0, 0.66444], 2271 "120": [0, 0.43056, 0.12042, 0, 0.46389], 2272 "121": [0.19444, 0.43056, 0.08847, 0, 0.48555], 2273 "122": [0, 0.43056, 0.12292, 0, 0.40889], 2274 "126": [0.35, 0.31786, 0.11585, 0, 0.51111], 2275 "160": [0, 0, 0, 0, 0.25], 2276 "168": [0, 0.66786, 0.10474, 0, 0.51111], 2277 "176": [0, 0.69444, 0, 0, 0.83129], 2278 "184": [0.17014, 0, 0, 0, 0.46], 2279 "198": [0, 0.68333, 0.12028, 0, 0.88277], 2280 "216": [0.04861, 0.73194, 0.09403, 0, 0.76666], 2281 "223": [0.19444, 0.69444, 0.10514, 0, 0.53666], 2282 "230": [0, 0.43056, 0.07514, 0, 0.71555], 2283 "248": [0.09722, 0.52778, 0.09194, 0, 0.51111], 2284 "338": [0, 0.68333, 0.12028, 0, 0.98499], 2285 "339": [0, 0.43056, 0.07514, 0, 0.71555], 2286 "710": [0, 0.69444, 0.06646, 0, 0.51111], 2287 "711": [0, 0.62847, 0.08295, 0, 0.51111], 2288 "713": [0, 0.56167, 0.10333, 0, 0.51111], 2289 "714": [0, 0.69444, 0.09694, 0, 0.51111], 2290 "715": [0, 0.69444, 0, 0, 0.51111], 2291 "728": [0, 0.69444, 0.10806, 0, 0.51111], 2292 "729": [0, 0.66786, 0.11752, 0, 0.30667], 2293 "730": [0, 0.69444, 0, 0, 0.83129], 2294 "732": [0, 0.66786, 0.11585, 0, 0.51111], 2295 "733": [0, 0.69444, 0.1225, 0, 0.51111], 2296 "915": [0, 0.68333, 0.13305, 0, 0.62722], 2297 "916": [0, 0.68333, 0, 0, 0.81777], 2298 "920": [0, 0.68333, 0.09403, 0, 0.76666], 2299 "923": [0, 0.68333, 0, 0, 0.69222], 2300 "926": [0, 0.68333, 0.15294, 0, 0.66444], 2301 "928": [0, 0.68333, 0.16389, 0, 0.74333], 2302 "931": [0, 0.68333, 0.12028, 0, 0.71555], 2303 "933": [0, 0.68333, 0.11111, 0, 0.76666], 2304 "934": [0, 0.68333, 0.05986, 0, 0.71555], 2305 "936": [0, 0.68333, 0.11111, 0, 0.76666], 2306 "937": [0, 0.68333, 0.10257, 0, 0.71555], 2307 "8211": [0, 0.43056, 0.09208, 0, 0.51111], 2308 "8212": [0, 0.43056, 0.09208, 0, 1.02222], 2309 "8216": [0, 0.69444, 0.12417, 0, 0.30667], 2310 "8217": [0, 0.69444, 0.12417, 0, 0.30667], 2311 "8220": [0, 0.69444, 0.1685, 0, 0.51444], 2312 "8221": [0, 0.69444, 0.06961, 0, 0.51444], 2313 "8463": [0, 0.68889, 0, 0, 0.54028] 2314 }, 2315 "Main-Regular": { 2316 "32": [0, 0, 0, 0, 0.25], 2317 "33": [0, 0.69444, 0, 0, 0.27778], 2318 "34": [0, 0.69444, 0, 0, 0.5], 2319 "35": [0.19444, 0.69444, 0, 0, 0.83334], 2320 "36": [0.05556, 0.75, 0, 0, 0.5], 2321 "37": [0.05556, 0.75, 0, 0, 0.83334], 2322 "38": [0, 0.69444, 0, 0, 0.77778], 2323 "39": [0, 0.69444, 0, 0, 0.27778], 2324 "40": [0.25, 0.75, 0, 0, 0.38889], 2325 "41": [0.25, 0.75, 0, 0, 0.38889], 2326 "42": [0, 0.75, 0, 0, 0.5], 2327 "43": [0.08333, 0.58333, 0, 0, 0.77778], 2328 "44": [0.19444, 0.10556, 0, 0, 0.27778], 2329 "45": [0, 0.43056, 0, 0, 0.33333], 2330 "46": [0, 0.10556, 0, 0, 0.27778], 2331 "47": [0.25, 0.75, 0, 0, 0.5], 2332 "48": [0, 0.64444, 0, 0, 0.5], 2333 "49": [0, 0.64444, 0, 0, 0.5], 2334 "50": [0, 0.64444, 0, 0, 0.5], 2335 "51": [0, 0.64444, 0, 0, 0.5], 2336 "52": [0, 0.64444, 0, 0, 0.5], 2337 "53": [0, 0.64444, 0, 0, 0.5], 2338 "54": [0, 0.64444, 0, 0, 0.5], 2339 "55": [0, 0.64444, 0, 0, 0.5], 2340 "56": [0, 0.64444, 0, 0, 0.5], 2341 "57": [0, 0.64444, 0, 0, 0.5], 2342 "58": [0, 0.43056, 0, 0, 0.27778], 2343 "59": [0.19444, 0.43056, 0, 0, 0.27778], 2344 "60": [0.0391, 0.5391, 0, 0, 0.77778], 2345 "61": [-0.13313, 0.36687, 0, 0, 0.77778], 2346 "62": [0.0391, 0.5391, 0, 0, 0.77778], 2347 "63": [0, 0.69444, 0, 0, 0.47222], 2348 "64": [0, 0.69444, 0, 0, 0.77778], 2349 "65": [0, 0.68333, 0, 0, 0.75], 2350 "66": [0, 0.68333, 0, 0, 0.70834], 2351 "67": [0, 0.68333, 0, 0, 0.72222], 2352 "68": [0, 0.68333, 0, 0, 0.76389], 2353 "69": [0, 0.68333, 0, 0, 0.68056], 2354 "70": [0, 0.68333, 0, 0, 0.65278], 2355 "71": [0, 0.68333, 0, 0, 0.78472], 2356 "72": [0, 0.68333, 0, 0, 0.75], 2357 "73": [0, 0.68333, 0, 0, 0.36111], 2358 "74": [0, 0.68333, 0, 0, 0.51389], 2359 "75": [0, 0.68333, 0, 0, 0.77778], 2360 "76": [0, 0.68333, 0, 0, 0.625], 2361 "77": [0, 0.68333, 0, 0, 0.91667], 2362 "78": [0, 0.68333, 0, 0, 0.75], 2363 "79": [0, 0.68333, 0, 0, 0.77778], 2364 "80": [0, 0.68333, 0, 0, 0.68056], 2365 "81": [0.19444, 0.68333, 0, 0, 0.77778], 2366 "82": [0, 0.68333, 0, 0, 0.73611], 2367 "83": [0, 0.68333, 0, 0, 0.55556], 2368 "84": [0, 0.68333, 0, 0, 0.72222], 2369 "85": [0, 0.68333, 0, 0, 0.75], 2370 "86": [0, 0.68333, 0.01389, 0, 0.75], 2371 "87": [0, 0.68333, 0.01389, 0, 1.02778], 2372 "88": [0, 0.68333, 0, 0, 0.75], 2373 "89": [0, 0.68333, 0.025, 0, 0.75], 2374 "90": [0, 0.68333, 0, 0, 0.61111], 2375 "91": [0.25, 0.75, 0, 0, 0.27778], 2376 "92": [0.25, 0.75, 0, 0, 0.5], 2377 "93": [0.25, 0.75, 0, 0, 0.27778], 2378 "94": [0, 0.69444, 0, 0, 0.5], 2379 "95": [0.31, 0.12056, 0.02778, 0, 0.5], 2380 "97": [0, 0.43056, 0, 0, 0.5], 2381 "98": [0, 0.69444, 0, 0, 0.55556], 2382 "99": [0, 0.43056, 0, 0, 0.44445], 2383 "100": [0, 0.69444, 0, 0, 0.55556], 2384 "101": [0, 0.43056, 0, 0, 0.44445], 2385 "102": [0, 0.69444, 0.07778, 0, 0.30556], 2386 "103": [0.19444, 0.43056, 0.01389, 0, 0.5], 2387 "104": [0, 0.69444, 0, 0, 0.55556], 2388 "105": [0, 0.66786, 0, 0, 0.27778], 2389 "106": [0.19444, 0.66786, 0, 0, 0.30556], 2390 "107": [0, 0.69444, 0, 0, 0.52778], 2391 "108": [0, 0.69444, 0, 0, 0.27778], 2392 "109": [0, 0.43056, 0, 0, 0.83334], 2393 "110": [0, 0.43056, 0, 0, 0.55556], 2394 "111": [0, 0.43056, 0, 0, 0.5], 2395 "112": [0.19444, 0.43056, 0, 0, 0.55556], 2396 "113": [0.19444, 0.43056, 0, 0, 0.52778], 2397 "114": [0, 0.43056, 0, 0, 0.39167], 2398 "115": [0, 0.43056, 0, 0, 0.39445], 2399 "116": [0, 0.61508, 0, 0, 0.38889], 2400 "117": [0, 0.43056, 0, 0, 0.55556], 2401 "118": [0, 0.43056, 0.01389, 0, 0.52778], 2402 "119": [0, 0.43056, 0.01389, 0, 0.72222], 2403 "120": [0, 0.43056, 0, 0, 0.52778], 2404 "121": [0.19444, 0.43056, 0.01389, 0, 0.52778], 2405 "122": [0, 0.43056, 0, 0, 0.44445], 2406 "123": [0.25, 0.75, 0, 0, 0.5], 2407 "124": [0.25, 0.75, 0, 0, 0.27778], 2408 "125": [0.25, 0.75, 0, 0, 0.5], 2409 "126": [0.35, 0.31786, 0, 0, 0.5], 2410 "160": [0, 0, 0, 0, 0.25], 2411 "163": [0, 0.69444, 0, 0, 0.76909], 2412 "167": [0.19444, 0.69444, 0, 0, 0.44445], 2413 "168": [0, 0.66786, 0, 0, 0.5], 2414 "172": [0, 0.43056, 0, 0, 0.66667], 2415 "176": [0, 0.69444, 0, 0, 0.75], 2416 "177": [0.08333, 0.58333, 0, 0, 0.77778], 2417 "182": [0.19444, 0.69444, 0, 0, 0.61111], 2418 "184": [0.17014, 0, 0, 0, 0.44445], 2419 "198": [0, 0.68333, 0, 0, 0.90278], 2420 "215": [0.08333, 0.58333, 0, 0, 0.77778], 2421 "216": [0.04861, 0.73194, 0, 0, 0.77778], 2422 "223": [0, 0.69444, 0, 0, 0.5], 2423 "230": [0, 0.43056, 0, 0, 0.72222], 2424 "247": [0.08333, 0.58333, 0, 0, 0.77778], 2425 "248": [0.09722, 0.52778, 0, 0, 0.5], 2426 "305": [0, 0.43056, 0, 0, 0.27778], 2427 "338": [0, 0.68333, 0, 0, 1.01389], 2428 "339": [0, 0.43056, 0, 0, 0.77778], 2429 "567": [0.19444, 0.43056, 0, 0, 0.30556], 2430 "710": [0, 0.69444, 0, 0, 0.5], 2431 "711": [0, 0.62847, 0, 0, 0.5], 2432 "713": [0, 0.56778, 0, 0, 0.5], 2433 "714": [0, 0.69444, 0, 0, 0.5], 2434 "715": [0, 0.69444, 0, 0, 0.5], 2435 "728": [0, 0.69444, 0, 0, 0.5], 2436 "729": [0, 0.66786, 0, 0, 0.27778], 2437 "730": [0, 0.69444, 0, 0, 0.75], 2438 "732": [0, 0.66786, 0, 0, 0.5], 2439 "733": [0, 0.69444, 0, 0, 0.5], 2440 "915": [0, 0.68333, 0, 0, 0.625], 2441 "916": [0, 0.68333, 0, 0, 0.83334], 2442 "920": [0, 0.68333, 0, 0, 0.77778], 2443 "923": [0, 0.68333, 0, 0, 0.69445], 2444 "926": [0, 0.68333, 0, 0, 0.66667], 2445 "928": [0, 0.68333, 0, 0, 0.75], 2446 "931": [0, 0.68333, 0, 0, 0.72222], 2447 "933": [0, 0.68333, 0, 0, 0.77778], 2448 "934": [0, 0.68333, 0, 0, 0.72222], 2449 "936": [0, 0.68333, 0, 0, 0.77778], 2450 "937": [0, 0.68333, 0, 0, 0.72222], 2451 "8211": [0, 0.43056, 0.02778, 0, 0.5], 2452 "8212": [0, 0.43056, 0.02778, 0, 1.0], 2453 "8216": [0, 0.69444, 0, 0, 0.27778], 2454 "8217": [0, 0.69444, 0, 0, 0.27778], 2455 "8220": [0, 0.69444, 0, 0, 0.5], 2456 "8221": [0, 0.69444, 0, 0, 0.5], 2457 "8224": [0.19444, 0.69444, 0, 0, 0.44445], 2458 "8225": [0.19444, 0.69444, 0, 0, 0.44445], 2459 "8230": [0, 0.12, 0, 0, 1.172], 2460 "8242": [0, 0.55556, 0, 0, 0.275], 2461 "8407": [0, 0.71444, 0.15382, 0, 0.5], 2462 "8463": [0, 0.68889, 0, 0, 0.54028], 2463 "8465": [0, 0.69444, 0, 0, 0.72222], 2464 "8467": [0, 0.69444, 0, 0.11111, 0.41667], 2465 "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646], 2466 "8476": [0, 0.69444, 0, 0, 0.72222], 2467 "8501": [0, 0.69444, 0, 0, 0.61111], 2468 "8592": [-0.13313, 0.36687, 0, 0, 1.0], 2469 "8593": [0.19444, 0.69444, 0, 0, 0.5], 2470 "8594": [-0.13313, 0.36687, 0, 0, 1.0], 2471 "8595": [0.19444, 0.69444, 0, 0, 0.5], 2472 "8596": [-0.13313, 0.36687, 0, 0, 1.0], 2473 "8597": [0.25, 0.75, 0, 0, 0.5], 2474 "8598": [0.19444, 0.69444, 0, 0, 1.0], 2475 "8599": [0.19444, 0.69444, 0, 0, 1.0], 2476 "8600": [0.19444, 0.69444, 0, 0, 1.0], 2477 "8601": [0.19444, 0.69444, 0, 0, 1.0], 2478 "8614": [0.011, 0.511, 0, 0, 1.0], 2479 "8617": [0.011, 0.511, 0, 0, 1.126], 2480 "8618": [0.011, 0.511, 0, 0, 1.126], 2481 "8636": [-0.13313, 0.36687, 0, 0, 1.0], 2482 "8637": [-0.13313, 0.36687, 0, 0, 1.0], 2483 "8640": [-0.13313, 0.36687, 0, 0, 1.0], 2484 "8641": [-0.13313, 0.36687, 0, 0, 1.0], 2485 "8652": [0.011, 0.671, 0, 0, 1.0], 2486 "8656": [-0.13313, 0.36687, 0, 0, 1.0], 2487 "8657": [0.19444, 0.69444, 0, 0, 0.61111], 2488 "8658": [-0.13313, 0.36687, 0, 0, 1.0], 2489 "8659": [0.19444, 0.69444, 0, 0, 0.61111], 2490 "8660": [-0.13313, 0.36687, 0, 0, 1.0], 2491 "8661": [0.25, 0.75, 0, 0, 0.61111], 2492 "8704": [0, 0.69444, 0, 0, 0.55556], 2493 "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309], 2494 "8707": [0, 0.69444, 0, 0, 0.55556], 2495 "8709": [0.05556, 0.75, 0, 0, 0.5], 2496 "8711": [0, 0.68333, 0, 0, 0.83334], 2497 "8712": [0.0391, 0.5391, 0, 0, 0.66667], 2498 "8715": [0.0391, 0.5391, 0, 0, 0.66667], 2499 "8722": [0.08333, 0.58333, 0, 0, 0.77778], 2500 "8723": [0.08333, 0.58333, 0, 0, 0.77778], 2501 "8725": [0.25, 0.75, 0, 0, 0.5], 2502 "8726": [0.25, 0.75, 0, 0, 0.5], 2503 "8727": [-0.03472, 0.46528, 0, 0, 0.5], 2504 "8728": [-0.05555, 0.44445, 0, 0, 0.5], 2505 "8729": [-0.05555, 0.44445, 0, 0, 0.5], 2506 "8730": [0.2, 0.8, 0, 0, 0.83334], 2507 "8733": [0, 0.43056, 0, 0, 0.77778], 2508 "8734": [0, 0.43056, 0, 0, 1.0], 2509 "8736": [0, 0.69224, 0, 0, 0.72222], 2510 "8739": [0.25, 0.75, 0, 0, 0.27778], 2511 "8741": [0.25, 0.75, 0, 0, 0.5], 2512 "8743": [0, 0.55556, 0, 0, 0.66667], 2513 "8744": [0, 0.55556, 0, 0, 0.66667], 2514 "8745": [0, 0.55556, 0, 0, 0.66667], 2515 "8746": [0, 0.55556, 0, 0, 0.66667], 2516 "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667], 2517 "8764": [-0.13313, 0.36687, 0, 0, 0.77778], 2518 "8768": [0.19444, 0.69444, 0, 0, 0.27778], 2519 "8771": [-0.03625, 0.46375, 0, 0, 0.77778], 2520 "8773": [-0.022, 0.589, 0, 0, 1.0], 2521 "8776": [-0.01688, 0.48312, 0, 0, 0.77778], 2522 "8781": [-0.03625, 0.46375, 0, 0, 0.77778], 2523 "8784": [-0.133, 0.67, 0, 0, 0.778], 2524 "8801": [-0.03625, 0.46375, 0, 0, 0.77778], 2525 "8804": [0.13597, 0.63597, 0, 0, 0.77778], 2526 "8805": [0.13597, 0.63597, 0, 0, 0.77778], 2527 "8810": [0.0391, 0.5391, 0, 0, 1.0], 2528 "8811": [0.0391, 0.5391, 0, 0, 1.0], 2529 "8826": [0.0391, 0.5391, 0, 0, 0.77778], 2530 "8827": [0.0391, 0.5391, 0, 0, 0.77778], 2531 "8834": [0.0391, 0.5391, 0, 0, 0.77778], 2532 "8835": [0.0391, 0.5391, 0, 0, 0.77778], 2533 "8838": [0.13597, 0.63597, 0, 0, 0.77778], 2534 "8839": [0.13597, 0.63597, 0, 0, 0.77778], 2535 "8846": [0, 0.55556, 0, 0, 0.66667], 2536 "8849": [0.13597, 0.63597, 0, 0, 0.77778], 2537 "8850": [0.13597, 0.63597, 0, 0, 0.77778], 2538 "8851": [0, 0.55556, 0, 0, 0.66667], 2539 "8852": [0, 0.55556, 0, 0, 0.66667], 2540 "8853": [0.08333, 0.58333, 0, 0, 0.77778], 2541 "8854": [0.08333, 0.58333, 0, 0, 0.77778], 2542 "8855": [0.08333, 0.58333, 0, 0, 0.77778], 2543 "8856": [0.08333, 0.58333, 0, 0, 0.77778], 2544 "8857": [0.08333, 0.58333, 0, 0, 0.77778], 2545 "8866": [0, 0.69444, 0, 0, 0.61111], 2546 "8867": [0, 0.69444, 0, 0, 0.61111], 2547 "8868": [0, 0.69444, 0, 0, 0.77778], 2548 "8869": [0, 0.69444, 0, 0, 0.77778], 2549 "8872": [0.249, 0.75, 0, 0, 0.867], 2550 "8900": [-0.05555, 0.44445, 0, 0, 0.5], 2551 "8901": [-0.05555, 0.44445, 0, 0, 0.27778], 2552 "8902": [-0.03472, 0.46528, 0, 0, 0.5], 2553 "8904": [0.005, 0.505, 0, 0, 0.9], 2554 "8942": [0.03, 0.9, 0, 0, 0.278], 2555 "8943": [-0.19, 0.31, 0, 0, 1.172], 2556 "8945": [-0.1, 0.82, 0, 0, 1.282], 2557 "8968": [0.25, 0.75, 0, 0, 0.44445], 2558 "8969": [0.25, 0.75, 0, 0, 0.44445], 2559 "8970": [0.25, 0.75, 0, 0, 0.44445], 2560 "8971": [0.25, 0.75, 0, 0, 0.44445], 2561 "8994": [-0.14236, 0.35764, 0, 0, 1.0], 2562 "8995": [-0.14236, 0.35764, 0, 0, 1.0], 2563 "9136": [0.244, 0.744, 0, 0, 0.412], 2564 "9137": [0.244, 0.744, 0, 0, 0.412], 2565 "9651": [0.19444, 0.69444, 0, 0, 0.88889], 2566 "9657": [-0.03472, 0.46528, 0, 0, 0.5], 2567 "9661": [0.19444, 0.69444, 0, 0, 0.88889], 2568 "9667": [-0.03472, 0.46528, 0, 0, 0.5], 2569 "9711": [0.19444, 0.69444, 0, 0, 1.0], 2570 "9824": [0.12963, 0.69444, 0, 0, 0.77778], 2571 "9825": [0.12963, 0.69444, 0, 0, 0.77778], 2572 "9826": [0.12963, 0.69444, 0, 0, 0.77778], 2573 "9827": [0.12963, 0.69444, 0, 0, 0.77778], 2574 "9837": [0, 0.75, 0, 0, 0.38889], 2575 "9838": [0.19444, 0.69444, 0, 0, 0.38889], 2576 "9839": [0.19444, 0.69444, 0, 0, 0.38889], 2577 "10216": [0.25, 0.75, 0, 0, 0.38889], 2578 "10217": [0.25, 0.75, 0, 0, 0.38889], 2579 "10222": [0.244, 0.744, 0, 0, 0.412], 2580 "10223": [0.244, 0.744, 0, 0, 0.412], 2581 "10229": [0.011, 0.511, 0, 0, 1.609], 2582 "10230": [0.011, 0.511, 0, 0, 1.638], 2583 "10231": [0.011, 0.511, 0, 0, 1.859], 2584 "10232": [0.024, 0.525, 0, 0, 1.609], 2585 "10233": [0.024, 0.525, 0, 0, 1.638], 2586 "10234": [0.024, 0.525, 0, 0, 1.858], 2587 "10236": [0.011, 0.511, 0, 0, 1.638], 2588 "10815": [0, 0.68333, 0, 0, 0.75], 2589 "10927": [0.13597, 0.63597, 0, 0, 0.77778], 2590 "10928": [0.13597, 0.63597, 0, 0, 0.77778], 2591 "57376": [0.19444, 0.69444, 0, 0, 0] 2592 }, 2593 "Math-BoldItalic": { 2594 "32": [0, 0, 0, 0, 0.25], 2595 "48": [0, 0.44444, 0, 0, 0.575], 2596 "49": [0, 0.44444, 0, 0, 0.575], 2597 "50": [0, 0.44444, 0, 0, 0.575], 2598 "51": [0.19444, 0.44444, 0, 0, 0.575], 2599 "52": [0.19444, 0.44444, 0, 0, 0.575], 2600 "53": [0.19444, 0.44444, 0, 0, 0.575], 2601 "54": [0, 0.64444, 0, 0, 0.575], 2602 "55": [0.19444, 0.44444, 0, 0, 0.575], 2603 "56": [0, 0.64444, 0, 0, 0.575], 2604 "57": [0.19444, 0.44444, 0, 0, 0.575], 2605 "65": [0, 0.68611, 0, 0, 0.86944], 2606 "66": [0, 0.68611, 0.04835, 0, 0.8664], 2607 "67": [0, 0.68611, 0.06979, 0, 0.81694], 2608 "68": [0, 0.68611, 0.03194, 0, 0.93812], 2609 "69": [0, 0.68611, 0.05451, 0, 0.81007], 2610 "70": [0, 0.68611, 0.15972, 0, 0.68889], 2611 "71": [0, 0.68611, 0, 0, 0.88673], 2612 "72": [0, 0.68611, 0.08229, 0, 0.98229], 2613 "73": [0, 0.68611, 0.07778, 0, 0.51111], 2614 "74": [0, 0.68611, 0.10069, 0, 0.63125], 2615 "75": [0, 0.68611, 0.06979, 0, 0.97118], 2616 "76": [0, 0.68611, 0, 0, 0.75555], 2617 "77": [0, 0.68611, 0.11424, 0, 1.14201], 2618 "78": [0, 0.68611, 0.11424, 0, 0.95034], 2619 "79": [0, 0.68611, 0.03194, 0, 0.83666], 2620 "80": [0, 0.68611, 0.15972, 0, 0.72309], 2621 "81": [0.19444, 0.68611, 0, 0, 0.86861], 2622 "82": [0, 0.68611, 0.00421, 0, 0.87235], 2623 "83": [0, 0.68611, 0.05382, 0, 0.69271], 2624 "84": [0, 0.68611, 0.15972, 0, 0.63663], 2625 "85": [0, 0.68611, 0.11424, 0, 0.80027], 2626 "86": [0, 0.68611, 0.25555, 0, 0.67778], 2627 "87": [0, 0.68611, 0.15972, 0, 1.09305], 2628 "88": [0, 0.68611, 0.07778, 0, 0.94722], 2629 "89": [0, 0.68611, 0.25555, 0, 0.67458], 2630 "90": [0, 0.68611, 0.06979, 0, 0.77257], 2631 "97": [0, 0.44444, 0, 0, 0.63287], 2632 "98": [0, 0.69444, 0, 0, 0.52083], 2633 "99": [0, 0.44444, 0, 0, 0.51342], 2634 "100": [0, 0.69444, 0, 0, 0.60972], 2635 "101": [0, 0.44444, 0, 0, 0.55361], 2636 "102": [0.19444, 0.69444, 0.11042, 0, 0.56806], 2637 "103": [0.19444, 0.44444, 0.03704, 0, 0.5449], 2638 "104": [0, 0.69444, 0, 0, 0.66759], 2639 "105": [0, 0.69326, 0, 0, 0.4048], 2640 "106": [0.19444, 0.69326, 0.0622, 0, 0.47083], 2641 "107": [0, 0.69444, 0.01852, 0, 0.6037], 2642 "108": [0, 0.69444, 0.0088, 0, 0.34815], 2643 "109": [0, 0.44444, 0, 0, 1.0324], 2644 "110": [0, 0.44444, 0, 0, 0.71296], 2645 "111": [0, 0.44444, 0, 0, 0.58472], 2646 "112": [0.19444, 0.44444, 0, 0, 0.60092], 2647 "113": [0.19444, 0.44444, 0.03704, 0, 0.54213], 2648 "114": [0, 0.44444, 0.03194, 0, 0.5287], 2649 "115": [0, 0.44444, 0, 0, 0.53125], 2650 "116": [0, 0.63492, 0, 0, 0.41528], 2651 "117": [0, 0.44444, 0, 0, 0.68102], 2652 "118": [0, 0.44444, 0.03704, 0, 0.56666], 2653 "119": [0, 0.44444, 0.02778, 0, 0.83148], 2654 "120": [0, 0.44444, 0, 0, 0.65903], 2655 "121": [0.19444, 0.44444, 0.03704, 0, 0.59028], 2656 "122": [0, 0.44444, 0.04213, 0, 0.55509], 2657 "160": [0, 0, 0, 0, 0.25], 2658 "915": [0, 0.68611, 0.15972, 0, 0.65694], 2659 "916": [0, 0.68611, 0, 0, 0.95833], 2660 "920": [0, 0.68611, 0.03194, 0, 0.86722], 2661 "923": [0, 0.68611, 0, 0, 0.80555], 2662 "926": [0, 0.68611, 0.07458, 0, 0.84125], 2663 "928": [0, 0.68611, 0.08229, 0, 0.98229], 2664 "931": [0, 0.68611, 0.05451, 0, 0.88507], 2665 "933": [0, 0.68611, 0.15972, 0, 0.67083], 2666 "934": [0, 0.68611, 0, 0, 0.76666], 2667 "936": [0, 0.68611, 0.11653, 0, 0.71402], 2668 "937": [0, 0.68611, 0.04835, 0, 0.8789], 2669 "945": [0, 0.44444, 0, 0, 0.76064], 2670 "946": [0.19444, 0.69444, 0.03403, 0, 0.65972], 2671 "947": [0.19444, 0.44444, 0.06389, 0, 0.59003], 2672 "948": [0, 0.69444, 0.03819, 0, 0.52222], 2673 "949": [0, 0.44444, 0, 0, 0.52882], 2674 "950": [0.19444, 0.69444, 0.06215, 0, 0.50833], 2675 "951": [0.19444, 0.44444, 0.03704, 0, 0.6], 2676 "952": [0, 0.69444, 0.03194, 0, 0.5618], 2677 "953": [0, 0.44444, 0, 0, 0.41204], 2678 "954": [0, 0.44444, 0, 0, 0.66759], 2679 "955": [0, 0.69444, 0, 0, 0.67083], 2680 "956": [0.19444, 0.44444, 0, 0, 0.70787], 2681 "957": [0, 0.44444, 0.06898, 0, 0.57685], 2682 "958": [0.19444, 0.69444, 0.03021, 0, 0.50833], 2683 "959": [0, 0.44444, 0, 0, 0.58472], 2684 "960": [0, 0.44444, 0.03704, 0, 0.68241], 2685 "961": [0.19444, 0.44444, 0, 0, 0.6118], 2686 "962": [0.09722, 0.44444, 0.07917, 0, 0.42361], 2687 "963": [0, 0.44444, 0.03704, 0, 0.68588], 2688 "964": [0, 0.44444, 0.13472, 0, 0.52083], 2689 "965": [0, 0.44444, 0.03704, 0, 0.63055], 2690 "966": [0.19444, 0.44444, 0, 0, 0.74722], 2691 "967": [0.19444, 0.44444, 0, 0, 0.71805], 2692 "968": [0.19444, 0.69444, 0.03704, 0, 0.75833], 2693 "969": [0, 0.44444, 0.03704, 0, 0.71782], 2694 "977": [0, 0.69444, 0, 0, 0.69155], 2695 "981": [0.19444, 0.69444, 0, 0, 0.7125], 2696 "982": [0, 0.44444, 0.03194, 0, 0.975], 2697 "1009": [0.19444, 0.44444, 0, 0, 0.6118], 2698 "1013": [0, 0.44444, 0, 0, 0.48333], 2699 "57649": [0, 0.44444, 0, 0, 0.39352], 2700 "57911": [0.19444, 0.44444, 0, 0, 0.43889] 2701 }, 2702 "Math-Italic": { 2703 "32": [0, 0, 0, 0, 0.25], 2704 "48": [0, 0.43056, 0, 0, 0.5], 2705 "49": [0, 0.43056, 0, 0, 0.5], 2706 "50": [0, 0.43056, 0, 0, 0.5], 2707 "51": [0.19444, 0.43056, 0, 0, 0.5], 2708 "52": [0.19444, 0.43056, 0, 0, 0.5], 2709 "53": [0.19444, 0.43056, 0, 0, 0.5], 2710 "54": [0, 0.64444, 0, 0, 0.5], 2711 "55": [0.19444, 0.43056, 0, 0, 0.5], 2712 "56": [0, 0.64444, 0, 0, 0.5], 2713 "57": [0.19444, 0.43056, 0, 0, 0.5], 2714 "65": [0, 0.68333, 0, 0.13889, 0.75], 2715 "66": [0, 0.68333, 0.05017, 0.08334, 0.75851], 2716 "67": [0, 0.68333, 0.07153, 0.08334, 0.71472], 2717 "68": [0, 0.68333, 0.02778, 0.05556, 0.82792], 2718 "69": [0, 0.68333, 0.05764, 0.08334, 0.7382], 2719 "70": [0, 0.68333, 0.13889, 0.08334, 0.64306], 2720 "71": [0, 0.68333, 0, 0.08334, 0.78625], 2721 "72": [0, 0.68333, 0.08125, 0.05556, 0.83125], 2722 "73": [0, 0.68333, 0.07847, 0.11111, 0.43958], 2723 "74": [0, 0.68333, 0.09618, 0.16667, 0.55451], 2724 "75": [0, 0.68333, 0.07153, 0.05556, 0.84931], 2725 "76": [0, 0.68333, 0, 0.02778, 0.68056], 2726 "77": [0, 0.68333, 0.10903, 0.08334, 0.97014], 2727 "78": [0, 0.68333, 0.10903, 0.08334, 0.80347], 2728 "79": [0, 0.68333, 0.02778, 0.08334, 0.76278], 2729 "80": [0, 0.68333, 0.13889, 0.08334, 0.64201], 2730 "81": [0.19444, 0.68333, 0, 0.08334, 0.79056], 2731 "82": [0, 0.68333, 0.00773, 0.08334, 0.75929], 2732 "83": [0, 0.68333, 0.05764, 0.08334, 0.6132], 2733 "84": [0, 0.68333, 0.13889, 0.08334, 0.58438], 2734 "85": [0, 0.68333, 0.10903, 0.02778, 0.68278], 2735 "86": [0, 0.68333, 0.22222, 0, 0.58333], 2736 "87": [0, 0.68333, 0.13889, 0, 0.94445], 2737 "88": [0, 0.68333, 0.07847, 0.08334, 0.82847], 2738 "89": [0, 0.68333, 0.22222, 0, 0.58056], 2739 "90": [0, 0.68333, 0.07153, 0.08334, 0.68264], 2740 "97": [0, 0.43056, 0, 0, 0.52859], 2741 "98": [0, 0.69444, 0, 0, 0.42917], 2742 "99": [0, 0.43056, 0, 0.05556, 0.43276], 2743 "100": [0, 0.69444, 0, 0.16667, 0.52049], 2744 "101": [0, 0.43056, 0, 0.05556, 0.46563], 2745 "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959], 2746 "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697], 2747 "104": [0, 0.69444, 0, 0, 0.57616], 2748 "105": [0, 0.65952, 0, 0, 0.34451], 2749 "106": [0.19444, 0.65952, 0.05724, 0, 0.41181], 2750 "107": [0, 0.69444, 0.03148, 0, 0.5206], 2751 "108": [0, 0.69444, 0.01968, 0.08334, 0.29838], 2752 "109": [0, 0.43056, 0, 0, 0.87801], 2753 "110": [0, 0.43056, 0, 0, 0.60023], 2754 "111": [0, 0.43056, 0, 0.05556, 0.48472], 2755 "112": [0.19444, 0.43056, 0, 0.08334, 0.50313], 2756 "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641], 2757 "114": [0, 0.43056, 0.02778, 0.05556, 0.45116], 2758 "115": [0, 0.43056, 0, 0.05556, 0.46875], 2759 "116": [0, 0.61508, 0, 0.08334, 0.36111], 2760 "117": [0, 0.43056, 0, 0.02778, 0.57246], 2761 "118": [0, 0.43056, 0.03588, 0.02778, 0.48472], 2762 "119": [0, 0.43056, 0.02691, 0.08334, 0.71592], 2763 "120": [0, 0.43056, 0, 0.02778, 0.57153], 2764 "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028], 2765 "122": [0, 0.43056, 0.04398, 0.05556, 0.46505], 2766 "160": [0, 0, 0, 0, 0.25], 2767 "915": [0, 0.68333, 0.13889, 0.08334, 0.61528], 2768 "916": [0, 0.68333, 0, 0.16667, 0.83334], 2769 "920": [0, 0.68333, 0.02778, 0.08334, 0.76278], 2770 "923": [0, 0.68333, 0, 0.16667, 0.69445], 2771 "926": [0, 0.68333, 0.07569, 0.08334, 0.74236], 2772 "928": [0, 0.68333, 0.08125, 0.05556, 0.83125], 2773 "931": [0, 0.68333, 0.05764, 0.08334, 0.77986], 2774 "933": [0, 0.68333, 0.13889, 0.05556, 0.58333], 2775 "934": [0, 0.68333, 0, 0.08334, 0.66667], 2776 "936": [0, 0.68333, 0.11, 0.05556, 0.61222], 2777 "937": [0, 0.68333, 0.05017, 0.08334, 0.7724], 2778 "945": [0, 0.43056, 0.0037, 0.02778, 0.6397], 2779 "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563], 2780 "947": [0.19444, 0.43056, 0.05556, 0, 0.51773], 2781 "948": [0, 0.69444, 0.03785, 0.05556, 0.44444], 2782 "949": [0, 0.43056, 0, 0.08334, 0.46632], 2783 "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375], 2784 "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653], 2785 "952": [0, 0.69444, 0.02778, 0.08334, 0.46944], 2786 "953": [0, 0.43056, 0, 0.05556, 0.35394], 2787 "954": [0, 0.43056, 0, 0, 0.57616], 2788 "955": [0, 0.69444, 0, 0, 0.58334], 2789 "956": [0.19444, 0.43056, 0, 0.02778, 0.60255], 2790 "957": [0, 0.43056, 0.06366, 0.02778, 0.49398], 2791 "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375], 2792 "959": [0, 0.43056, 0, 0.05556, 0.48472], 2793 "960": [0, 0.43056, 0.03588, 0, 0.57003], 2794 "961": [0.19444, 0.43056, 0, 0.08334, 0.51702], 2795 "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285], 2796 "963": [0, 0.43056, 0.03588, 0, 0.57141], 2797 "964": [0, 0.43056, 0.1132, 0.02778, 0.43715], 2798 "965": [0, 0.43056, 0.03588, 0.02778, 0.54028], 2799 "966": [0.19444, 0.43056, 0, 0.08334, 0.65417], 2800 "967": [0.19444, 0.43056, 0, 0.05556, 0.62569], 2801 "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139], 2802 "969": [0, 0.43056, 0.03588, 0, 0.62245], 2803 "977": [0, 0.69444, 0, 0.08334, 0.59144], 2804 "981": [0.19444, 0.69444, 0, 0.08334, 0.59583], 2805 "982": [0, 0.43056, 0.02778, 0, 0.82813], 2806 "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702], 2807 "1013": [0, 0.43056, 0, 0.05556, 0.4059], 2808 "57649": [0, 0.43056, 0, 0.02778, 0.32246], 2809 "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403] 2810 }, 2811 "SansSerif-Bold": { 2812 "32": [0, 0, 0, 0, 0.25], 2813 "33": [0, 0.69444, 0, 0, 0.36667], 2814 "34": [0, 0.69444, 0, 0, 0.55834], 2815 "35": [0.19444, 0.69444, 0, 0, 0.91667], 2816 "36": [0.05556, 0.75, 0, 0, 0.55], 2817 "37": [0.05556, 0.75, 0, 0, 1.02912], 2818 "38": [0, 0.69444, 0, 0, 0.83056], 2819 "39": [0, 0.69444, 0, 0, 0.30556], 2820 "40": [0.25, 0.75, 0, 0, 0.42778], 2821 "41": [0.25, 0.75, 0, 0, 0.42778], 2822 "42": [0, 0.75, 0, 0, 0.55], 2823 "43": [0.11667, 0.61667, 0, 0, 0.85556], 2824 "44": [0.10556, 0.13056, 0, 0, 0.30556], 2825 "45": [0, 0.45833, 0, 0, 0.36667], 2826 "46": [0, 0.13056, 0, 0, 0.30556], 2827 "47": [0.25, 0.75, 0, 0, 0.55], 2828 "48": [0, 0.69444, 0, 0, 0.55], 2829 "49": [0, 0.69444, 0, 0, 0.55], 2830 "50": [0, 0.69444, 0, 0, 0.55], 2831 "51": [0, 0.69444, 0, 0, 0.55], 2832 "52": [0, 0.69444, 0, 0, 0.55], 2833 "53": [0, 0.69444, 0, 0, 0.55], 2834 "54": [0, 0.69444, 0, 0, 0.55], 2835 "55": [0, 0.69444, 0, 0, 0.55], 2836 "56": [0, 0.69444, 0, 0, 0.55], 2837 "57": [0, 0.69444, 0, 0, 0.55], 2838 "58": [0, 0.45833, 0, 0, 0.30556], 2839 "59": [0.10556, 0.45833, 0, 0, 0.30556], 2840 "61": [-0.09375, 0.40625, 0, 0, 0.85556], 2841 "63": [0, 0.69444, 0, 0, 0.51945], 2842 "64": [0, 0.69444, 0, 0, 0.73334], 2843 "65": [0, 0.69444, 0, 0, 0.73334], 2844 "66": [0, 0.69444, 0, 0, 0.73334], 2845 "67": [0, 0.69444, 0, 0, 0.70278], 2846 "68": [0, 0.69444, 0, 0, 0.79445], 2847 "69": [0, 0.69444, 0, 0, 0.64167], 2848 "70": [0, 0.69444, 0, 0, 0.61111], 2849 "71": [0, 0.69444, 0, 0, 0.73334], 2850 "72": [0, 0.69444, 0, 0, 0.79445], 2851 "73": [0, 0.69444, 0, 0, 0.33056], 2852 "74": [0, 0.69444, 0, 0, 0.51945], 2853 "75": [0, 0.69444, 0, 0, 0.76389], 2854 "76": [0, 0.69444, 0, 0, 0.58056], 2855 "77": [0, 0.69444, 0, 0, 0.97778], 2856 "78": [0, 0.69444, 0, 0, 0.79445], 2857 "79": [0, 0.69444, 0, 0, 0.79445], 2858 "80": [0, 0.69444, 0, 0, 0.70278], 2859 "81": [0.10556, 0.69444, 0, 0, 0.79445], 2860 "82": [0, 0.69444, 0, 0, 0.70278], 2861 "83": [0, 0.69444, 0, 0, 0.61111], 2862 "84": [0, 0.69444, 0, 0, 0.73334], 2863 "85": [0, 0.69444, 0, 0, 0.76389], 2864 "86": [0, 0.69444, 0.01528, 0, 0.73334], 2865 "87": [0, 0.69444, 0.01528, 0, 1.03889], 2866 "88": [0, 0.69444, 0, 0, 0.73334], 2867 "89": [0, 0.69444, 0.0275, 0, 0.73334], 2868 "90": [0, 0.69444, 0, 0, 0.67223], 2869 "91": [0.25, 0.75, 0, 0, 0.34306], 2870 "93": [0.25, 0.75, 0, 0, 0.34306], 2871 "94": [0, 0.69444, 0, 0, 0.55], 2872 "95": [0.35, 0.10833, 0.03056, 0, 0.55], 2873 "97": [0, 0.45833, 0, 0, 0.525], 2874 "98": [0, 0.69444, 0, 0, 0.56111], 2875 "99": [0, 0.45833, 0, 0, 0.48889], 2876 "100": [0, 0.69444, 0, 0, 0.56111], 2877 "101": [0, 0.45833, 0, 0, 0.51111], 2878 "102": [0, 0.69444, 0.07639, 0, 0.33611], 2879 "103": [0.19444, 0.45833, 0.01528, 0, 0.55], 2880 "104": [0, 0.69444, 0, 0, 0.56111], 2881 "105": [0, 0.69444, 0, 0, 0.25556], 2882 "106": [0.19444, 0.69444, 0, 0, 0.28611], 2883 "107": [0, 0.69444, 0, 0, 0.53056], 2884 "108": [0, 0.69444, 0, 0, 0.25556], 2885 "109": [0, 0.45833, 0, 0, 0.86667], 2886 "110": [0, 0.45833, 0, 0, 0.56111], 2887 "111": [0, 0.45833, 0, 0, 0.55], 2888 "112": [0.19444, 0.45833, 0, 0, 0.56111], 2889 "113": [0.19444, 0.45833, 0, 0, 0.56111], 2890 "114": [0, 0.45833, 0.01528, 0, 0.37222], 2891 "115": [0, 0.45833, 0, 0, 0.42167], 2892 "116": [0, 0.58929, 0, 0, 0.40417], 2893 "117": [0, 0.45833, 0, 0, 0.56111], 2894 "118": [0, 0.45833, 0.01528, 0, 0.5], 2895 "119": [0, 0.45833, 0.01528, 0, 0.74445], 2896 "120": [0, 0.45833, 0, 0, 0.5], 2897 "121": [0.19444, 0.45833, 0.01528, 0, 0.5], 2898 "122": [0, 0.45833, 0, 0, 0.47639], 2899 "126": [0.35, 0.34444, 0, 0, 0.55], 2900 "160": [0, 0, 0, 0, 0.25], 2901 "168": [0, 0.69444, 0, 0, 0.55], 2902 "176": [0, 0.69444, 0, 0, 0.73334], 2903 "180": [0, 0.69444, 0, 0, 0.55], 2904 "184": [0.17014, 0, 0, 0, 0.48889], 2905 "305": [0, 0.45833, 0, 0, 0.25556], 2906 "567": [0.19444, 0.45833, 0, 0, 0.28611], 2907 "710": [0, 0.69444, 0, 0, 0.55], 2908 "711": [0, 0.63542, 0, 0, 0.55], 2909 "713": [0, 0.63778, 0, 0, 0.55], 2910 "728": [0, 0.69444, 0, 0, 0.55], 2911 "729": [0, 0.69444, 0, 0, 0.30556], 2912 "730": [0, 0.69444, 0, 0, 0.73334], 2913 "732": [0, 0.69444, 0, 0, 0.55], 2914 "733": [0, 0.69444, 0, 0, 0.55], 2915 "915": [0, 0.69444, 0, 0, 0.58056], 2916 "916": [0, 0.69444, 0, 0, 0.91667], 2917 "920": [0, 0.69444, 0, 0, 0.85556], 2918 "923": [0, 0.69444, 0, 0, 0.67223], 2919 "926": [0, 0.69444, 0, 0, 0.73334], 2920 "928": [0, 0.69444, 0, 0, 0.79445], 2921 "931": [0, 0.69444, 0, 0, 0.79445], 2922 "933": [0, 0.69444, 0, 0, 0.85556], 2923 "934": [0, 0.69444, 0, 0, 0.79445], 2924 "936": [0, 0.69444, 0, 0, 0.85556], 2925 "937": [0, 0.69444, 0, 0, 0.79445], 2926 "8211": [0, 0.45833, 0.03056, 0, 0.55], 2927 "8212": [0, 0.45833, 0.03056, 0, 1.10001], 2928 "8216": [0, 0.69444, 0, 0, 0.30556], 2929 "8217": [0, 0.69444, 0, 0, 0.30556], 2930 "8220": [0, 0.69444, 0, 0, 0.55834], 2931 "8221": [0, 0.69444, 0, 0, 0.55834] 2932 }, 2933 "SansSerif-Italic": { 2934 "32": [0, 0, 0, 0, 0.25], 2935 "33": [0, 0.69444, 0.05733, 0, 0.31945], 2936 "34": [0, 0.69444, 0.00316, 0, 0.5], 2937 "35": [0.19444, 0.69444, 0.05087, 0, 0.83334], 2938 "36": [0.05556, 0.75, 0.11156, 0, 0.5], 2939 "37": [0.05556, 0.75, 0.03126, 0, 0.83334], 2940 "38": [0, 0.69444, 0.03058, 0, 0.75834], 2941 "39": [0, 0.69444, 0.07816, 0, 0.27778], 2942 "40": [0.25, 0.75, 0.13164, 0, 0.38889], 2943 "41": [0.25, 0.75, 0.02536, 0, 0.38889], 2944 "42": [0, 0.75, 0.11775, 0, 0.5], 2945 "43": [0.08333, 0.58333, 0.02536, 0, 0.77778], 2946 "44": [0.125, 0.08333, 0, 0, 0.27778], 2947 "45": [0, 0.44444, 0.01946, 0, 0.33333], 2948 "46": [0, 0.08333, 0, 0, 0.27778], 2949 "47": [0.25, 0.75, 0.13164, 0, 0.5], 2950 "48": [0, 0.65556, 0.11156, 0, 0.5], 2951 "49": [0, 0.65556, 0.11156, 0, 0.5], 2952 "50": [0, 0.65556, 0.11156, 0, 0.5], 2953 "51": [0, 0.65556, 0.11156, 0, 0.5], 2954 "52": [0, 0.65556, 0.11156, 0, 0.5], 2955 "53": [0, 0.65556, 0.11156, 0, 0.5], 2956 "54": [0, 0.65556, 0.11156, 0, 0.5], 2957 "55": [0, 0.65556, 0.11156, 0, 0.5], 2958 "56": [0, 0.65556, 0.11156, 0, 0.5], 2959 "57": [0, 0.65556, 0.11156, 0, 0.5], 2960 "58": [0, 0.44444, 0.02502, 0, 0.27778], 2961 "59": [0.125, 0.44444, 0.02502, 0, 0.27778], 2962 "61": [-0.13, 0.37, 0.05087, 0, 0.77778], 2963 "63": [0, 0.69444, 0.11809, 0, 0.47222], 2964 "64": [0, 0.69444, 0.07555, 0, 0.66667], 2965 "65": [0, 0.69444, 0, 0, 0.66667], 2966 "66": [0, 0.69444, 0.08293, 0, 0.66667], 2967 "67": [0, 0.69444, 0.11983, 0, 0.63889], 2968 "68": [0, 0.69444, 0.07555, 0, 0.72223], 2969 "69": [0, 0.69444, 0.11983, 0, 0.59722], 2970 "70": [0, 0.69444, 0.13372, 0, 0.56945], 2971 "71": [0, 0.69444, 0.11983, 0, 0.66667], 2972 "72": [0, 0.69444, 0.08094, 0, 0.70834], 2973 "73": [0, 0.69444, 0.13372, 0, 0.27778], 2974 "74": [0, 0.69444, 0.08094, 0, 0.47222], 2975 "75": [0, 0.69444, 0.11983, 0, 0.69445], 2976 "76": [0, 0.69444, 0, 0, 0.54167], 2977 "77": [0, 0.69444, 0.08094, 0, 0.875], 2978 "78": [0, 0.69444, 0.08094, 0, 0.70834], 2979 "79": [0, 0.69444, 0.07555, 0, 0.73611], 2980 "80": [0, 0.69444, 0.08293, 0, 0.63889], 2981 "81": [0.125, 0.69444, 0.07555, 0, 0.73611], 2982 "82": [0, 0.69444, 0.08293, 0, 0.64584], 2983 "83": [0, 0.69444, 0.09205, 0, 0.55556], 2984 "84": [0, 0.69444, 0.13372, 0, 0.68056], 2985 "85": [0, 0.69444, 0.08094, 0, 0.6875], 2986 "86": [0, 0.69444, 0.1615, 0, 0.66667], 2987 "87": [0, 0.69444, 0.1615, 0, 0.94445], 2988 "88": [0, 0.69444, 0.13372, 0, 0.66667], 2989 "89": [0, 0.69444, 0.17261, 0, 0.66667], 2990 "90": [0, 0.69444, 0.11983, 0, 0.61111], 2991 "91": [0.25, 0.75, 0.15942, 0, 0.28889], 2992 "93": [0.25, 0.75, 0.08719, 0, 0.28889], 2993 "94": [0, 0.69444, 0.0799, 0, 0.5], 2994 "95": [0.35, 0.09444, 0.08616, 0, 0.5], 2995 "97": [0, 0.44444, 0.00981, 0, 0.48056], 2996 "98": [0, 0.69444, 0.03057, 0, 0.51667], 2997 "99": [0, 0.44444, 0.08336, 0, 0.44445], 2998 "100": [0, 0.69444, 0.09483, 0, 0.51667], 2999 "101": [0, 0.44444, 0.06778, 0, 0.44445], 3000 "102": [0, 0.69444, 0.21705, 0, 0.30556], 3001 "103": [0.19444, 0.44444, 0.10836, 0, 0.5], 3002 "104": [0, 0.69444, 0.01778, 0, 0.51667], 3003 "105": [0, 0.67937, 0.09718, 0, 0.23889], 3004 "106": [0.19444, 0.67937, 0.09162, 0, 0.26667], 3005 "107": [0, 0.69444, 0.08336, 0, 0.48889], 3006 "108": [0, 0.69444, 0.09483, 0, 0.23889], 3007 "109": [0, 0.44444, 0.01778, 0, 0.79445], 3008 "110": [0, 0.44444, 0.01778, 0, 0.51667], 3009 "111": [0, 0.44444, 0.06613, 0, 0.5], 3010 "112": [0.19444, 0.44444, 0.0389, 0, 0.51667], 3011 "113": [0.19444, 0.44444, 0.04169, 0, 0.51667], 3012 "114": [0, 0.44444, 0.10836, 0, 0.34167], 3013 "115": [0, 0.44444, 0.0778, 0, 0.38333], 3014 "116": [0, 0.57143, 0.07225, 0, 0.36111], 3015 "117": [0, 0.44444, 0.04169, 0, 0.51667], 3016 "118": [0, 0.44444, 0.10836, 0, 0.46111], 3017 "119": [0, 0.44444, 0.10836, 0, 0.68334], 3018 "120": [0, 0.44444, 0.09169, 0, 0.46111], 3019 "121": [0.19444, 0.44444, 0.10836, 0, 0.46111], 3020 "122": [0, 0.44444, 0.08752, 0, 0.43472], 3021 "126": [0.35, 0.32659, 0.08826, 0, 0.5], 3022 "160": [0, 0, 0, 0, 0.25], 3023 "168": [0, 0.67937, 0.06385, 0, 0.5], 3024 "176": [0, 0.69444, 0, 0, 0.73752], 3025 "184": [0.17014, 0, 0, 0, 0.44445], 3026 "305": [0, 0.44444, 0.04169, 0, 0.23889], 3027 "567": [0.19444, 0.44444, 0.04169, 0, 0.26667], 3028 "710": [0, 0.69444, 0.0799, 0, 0.5], 3029 "711": [0, 0.63194, 0.08432, 0, 0.5], 3030 "713": [0, 0.60889, 0.08776, 0, 0.5], 3031 "714": [0, 0.69444, 0.09205, 0, 0.5], 3032 "715": [0, 0.69444, 0, 0, 0.5], 3033 "728": [0, 0.69444, 0.09483, 0, 0.5], 3034 "729": [0, 0.67937, 0.07774, 0, 0.27778], 3035 "730": [0, 0.69444, 0, 0, 0.73752], 3036 "732": [0, 0.67659, 0.08826, 0, 0.5], 3037 "733": [0, 0.69444, 0.09205, 0, 0.5], 3038 "915": [0, 0.69444, 0.13372, 0, 0.54167], 3039 "916": [0, 0.69444, 0, 0, 0.83334], 3040 "920": [0, 0.69444, 0.07555, 0, 0.77778], 3041 "923": [0, 0.69444, 0, 0, 0.61111], 3042 "926": [0, 0.69444, 0.12816, 0, 0.66667], 3043 "928": [0, 0.69444, 0.08094, 0, 0.70834], 3044 "931": [0, 0.69444, 0.11983, 0, 0.72222], 3045 "933": [0, 0.69444, 0.09031, 0, 0.77778], 3046 "934": [0, 0.69444, 0.04603, 0, 0.72222], 3047 "936": [0, 0.69444, 0.09031, 0, 0.77778], 3048 "937": [0, 0.69444, 0.08293, 0, 0.72222], 3049 "8211": [0, 0.44444, 0.08616, 0, 0.5], 3050 "8212": [0, 0.44444, 0.08616, 0, 1.0], 3051 "8216": [0, 0.69444, 0.07816, 0, 0.27778], 3052 "8217": [0, 0.69444, 0.07816, 0, 0.27778], 3053 "8220": [0, 0.69444, 0.14205, 0, 0.5], 3054 "8221": [0, 0.69444, 0.00316, 0, 0.5] 3055 }, 3056 "SansSerif-Regular": { 3057 "32": [0, 0, 0, 0, 0.25], 3058 "33": [0, 0.69444, 0, 0, 0.31945], 3059 "34": [0, 0.69444, 0, 0, 0.5], 3060 "35": [0.19444, 0.69444, 0, 0, 0.83334], 3061 "36": [0.05556, 0.75, 0, 0, 0.5], 3062 "37": [0.05556, 0.75, 0, 0, 0.83334], 3063 "38": [0, 0.69444, 0, 0, 0.75834], 3064 "39": [0, 0.69444, 0, 0, 0.27778], 3065 "40": [0.25, 0.75, 0, 0, 0.38889], 3066 "41": [0.25, 0.75, 0, 0, 0.38889], 3067 "42": [0, 0.75, 0, 0, 0.5], 3068 "43": [0.08333, 0.58333, 0, 0, 0.77778], 3069 "44": [0.125, 0.08333, 0, 0, 0.27778], 3070 "45": [0, 0.44444, 0, 0, 0.33333], 3071 "46": [0, 0.08333, 0, 0, 0.27778], 3072 "47": [0.25, 0.75, 0, 0, 0.5], 3073 "48": [0, 0.65556, 0, 0, 0.5], 3074 "49": [0, 0.65556, 0, 0, 0.5], 3075 "50": [0, 0.65556, 0, 0, 0.5], 3076 "51": [0, 0.65556, 0, 0, 0.5], 3077 "52": [0, 0.65556, 0, 0, 0.5], 3078 "53": [0, 0.65556, 0, 0, 0.5], 3079 "54": [0, 0.65556, 0, 0, 0.5], 3080 "55": [0, 0.65556, 0, 0, 0.5], 3081 "56": [0, 0.65556, 0, 0, 0.5], 3082 "57": [0, 0.65556, 0, 0, 0.5], 3083 "58": [0, 0.44444, 0, 0, 0.27778], 3084 "59": [0.125, 0.44444, 0, 0, 0.27778], 3085 "61": [-0.13, 0.37, 0, 0, 0.77778], 3086 "63": [0, 0.69444, 0, 0, 0.47222], 3087 "64": [0, 0.69444, 0, 0, 0.66667], 3088 "65": [0, 0.69444, 0, 0, 0.66667], 3089 "66": [0, 0.69444, 0, 0, 0.66667], 3090 "67": [0, 0.69444, 0, 0, 0.63889], 3091 "68": [0, 0.69444, 0, 0, 0.72223], 3092 "69": [0, 0.69444, 0, 0, 0.59722], 3093 "70": [0, 0.69444, 0, 0, 0.56945], 3094 "71": [0, 0.69444, 0, 0, 0.66667], 3095 "72": [0, 0.69444, 0, 0, 0.70834], 3096 "73": [0, 0.69444, 0, 0, 0.27778], 3097 "74": [0, 0.69444, 0, 0, 0.47222], 3098 "75": [0, 0.69444, 0, 0, 0.69445], 3099 "76": [0, 0.69444, 0, 0, 0.54167], 3100 "77": [0, 0.69444, 0, 0, 0.875], 3101 "78": [0, 0.69444, 0, 0, 0.70834], 3102 "79": [0, 0.69444, 0, 0, 0.73611], 3103 "80": [0, 0.69444, 0, 0, 0.63889], 3104 "81": [0.125, 0.69444, 0, 0, 0.73611], 3105 "82": [0, 0.69444, 0, 0, 0.64584], 3106 "83": [0, 0.69444, 0, 0, 0.55556], 3107 "84": [0, 0.69444, 0, 0, 0.68056], 3108 "85": [0, 0.69444, 0, 0, 0.6875], 3109 "86": [0, 0.69444, 0.01389, 0, 0.66667], 3110 "87": [0, 0.69444, 0.01389, 0, 0.94445], 3111 "88": [0, 0.69444, 0, 0, 0.66667], 3112 "89": [0, 0.69444, 0.025, 0, 0.66667], 3113 "90": [0, 0.69444, 0, 0, 0.61111], 3114 "91": [0.25, 0.75, 0, 0, 0.28889], 3115 "93": [0.25, 0.75, 0, 0, 0.28889], 3116 "94": [0, 0.69444, 0, 0, 0.5], 3117 "95": [0.35, 0.09444, 0.02778, 0, 0.5], 3118 "97": [0, 0.44444, 0, 0, 0.48056], 3119 "98": [0, 0.69444, 0, 0, 0.51667], 3120 "99": [0, 0.44444, 0, 0, 0.44445], 3121 "100": [0, 0.69444, 0, 0, 0.51667], 3122 "101": [0, 0.44444, 0, 0, 0.44445], 3123 "102": [0, 0.69444, 0.06944, 0, 0.30556], 3124 "103": [0.19444, 0.44444, 0.01389, 0, 0.5], 3125 "104": [0, 0.69444, 0, 0, 0.51667], 3126 "105": [0, 0.67937, 0, 0, 0.23889], 3127 "106": [0.19444, 0.67937, 0, 0, 0.26667], 3128 "107": [0, 0.69444, 0, 0, 0.48889], 3129 "108": [0, 0.69444, 0, 0, 0.23889], 3130 "109": [0, 0.44444, 0, 0, 0.79445], 3131 "110": [0, 0.44444, 0, 0, 0.51667], 3132 "111": [0, 0.44444, 0, 0, 0.5], 3133 "112": [0.19444, 0.44444, 0, 0, 0.51667], 3134 "113": [0.19444, 0.44444, 0, 0, 0.51667], 3135 "114": [0, 0.44444, 0.01389, 0, 0.34167], 3136 "115": [0, 0.44444, 0, 0, 0.38333], 3137 "116": [0, 0.57143, 0, 0, 0.36111], 3138 "117": [0, 0.44444, 0, 0, 0.51667], 3139 "118": [0, 0.44444, 0.01389, 0, 0.46111], 3140 "119": [0, 0.44444, 0.01389, 0, 0.68334], 3141 "120": [0, 0.44444, 0, 0, 0.46111], 3142 "121": [0.19444, 0.44444, 0.01389, 0, 0.46111], 3143 "122": [0, 0.44444, 0, 0, 0.43472], 3144 "126": [0.35, 0.32659, 0, 0, 0.5], 3145 "160": [0, 0, 0, 0, 0.25], 3146 "168": [0, 0.67937, 0, 0, 0.5], 3147 "176": [0, 0.69444, 0, 0, 0.66667], 3148 "184": [0.17014, 0, 0, 0, 0.44445], 3149 "305": [0, 0.44444, 0, 0, 0.23889], 3150 "567": [0.19444, 0.44444, 0, 0, 0.26667], 3151 "710": [0, 0.69444, 0, 0, 0.5], 3152 "711": [0, 0.63194, 0, 0, 0.5], 3153 "713": [0, 0.60889, 0, 0, 0.5], 3154 "714": [0, 0.69444, 0, 0, 0.5], 3155 "715": [0, 0.69444, 0, 0, 0.5], 3156 "728": [0, 0.69444, 0, 0, 0.5], 3157 "729": [0, 0.67937, 0, 0, 0.27778], 3158 "730": [0, 0.69444, 0, 0, 0.66667], 3159 "732": [0, 0.67659, 0, 0, 0.5], 3160 "733": [0, 0.69444, 0, 0, 0.5], 3161 "915": [0, 0.69444, 0, 0, 0.54167], 3162 "916": [0, 0.69444, 0, 0, 0.83334], 3163 "920": [0, 0.69444, 0, 0, 0.77778], 3164 "923": [0, 0.69444, 0, 0, 0.61111], 3165 "926": [0, 0.69444, 0, 0, 0.66667], 3166 "928": [0, 0.69444, 0, 0, 0.70834], 3167 "931": [0, 0.69444, 0, 0, 0.72222], 3168 "933": [0, 0.69444, 0, 0, 0.77778], 3169 "934": [0, 0.69444, 0, 0, 0.72222], 3170 "936": [0, 0.69444, 0, 0, 0.77778], 3171 "937": [0, 0.69444, 0, 0, 0.72222], 3172 "8211": [0, 0.44444, 0.02778, 0, 0.5], 3173 "8212": [0, 0.44444, 0.02778, 0, 1.0], 3174 "8216": [0, 0.69444, 0, 0, 0.27778], 3175 "8217": [0, 0.69444, 0, 0, 0.27778], 3176 "8220": [0, 0.69444, 0, 0, 0.5], 3177 "8221": [0, 0.69444, 0, 0, 0.5] 3178 }, 3179 "Script-Regular": { 3180 "32": [0, 0, 0, 0, 0.25], 3181 "65": [0, 0.7, 0.22925, 0, 0.80253], 3182 "66": [0, 0.7, 0.04087, 0, 0.90757], 3183 "67": [0, 0.7, 0.1689, 0, 0.66619], 3184 "68": [0, 0.7, 0.09371, 0, 0.77443], 3185 "69": [0, 0.7, 0.18583, 0, 0.56162], 3186 "70": [0, 0.7, 0.13634, 0, 0.89544], 3187 "71": [0, 0.7, 0.17322, 0, 0.60961], 3188 "72": [0, 0.7, 0.29694, 0, 0.96919], 3189 "73": [0, 0.7, 0.19189, 0, 0.80907], 3190 "74": [0.27778, 0.7, 0.19189, 0, 1.05159], 3191 "75": [0, 0.7, 0.31259, 0, 0.91364], 3192 "76": [0, 0.7, 0.19189, 0, 0.87373], 3193 "77": [0, 0.7, 0.15981, 0, 1.08031], 3194 "78": [0, 0.7, 0.3525, 0, 0.9015], 3195 "79": [0, 0.7, 0.08078, 0, 0.73787], 3196 "80": [0, 0.7, 0.08078, 0, 1.01262], 3197 "81": [0, 0.7, 0.03305, 0, 0.88282], 3198 "82": [0, 0.7, 0.06259, 0, 0.85], 3199 "83": [0, 0.7, 0.19189, 0, 0.86767], 3200 "84": [0, 0.7, 0.29087, 0, 0.74697], 3201 "85": [0, 0.7, 0.25815, 0, 0.79996], 3202 "86": [0, 0.7, 0.27523, 0, 0.62204], 3203 "87": [0, 0.7, 0.27523, 0, 0.80532], 3204 "88": [0, 0.7, 0.26006, 0, 0.94445], 3205 "89": [0, 0.7, 0.2939, 0, 0.70961], 3206 "90": [0, 0.7, 0.24037, 0, 0.8212], 3207 "160": [0, 0, 0, 0, 0.25] 3208 }, 3209 "Size1-Regular": { 3210 "32": [0, 0, 0, 0, 0.25], 3211 "40": [0.35001, 0.85, 0, 0, 0.45834], 3212 "41": [0.35001, 0.85, 0, 0, 0.45834], 3213 "47": [0.35001, 0.85, 0, 0, 0.57778], 3214 "91": [0.35001, 0.85, 0, 0, 0.41667], 3215 "92": [0.35001, 0.85, 0, 0, 0.57778], 3216 "93": [0.35001, 0.85, 0, 0, 0.41667], 3217 "123": [0.35001, 0.85, 0, 0, 0.58334], 3218 "125": [0.35001, 0.85, 0, 0, 0.58334], 3219 "160": [0, 0, 0, 0, 0.25], 3220 "710": [0, 0.72222, 0, 0, 0.55556], 3221 "732": [0, 0.72222, 0, 0, 0.55556], 3222 "770": [0, 0.72222, 0, 0, 0.55556], 3223 "771": [0, 0.72222, 0, 0, 0.55556], 3224 "8214": [-0.00099, 0.601, 0, 0, 0.77778], 3225 "8593": [1e-05, 0.6, 0, 0, 0.66667], 3226 "8595": [1e-05, 0.6, 0, 0, 0.66667], 3227 "8657": [1e-05, 0.6, 0, 0, 0.77778], 3228 "8659": [1e-05, 0.6, 0, 0, 0.77778], 3229 "8719": [0.25001, 0.75, 0, 0, 0.94445], 3230 "8720": [0.25001, 0.75, 0, 0, 0.94445], 3231 "8721": [0.25001, 0.75, 0, 0, 1.05556], 3232 "8730": [0.35001, 0.85, 0, 0, 1.0], 3233 "8739": [-0.00599, 0.606, 0, 0, 0.33333], 3234 "8741": [-0.00599, 0.606, 0, 0, 0.55556], 3235 "8747": [0.30612, 0.805, 0.19445, 0, 0.47222], 3236 "8748": [0.306, 0.805, 0.19445, 0, 0.47222], 3237 "8749": [0.306, 0.805, 0.19445, 0, 0.47222], 3238 "8750": [0.30612, 0.805, 0.19445, 0, 0.47222], 3239 "8896": [0.25001, 0.75, 0, 0, 0.83334], 3240 "8897": [0.25001, 0.75, 0, 0, 0.83334], 3241 "8898": [0.25001, 0.75, 0, 0, 0.83334], 3242 "8899": [0.25001, 0.75, 0, 0, 0.83334], 3243 "8968": [0.35001, 0.85, 0, 0, 0.47222], 3244 "8969": [0.35001, 0.85, 0, 0, 0.47222], 3245 "8970": [0.35001, 0.85, 0, 0, 0.47222], 3246 "8971": [0.35001, 0.85, 0, 0, 0.47222], 3247 "9168": [-0.00099, 0.601, 0, 0, 0.66667], 3248 "10216": [0.35001, 0.85, 0, 0, 0.47222], 3249 "10217": [0.35001, 0.85, 0, 0, 0.47222], 3250 "10752": [0.25001, 0.75, 0, 0, 1.11111], 3251 "10753": [0.25001, 0.75, 0, 0, 1.11111], 3252 "10754": [0.25001, 0.75, 0, 0, 1.11111], 3253 "10756": [0.25001, 0.75, 0, 0, 0.83334], 3254 "10758": [0.25001, 0.75, 0, 0, 0.83334] 3255 }, 3256 "Size2-Regular": { 3257 "32": [0, 0, 0, 0, 0.25], 3258 "40": [0.65002, 1.15, 0, 0, 0.59722], 3259 "41": [0.65002, 1.15, 0, 0, 0.59722], 3260 "47": [0.65002, 1.15, 0, 0, 0.81111], 3261 "91": [0.65002, 1.15, 0, 0, 0.47222], 3262 "92": [0.65002, 1.15, 0, 0, 0.81111], 3263 "93": [0.65002, 1.15, 0, 0, 0.47222], 3264 "123": [0.65002, 1.15, 0, 0, 0.66667], 3265 "125": [0.65002, 1.15, 0, 0, 0.66667], 3266 "160": [0, 0, 0, 0, 0.25], 3267 "710": [0, 0.75, 0, 0, 1.0], 3268 "732": [0, 0.75, 0, 0, 1.0], 3269 "770": [0, 0.75, 0, 0, 1.0], 3270 "771": [0, 0.75, 0, 0, 1.0], 3271 "8719": [0.55001, 1.05, 0, 0, 1.27778], 3272 "8720": [0.55001, 1.05, 0, 0, 1.27778], 3273 "8721": [0.55001, 1.05, 0, 0, 1.44445], 3274 "8730": [0.65002, 1.15, 0, 0, 1.0], 3275 "8747": [0.86225, 1.36, 0.44445, 0, 0.55556], 3276 "8748": [0.862, 1.36, 0.44445, 0, 0.55556], 3277 "8749": [0.862, 1.36, 0.44445, 0, 0.55556], 3278 "8750": [0.86225, 1.36, 0.44445, 0, 0.55556], 3279 "8896": [0.55001, 1.05, 0, 0, 1.11111], 3280 "8897": [0.55001, 1.05, 0, 0, 1.11111], 3281 "8898": [0.55001, 1.05, 0, 0, 1.11111], 3282 "8899": [0.55001, 1.05, 0, 0, 1.11111], 3283 "8968": [0.65002, 1.15, 0, 0, 0.52778], 3284 "8969": [0.65002, 1.15, 0, 0, 0.52778], 3285 "8970": [0.65002, 1.15, 0, 0, 0.52778], 3286 "8971": [0.65002, 1.15, 0, 0, 0.52778], 3287 "10216": [0.65002, 1.15, 0, 0, 0.61111], 3288 "10217": [0.65002, 1.15, 0, 0, 0.61111], 3289 "10752": [0.55001, 1.05, 0, 0, 1.51112], 3290 "10753": [0.55001, 1.05, 0, 0, 1.51112], 3291 "10754": [0.55001, 1.05, 0, 0, 1.51112], 3292 "10756": [0.55001, 1.05, 0, 0, 1.11111], 3293 "10758": [0.55001, 1.05, 0, 0, 1.11111] 3294 }, 3295 "Size3-Regular": { 3296 "32": [0, 0, 0, 0, 0.25], 3297 "40": [0.95003, 1.45, 0, 0, 0.73611], 3298 "41": [0.95003, 1.45, 0, 0, 0.73611], 3299 "47": [0.95003, 1.45, 0, 0, 1.04445], 3300 "91": [0.95003, 1.45, 0, 0, 0.52778], 3301 "92": [0.95003, 1.45, 0, 0, 1.04445], 3302 "93": [0.95003, 1.45, 0, 0, 0.52778], 3303 "123": [0.95003, 1.45, 0, 0, 0.75], 3304 "125": [0.95003, 1.45, 0, 0, 0.75], 3305 "160": [0, 0, 0, 0, 0.25], 3306 "710": [0, 0.75, 0, 0, 1.44445], 3307 "732": [0, 0.75, 0, 0, 1.44445], 3308 "770": [0, 0.75, 0, 0, 1.44445], 3309 "771": [0, 0.75, 0, 0, 1.44445], 3310 "8730": [0.95003, 1.45, 0, 0, 1.0], 3311 "8968": [0.95003, 1.45, 0, 0, 0.58334], 3312 "8969": [0.95003, 1.45, 0, 0, 0.58334], 3313 "8970": [0.95003, 1.45, 0, 0, 0.58334], 3314 "8971": [0.95003, 1.45, 0, 0, 0.58334], 3315 "10216": [0.95003, 1.45, 0, 0, 0.75], 3316 "10217": [0.95003, 1.45, 0, 0, 0.75] 3317 }, 3318 "Size4-Regular": { 3319 "32": [0, 0, 0, 0, 0.25], 3320 "40": [1.25003, 1.75, 0, 0, 0.79167], 3321 "41": [1.25003, 1.75, 0, 0, 0.79167], 3322 "47": [1.25003, 1.75, 0, 0, 1.27778], 3323 "91": [1.25003, 1.75, 0, 0, 0.58334], 3324 "92": [1.25003, 1.75, 0, 0, 1.27778], 3325 "93": [1.25003, 1.75, 0, 0, 0.58334], 3326 "123": [1.25003, 1.75, 0, 0, 0.80556], 3327 "125": [1.25003, 1.75, 0, 0, 0.80556], 3328 "160": [0, 0, 0, 0, 0.25], 3329 "710": [0, 0.825, 0, 0, 1.8889], 3330 "732": [0, 0.825, 0, 0, 1.8889], 3331 "770": [0, 0.825, 0, 0, 1.8889], 3332 "771": [0, 0.825, 0, 0, 1.8889], 3333 "8730": [1.25003, 1.75, 0, 0, 1.0], 3334 "8968": [1.25003, 1.75, 0, 0, 0.63889], 3335 "8969": [1.25003, 1.75, 0, 0, 0.63889], 3336 "8970": [1.25003, 1.75, 0, 0, 0.63889], 3337 "8971": [1.25003, 1.75, 0, 0, 0.63889], 3338 "9115": [0.64502, 1.155, 0, 0, 0.875], 3339 "9116": [1e-05, 0.6, 0, 0, 0.875], 3340 "9117": [0.64502, 1.155, 0, 0, 0.875], 3341 "9118": [0.64502, 1.155, 0, 0, 0.875], 3342 "9119": [1e-05, 0.6, 0, 0, 0.875], 3343 "9120": [0.64502, 1.155, 0, 0, 0.875], 3344 "9121": [0.64502, 1.155, 0, 0, 0.66667], 3345 "9122": [-0.00099, 0.601, 0, 0, 0.66667], 3346 "9123": [0.64502, 1.155, 0, 0, 0.66667], 3347 "9124": [0.64502, 1.155, 0, 0, 0.66667], 3348 "9125": [-0.00099, 0.601, 0, 0, 0.66667], 3349 "9126": [0.64502, 1.155, 0, 0, 0.66667], 3350 "9127": [1e-05, 0.9, 0, 0, 0.88889], 3351 "9128": [0.65002, 1.15, 0, 0, 0.88889], 3352 "9129": [0.90001, 0, 0, 0, 0.88889], 3353 "9130": [0, 0.3, 0, 0, 0.88889], 3354 "9131": [1e-05, 0.9, 0, 0, 0.88889], 3355 "9132": [0.65002, 1.15, 0, 0, 0.88889], 3356 "9133": [0.90001, 0, 0, 0, 0.88889], 3357 "9143": [0.88502, 0.915, 0, 0, 1.05556], 3358 "10216": [1.25003, 1.75, 0, 0, 0.80556], 3359 "10217": [1.25003, 1.75, 0, 0, 0.80556], 3360 "57344": [-0.00499, 0.605, 0, 0, 1.05556], 3361 "57345": [-0.00499, 0.605, 0, 0, 1.05556], 3362 "57680": [0, 0.12, 0, 0, 0.45], 3363 "57681": [0, 0.12, 0, 0, 0.45], 3364 "57682": [0, 0.12, 0, 0, 0.45], 3365 "57683": [0, 0.12, 0, 0, 0.45] 3366 }, 3367 "Typewriter-Regular": { 3368 "32": [0, 0, 0, 0, 0.525], 3369 "33": [0, 0.61111, 0, 0, 0.525], 3370 "34": [0, 0.61111, 0, 0, 0.525], 3371 "35": [0, 0.61111, 0, 0, 0.525], 3372 "36": [0.08333, 0.69444, 0, 0, 0.525], 3373 "37": [0.08333, 0.69444, 0, 0, 0.525], 3374 "38": [0, 0.61111, 0, 0, 0.525], 3375 "39": [0, 0.61111, 0, 0, 0.525], 3376 "40": [0.08333, 0.69444, 0, 0, 0.525], 3377 "41": [0.08333, 0.69444, 0, 0, 0.525], 3378 "42": [0, 0.52083, 0, 0, 0.525], 3379 "43": [-0.08056, 0.53055, 0, 0, 0.525], 3380 "44": [0.13889, 0.125, 0, 0, 0.525], 3381 "45": [-0.08056, 0.53055, 0, 0, 0.525], 3382 "46": [0, 0.125, 0, 0, 0.525], 3383 "47": [0.08333, 0.69444, 0, 0, 0.525], 3384 "48": [0, 0.61111, 0, 0, 0.525], 3385 "49": [0, 0.61111, 0, 0, 0.525], 3386 "50": [0, 0.61111, 0, 0, 0.525], 3387 "51": [0, 0.61111, 0, 0, 0.525], 3388 "52": [0, 0.61111, 0, 0, 0.525], 3389 "53": [0, 0.61111, 0, 0, 0.525], 3390 "54": [0, 0.61111, 0, 0, 0.525], 3391 "55": [0, 0.61111, 0, 0, 0.525], 3392 "56": [0, 0.61111, 0, 0, 0.525], 3393 "57": [0, 0.61111, 0, 0, 0.525], 3394 "58": [0, 0.43056, 0, 0, 0.525], 3395 "59": [0.13889, 0.43056, 0, 0, 0.525], 3396 "60": [-0.05556, 0.55556, 0, 0, 0.525], 3397 "61": [-0.19549, 0.41562, 0, 0, 0.525], 3398 "62": [-0.05556, 0.55556, 0, 0, 0.525], 3399 "63": [0, 0.61111, 0, 0, 0.525], 3400 "64": [0, 0.61111, 0, 0, 0.525], 3401 "65": [0, 0.61111, 0, 0, 0.525], 3402 "66": [0, 0.61111, 0, 0, 0.525], 3403 "67": [0, 0.61111, 0, 0, 0.525], 3404 "68": [0, 0.61111, 0, 0, 0.525], 3405 "69": [0, 0.61111, 0, 0, 0.525], 3406 "70": [0, 0.61111, 0, 0, 0.525], 3407 "71": [0, 0.61111, 0, 0, 0.525], 3408 "72": [0, 0.61111, 0, 0, 0.525], 3409 "73": [0, 0.61111, 0, 0, 0.525], 3410 "74": [0, 0.61111, 0, 0, 0.525], 3411 "75": [0, 0.61111, 0, 0, 0.525], 3412 "76": [0, 0.61111, 0, 0, 0.525], 3413 "77": [0, 0.61111, 0, 0, 0.525], 3414 "78": [0, 0.61111, 0, 0, 0.525], 3415 "79": [0, 0.61111, 0, 0, 0.525], 3416 "80": [0, 0.61111, 0, 0, 0.525], 3417 "81": [0.13889, 0.61111, 0, 0, 0.525], 3418 "82": [0, 0.61111, 0, 0, 0.525], 3419 "83": [0, 0.61111, 0, 0, 0.525], 3420 "84": [0, 0.61111, 0, 0, 0.525], 3421 "85": [0, 0.61111, 0, 0, 0.525], 3422 "86": [0, 0.61111, 0, 0, 0.525], 3423 "87": [0, 0.61111, 0, 0, 0.525], 3424 "88": [0, 0.61111, 0, 0, 0.525], 3425 "89": [0, 0.61111, 0, 0, 0.525], 3426 "90": [0, 0.61111, 0, 0, 0.525], 3427 "91": [0.08333, 0.69444, 0, 0, 0.525], 3428 "92": [0.08333, 0.69444, 0, 0, 0.525], 3429 "93": [0.08333, 0.69444, 0, 0, 0.525], 3430 "94": [0, 0.61111, 0, 0, 0.525], 3431 "95": [0.09514, 0, 0, 0, 0.525], 3432 "96": [0, 0.61111, 0, 0, 0.525], 3433 "97": [0, 0.43056, 0, 0, 0.525], 3434 "98": [0, 0.61111, 0, 0, 0.525], 3435 "99": [0, 0.43056, 0, 0, 0.525], 3436 "100": [0, 0.61111, 0, 0, 0.525], 3437 "101": [0, 0.43056, 0, 0, 0.525], 3438 "102": [0, 0.61111, 0, 0, 0.525], 3439 "103": [0.22222, 0.43056, 0, 0, 0.525], 3440 "104": [0, 0.61111, 0, 0, 0.525], 3441 "105": [0, 0.61111, 0, 0, 0.525], 3442 "106": [0.22222, 0.61111, 0, 0, 0.525], 3443 "107": [0, 0.61111, 0, 0, 0.525], 3444 "108": [0, 0.61111, 0, 0, 0.525], 3445 "109": [0, 0.43056, 0, 0, 0.525], 3446 "110": [0, 0.43056, 0, 0, 0.525], 3447 "111": [0, 0.43056, 0, 0, 0.525], 3448 "112": [0.22222, 0.43056, 0, 0, 0.525], 3449 "113": [0.22222, 0.43056, 0, 0, 0.525], 3450 "114": [0, 0.43056, 0, 0, 0.525], 3451 "115": [0, 0.43056, 0, 0, 0.525], 3452 "116": [0, 0.55358, 0, 0, 0.525], 3453 "117": [0, 0.43056, 0, 0, 0.525], 3454 "118": [0, 0.43056, 0, 0, 0.525], 3455 "119": [0, 0.43056, 0, 0, 0.525], 3456 "120": [0, 0.43056, 0, 0, 0.525], 3457 "121": [0.22222, 0.43056, 0, 0, 0.525], 3458 "122": [0, 0.43056, 0, 0, 0.525], 3459 "123": [0.08333, 0.69444, 0, 0, 0.525], 3460 "124": [0.08333, 0.69444, 0, 0, 0.525], 3461 "125": [0.08333, 0.69444, 0, 0, 0.525], 3462 "126": [0, 0.61111, 0, 0, 0.525], 3463 "127": [0, 0.61111, 0, 0, 0.525], 3464 "160": [0, 0, 0, 0, 0.525], 3465 "176": [0, 0.61111, 0, 0, 0.525], 3466 "184": [0.19445, 0, 0, 0, 0.525], 3467 "305": [0, 0.43056, 0, 0, 0.525], 3468 "567": [0.22222, 0.43056, 0, 0, 0.525], 3469 "711": [0, 0.56597, 0, 0, 0.525], 3470 "713": [0, 0.56555, 0, 0, 0.525], 3471 "714": [0, 0.61111, 0, 0, 0.525], 3472 "715": [0, 0.61111, 0, 0, 0.525], 3473 "728": [0, 0.61111, 0, 0, 0.525], 3474 "730": [0, 0.61111, 0, 0, 0.525], 3475 "770": [0, 0.61111, 0, 0, 0.525], 3476 "771": [0, 0.61111, 0, 0, 0.525], 3477 "776": [0, 0.61111, 0, 0, 0.525], 3478 "915": [0, 0.61111, 0, 0, 0.525], 3479 "916": [0, 0.61111, 0, 0, 0.525], 3480 "920": [0, 0.61111, 0, 0, 0.525], 3481 "923": [0, 0.61111, 0, 0, 0.525], 3482 "926": [0, 0.61111, 0, 0, 0.525], 3483 "928": [0, 0.61111, 0, 0, 0.525], 3484 "931": [0, 0.61111, 0, 0, 0.525], 3485 "933": [0, 0.61111, 0, 0, 0.525], 3486 "934": [0, 0.61111, 0, 0, 0.525], 3487 "936": [0, 0.61111, 0, 0, 0.525], 3488 "937": [0, 0.61111, 0, 0, 0.525], 3489 "8216": [0, 0.61111, 0, 0, 0.525], 3490 "8217": [0, 0.61111, 0, 0, 0.525], 3491 "8242": [0, 0.61111, 0, 0, 0.525], 3492 "9251": [0.11111, 0.21944, 0, 0, 0.525] 3493 } 3494 }; 3495 3496 /** 3497 * This file contains metrics regarding fonts and individual symbols. The sigma 3498 * and xi variables, as well as the metricMap map contain data extracted from 3499 * TeX, TeX font metrics, and the TTF files. These data are then exposed via the 3500 * `metrics` variable and the getCharacterMetrics function. 3501 */ 3502 // In TeX, there are actually three sets of dimensions, one for each of 3503 // textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4: 3504 // 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt). These are 3505 // provided in the the arrays below, in that order. 3506 // 3507 // The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively. 3508 // This was determined by running the following script: 3509 // 3510 // latex -interaction=nonstopmode \ 3511 // '\documentclass{article}\usepackage{amsmath}\begin{document}' \ 3512 // '$a$ \expandafter\show\the\textfont2' \ 3513 // '\expandafter\show\the\scriptfont2' \ 3514 // '\expandafter\show\the\scriptscriptfont2' \ 3515 // '\stop' 3516 // 3517 // The metrics themselves were retreived using the following commands: 3518 // 3519 // tftopl cmsy10 3520 // tftopl cmsy7 3521 // tftopl cmsy5 3522 // 3523 // The output of each of these commands is quite lengthy. The only part we 3524 // care about is the FONTDIMEN section. Each value is measured in EMs. 3525 var sigmasAndXis = { 3526 slant: [0.250, 0.250, 0.250], 3527 // sigma1 3528 space: [0.000, 0.000, 0.000], 3529 // sigma2 3530 stretch: [0.000, 0.000, 0.000], 3531 // sigma3 3532 shrink: [0.000, 0.000, 0.000], 3533 // sigma4 3534 xHeight: [0.431, 0.431, 0.431], 3535 // sigma5 3536 quad: [1.000, 1.171, 1.472], 3537 // sigma6 3538 extraSpace: [0.000, 0.000, 0.000], 3539 // sigma7 3540 num1: [0.677, 0.732, 0.925], 3541 // sigma8 3542 num2: [0.394, 0.384, 0.387], 3543 // sigma9 3544 num3: [0.444, 0.471, 0.504], 3545 // sigma10 3546 denom1: [0.686, 0.752, 1.025], 3547 // sigma11 3548 denom2: [0.345, 0.344, 0.532], 3549 // sigma12 3550 sup1: [0.413, 0.503, 0.504], 3551 // sigma13 3552 sup2: [0.363, 0.431, 0.404], 3553 // sigma14 3554 sup3: [0.289, 0.286, 0.294], 3555 // sigma15 3556 sub1: [0.150, 0.143, 0.200], 3557 // sigma16 3558 sub2: [0.247, 0.286, 0.400], 3559 // sigma17 3560 supDrop: [0.386, 0.353, 0.494], 3561 // sigma18 3562 subDrop: [0.050, 0.071, 0.100], 3563 // sigma19 3564 delim1: [2.390, 1.700, 1.980], 3565 // sigma20 3566 delim2: [1.010, 1.157, 1.420], 3567 // sigma21 3568 axisHeight: [0.250, 0.250, 0.250], 3569 // sigma22 3570 // These font metrics are extracted from TeX by using tftopl on cmex10.tfm; 3571 // they correspond to the font parameters of the extension fonts (family 3). 3572 // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to 3573 // match cmex7, we'd use cmex7.tfm values for script and scriptscript 3574 // values. 3575 defaultRuleThickness: [0.04, 0.049, 0.049], 3576 // xi8; cmex7: 0.049 3577 bigOpSpacing1: [0.111, 0.111, 0.111], 3578 // xi9 3579 bigOpSpacing2: [0.166, 0.166, 0.166], 3580 // xi10 3581 bigOpSpacing3: [0.2, 0.2, 0.2], 3582 // xi11 3583 bigOpSpacing4: [0.6, 0.611, 0.611], 3584 // xi12; cmex7: 0.611 3585 bigOpSpacing5: [0.1, 0.143, 0.143], 3586 // xi13; cmex7: 0.143 3587 // The \sqrt rule width is taken from the height of the surd character. 3588 // Since we use the same font at all sizes, this thickness doesn't scale. 3589 sqrtRuleThickness: [0.04, 0.04, 0.04], 3590 // This value determines how large a pt is, for metrics which are defined 3591 // in terms of pts. 3592 // This value is also used in katex.less; if you change it make sure the 3593 // values match. 3594 ptPerEm: [10.0, 10.0, 10.0], 3595 // The space between adjacent `|` columns in an array definition. From 3596 // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm. 3597 doubleRuleSep: [0.2, 0.2, 0.2], 3598 // The width of separator lines in {array} environments. From 3599 // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm. 3600 arrayRuleWidth: [0.04, 0.04, 0.04], 3601 // Two values from LaTeX source2e: 3602 fboxsep: [0.3, 0.3, 0.3], 3603 // 3 pt / ptPerEm 3604 fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm 3605 3606 }; // This map contains a mapping from font name and character code to character 3607 // should have Latin-1 and Cyrillic characters, but may not depending on the 3608 // operating system. The metrics do not account for extra height from the 3609 // accents. In the case of Cyrillic characters which have both ascenders and 3610 // descenders we prefer approximations with ascenders, primarily to prevent 3611 // the fraction bar or root line from intersecting the glyph. 3612 // TODO(kevinb) allow union of multiple glyph metrics for better accuracy. 3613 3614 var extraCharacterMap = { 3615 // Latin-1 3616 'Å': 'A', 3617 'Ç': 'C', 3618 'Ð': 'D', 3619 'Þ': 'o', 3620 'å': 'a', 3621 'ç': 'c', 3622 'ð': 'd', 3623 'þ': 'o', 3624 // Cyrillic 3625 'А': 'A', 3626 'Б': 'B', 3627 'В': 'B', 3628 'Г': 'F', 3629 'Д': 'A', 3630 'Е': 'E', 3631 'Ж': 'K', 3632 'З': '3', 3633 'И': 'N', 3634 'Й': 'N', 3635 'К': 'K', 3636 'Л': 'N', 3637 'М': 'M', 3638 'Н': 'H', 3639 'О': 'O', 3640 'П': 'N', 3641 'Р': 'P', 3642 'С': 'C', 3643 'Т': 'T', 3644 'У': 'y', 3645 'Ф': 'O', 3646 'Х': 'X', 3647 'Ц': 'U', 3648 'Ч': 'h', 3649 'Ш': 'W', 3650 'Щ': 'W', 3651 'Ъ': 'B', 3652 'Ы': 'X', 3653 'Ь': 'B', 3654 'Э': '3', 3655 'Ю': 'X', 3656 'Я': 'R', 3657 'а': 'a', 3658 'б': 'b', 3659 'в': 'a', 3660 'г': 'r', 3661 'д': 'y', 3662 'е': 'e', 3663 'ж': 'm', 3664 'з': 'e', 3665 'и': 'n', 3666 'й': 'n', 3667 'к': 'n', 3668 'л': 'n', 3669 'м': 'm', 3670 'н': 'n', 3671 'о': 'o', 3672 'п': 'n', 3673 'р': 'p', 3674 'с': 'c', 3675 'т': 'o', 3676 'у': 'y', 3677 'ф': 'b', 3678 'х': 'x', 3679 'ц': 'n', 3680 'ч': 'n', 3681 'ш': 'w', 3682 'щ': 'w', 3683 'ъ': 'a', 3684 'ы': 'm', 3685 'ь': 'a', 3686 'э': 'e', 3687 'ю': 'm', 3688 'я': 'r' 3689 }; 3690 3691 /** 3692 * This function adds new font metrics to default metricMap 3693 * It can also override existing metrics 3694 */ 3695 function setFontMetrics(fontName, metrics) { 3696 fontMetricsData[fontName] = metrics; 3697 } 3698 /** 3699 * This function is a convenience function for looking up information in the 3700 * metricMap table. It takes a character as a string, and a font. 3701 * 3702 * Note: the `width` property may be undefined if fontMetricsData.js wasn't 3703 * built using `Make extended_metrics`. 3704 */ 3705 3706 function getCharacterMetrics(character, font, mode) { 3707 if (!fontMetricsData[font]) { 3708 throw new Error("Font metrics not found for font: " + font + "."); 3709 } 3710 3711 var ch = character.charCodeAt(0); 3712 var metrics = fontMetricsData[font][ch]; 3713 3714 if (!metrics && character[0] in extraCharacterMap) { 3715 ch = extraCharacterMap[character[0]].charCodeAt(0); 3716 metrics = fontMetricsData[font][ch]; 3717 } 3718 3719 if (!metrics && mode === 'text') { 3720 // We don't typically have font metrics for Asian scripts. 3721 // But since we support them in text mode, we need to return 3722 // some sort of metrics. 3723 // So if the character is in a script we support but we 3724 // don't have metrics for it, just use the metrics for 3725 // the Latin capital letter M. This is close enough because 3726 // we (currently) only care about the height of the glpyh 3727 // not its width. 3728 if (supportedCodepoint(ch)) { 3729 metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M' 3730 } 3731 } 3732 3733 if (metrics) { 3734 return { 3735 depth: metrics[0], 3736 height: metrics[1], 3737 italic: metrics[2], 3738 skew: metrics[3], 3739 width: metrics[4] 3740 }; 3741 } 3742 } 3743 var fontMetricsBySizeIndex = {}; 3744 /** 3745 * Get the font metrics for a given size. 3746 */ 3747 3748 function getGlobalMetrics(size) { 3749 var sizeIndex; 3750 3751 if (size >= 5) { 3752 sizeIndex = 0; 3753 } else if (size >= 3) { 3754 sizeIndex = 1; 3755 } else { 3756 sizeIndex = 2; 3757 } 3758 3759 if (!fontMetricsBySizeIndex[sizeIndex]) { 3760 var metrics = fontMetricsBySizeIndex[sizeIndex] = { 3761 cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18 3762 }; 3763 3764 for (var key in sigmasAndXis) { 3765 if (sigmasAndXis.hasOwnProperty(key)) { 3766 metrics[key] = sigmasAndXis[key][sizeIndex]; 3767 } 3768 } 3769 } 3770 3771 return fontMetricsBySizeIndex[sizeIndex]; 3772 } 3773 3774 /** 3775 * This file holds a list of all no-argument functions and single-character 3776 * symbols (like 'a' or ';'). 3777 * 3778 * For each of the symbols, there are three properties they can have: 3779 * - font (required): the font to be used for this symbol. Either "main" (the 3780 normal font), or "ams" (the ams fonts). 3781 * - group (required): the ParseNode group type the symbol should have (i.e. 3782 "textord", "mathord", etc). 3783 See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types 3784 * - replace: the character that this symbol or function should be 3785 * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi 3786 * character in the main font). 3787 * 3788 * The outermost map in the table indicates what mode the symbols should be 3789 * accepted in (e.g. "math" or "text"). 3790 */ 3791 // Some of these have a "-token" suffix since these are also used as `ParseNode` 3792 // types for raw text tokens, and we want to avoid conflicts with higher-level 3793 // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by 3794 // looking up the `symbols` map. 3795 var ATOMS = { 3796 "bin": 1, 3797 "close": 1, 3798 "inner": 1, 3799 "open": 1, 3800 "punct": 1, 3801 "rel": 1 3802 }; 3803 var NON_ATOMS = { 3804 "accent-token": 1, 3805 "mathord": 1, 3806 "op-token": 1, 3807 "spacing": 1, 3808 "textord": 1 3809 }; 3810 var symbols = { 3811 "math": {}, 3812 "text": {} 3813 }; 3814 /** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ 3815 3816 function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) { 3817 symbols[mode][name] = { 3818 font, 3819 group, 3820 replace 3821 }; 3822 3823 if (acceptUnicodeChar && replace) { 3824 symbols[mode][replace] = symbols[mode][name]; 3825 } 3826 } // Some abbreviations for commonly used strings. 3827 // This helps minify the code, and also spotting typos using jshint. 3828 // modes: 3829 3830 var math = "math"; 3831 var text$1 = "text"; // fonts: 3832 3833 var main = "main"; 3834 var ams = "ams"; // groups: 3835 3836 var accent = "accent-token"; 3837 var bin = "bin"; 3838 var close = "close"; 3839 var inner = "inner"; 3840 var mathord = "mathord"; 3841 var op = "op-token"; 3842 var open = "open"; 3843 var punct = "punct"; 3844 var rel = "rel"; 3845 var spacing = "spacing"; 3846 var textord = "textord"; // Now comes the symbol table 3847 // Relation Symbols 3848 3849 defineSymbol(math, main, rel, "\u2261", "\\equiv", true); 3850 defineSymbol(math, main, rel, "\u227a", "\\prec", true); 3851 defineSymbol(math, main, rel, "\u227b", "\\succ", true); 3852 defineSymbol(math, main, rel, "\u223c", "\\sim", true); 3853 defineSymbol(math, main, rel, "\u22a5", "\\perp"); 3854 defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true); 3855 defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true); 3856 defineSymbol(math, main, rel, "\u2243", "\\simeq", true); 3857 defineSymbol(math, main, rel, "\u2223", "\\mid", true); 3858 defineSymbol(math, main, rel, "\u226a", "\\ll", true); 3859 defineSymbol(math, main, rel, "\u226b", "\\gg", true); 3860 defineSymbol(math, main, rel, "\u224d", "\\asymp", true); 3861 defineSymbol(math, main, rel, "\u2225", "\\parallel"); 3862 defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true); 3863 defineSymbol(math, main, rel, "\u2323", "\\smile", true); 3864 defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true); 3865 defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true); 3866 defineSymbol(math, main, rel, "\u2250", "\\doteq", true); 3867 defineSymbol(math, main, rel, "\u2322", "\\frown", true); 3868 defineSymbol(math, main, rel, "\u220b", "\\ni", true); 3869 defineSymbol(math, main, rel, "\u221d", "\\propto", true); 3870 defineSymbol(math, main, rel, "\u22a2", "\\vdash", true); 3871 defineSymbol(math, main, rel, "\u22a3", "\\dashv", true); 3872 defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation 3873 3874 defineSymbol(math, main, punct, "\u002e", "\\ldotp"); 3875 defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols 3876 3877 defineSymbol(math, main, textord, "\u0023", "\\#"); 3878 defineSymbol(text$1, main, textord, "\u0023", "\\#"); 3879 defineSymbol(math, main, textord, "\u0026", "\\&"); 3880 defineSymbol(text$1, main, textord, "\u0026", "\\&"); 3881 defineSymbol(math, main, textord, "\u2135", "\\aleph", true); 3882 defineSymbol(math, main, textord, "\u2200", "\\forall", true); 3883 defineSymbol(math, main, textord, "\u210f", "\\hbar", true); 3884 defineSymbol(math, main, textord, "\u2203", "\\exists", true); 3885 defineSymbol(math, main, textord, "\u2207", "\\nabla", true); 3886 defineSymbol(math, main, textord, "\u266d", "\\flat", true); 3887 defineSymbol(math, main, textord, "\u2113", "\\ell", true); 3888 defineSymbol(math, main, textord, "\u266e", "\\natural", true); 3889 defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true); 3890 defineSymbol(math, main, textord, "\u2118", "\\wp", true); 3891 defineSymbol(math, main, textord, "\u266f", "\\sharp", true); 3892 defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true); 3893 defineSymbol(math, main, textord, "\u211c", "\\Re", true); 3894 defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true); 3895 defineSymbol(math, main, textord, "\u2111", "\\Im", true); 3896 defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true); 3897 defineSymbol(text$1, main, textord, "\u00a7", "\\S", true); 3898 defineSymbol(text$1, main, textord, "\u00b6", "\\P", true); // Math and Text 3899 3900 defineSymbol(math, main, textord, "\u2020", "\\dag"); 3901 defineSymbol(text$1, main, textord, "\u2020", "\\dag"); 3902 defineSymbol(text$1, main, textord, "\u2020", "\\textdagger"); 3903 defineSymbol(math, main, textord, "\u2021", "\\ddag"); 3904 defineSymbol(text$1, main, textord, "\u2021", "\\ddag"); 3905 defineSymbol(text$1, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters 3906 3907 defineSymbol(math, main, close, "\u23b1", "\\rmoustache", true); 3908 defineSymbol(math, main, open, "\u23b0", "\\lmoustache", true); 3909 defineSymbol(math, main, close, "\u27ef", "\\rgroup", true); 3910 defineSymbol(math, main, open, "\u27ee", "\\lgroup", true); // Binary Operators 3911 3912 defineSymbol(math, main, bin, "\u2213", "\\mp", true); 3913 defineSymbol(math, main, bin, "\u2296", "\\ominus", true); 3914 defineSymbol(math, main, bin, "\u228e", "\\uplus", true); 3915 defineSymbol(math, main, bin, "\u2293", "\\sqcap", true); 3916 defineSymbol(math, main, bin, "\u2217", "\\ast"); 3917 defineSymbol(math, main, bin, "\u2294", "\\sqcup", true); 3918 defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true); 3919 defineSymbol(math, main, bin, "\u2219", "\\bullet"); 3920 defineSymbol(math, main, bin, "\u2021", "\\ddagger"); 3921 defineSymbol(math, main, bin, "\u2240", "\\wr", true); 3922 defineSymbol(math, main, bin, "\u2a3f", "\\amalg"); 3923 defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath 3924 // Arrow Symbols 3925 3926 defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true); 3927 defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true); 3928 defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true); 3929 defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true); 3930 defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true); 3931 defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true); 3932 defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true); 3933 defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true); 3934 defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true); 3935 defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true); 3936 defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true); 3937 defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true); 3938 defineSymbol(math, main, rel, "\u2197", "\\nearrow", true); 3939 defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true); 3940 defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true); 3941 defineSymbol(math, main, rel, "\u2198", "\\searrow", true); 3942 defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true); 3943 defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true); 3944 defineSymbol(math, main, rel, "\u2199", "\\swarrow", true); 3945 defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true); 3946 defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true); 3947 defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true); 3948 defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations 3949 3950 defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceeded by "@" each have a corresponding macro. 3951 3952 defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant"); 3953 defineSymbol(math, ams, rel, "\ue011", "\\@nleqq"); 3954 defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true); 3955 defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true); 3956 defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq"); 3957 defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true); 3958 defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true); 3959 defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. 3960 3961 defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true); 3962 defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true); 3963 defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true); 3964 defineSymbol(math, ams, rel, "\u2241", "\\nsim", true); 3965 defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid"); 3966 defineSymbol(math, ams, rel, "\u2224", "\\nmid", true); 3967 defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true); 3968 defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true); 3969 defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft"); 3970 defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true); 3971 defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true); 3972 defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq"); 3973 defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true); 3974 defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq"); 3975 defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true); 3976 defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant"); 3977 defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq"); 3978 defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true); 3979 defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true); 3980 defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq"); 3981 defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true); 3982 defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true); 3983 defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. 3984 3985 defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true); 3986 defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true); 3987 defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. 3988 3989 defineSymbol(math, ams, rel, "\u2246", "\\ncong", true); 3990 defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel"); 3991 defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true); 3992 defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true); 3993 defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright"); 3994 defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true); 3995 defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq"); 3996 defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true); 3997 defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq"); 3998 defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true); 3999 defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq"); 4000 defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true); 4001 defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true); 4002 defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true); 4003 defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq"); 4004 defineSymbol(math, ams, bin, "\u22b4", "\\unlhd"); 4005 defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows 4006 4007 defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true); 4008 defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true); 4009 defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true); 4010 defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true); 4011 defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true); 4012 defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc 4013 4014 defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle"); 4015 defineSymbol(math, ams, textord, "\u210f", "\\hslash"); 4016 defineSymbol(math, ams, textord, "\u25bd", "\\triangledown"); 4017 defineSymbol(math, ams, textord, "\u25ca", "\\lozenge"); 4018 defineSymbol(math, ams, textord, "\u24c8", "\\circledS"); 4019 defineSymbol(math, ams, textord, "\u00ae", "\\circledR"); 4020 defineSymbol(text$1, ams, textord, "\u00ae", "\\circledR"); 4021 defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true); 4022 defineSymbol(math, ams, textord, "\u2204", "\\nexists"); 4023 defineSymbol(math, ams, textord, "\u2127", "\\mho"); 4024 defineSymbol(math, ams, textord, "\u2132", "\\Finv", true); 4025 defineSymbol(math, ams, textord, "\u2141", "\\Game", true); 4026 defineSymbol(math, ams, textord, "\u2035", "\\backprime"); 4027 defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle"); 4028 defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown"); 4029 defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare"); 4030 defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge"); 4031 defineSymbol(math, ams, textord, "\u2605", "\\bigstar"); 4032 defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true); 4033 defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 to \matheth. We map to AMS function \eth 4034 4035 defineSymbol(math, ams, textord, "\u00f0", "\\eth", true); 4036 defineSymbol(text$1, main, textord, "\u00f0", "\u00f0"); 4037 defineSymbol(math, ams, textord, "\u2571", "\\diagup"); 4038 defineSymbol(math, ams, textord, "\u2572", "\\diagdown"); 4039 defineSymbol(math, ams, textord, "\u25a1", "\\square"); 4040 defineSymbol(math, ams, textord, "\u25a1", "\\Box"); 4041 defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen 4042 4043 defineSymbol(math, ams, textord, "\u00a5", "\\yen", true); 4044 defineSymbol(text$1, ams, textord, "\u00a5", "\\yen", true); 4045 defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true); 4046 defineSymbol(text$1, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew 4047 4048 defineSymbol(math, ams, textord, "\u2136", "\\beth", true); 4049 defineSymbol(math, ams, textord, "\u2138", "\\daleth", true); 4050 defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek 4051 4052 defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true); 4053 defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters 4054 4055 defineSymbol(math, ams, open, "\u250c", "\\@ulcorner", true); 4056 defineSymbol(math, ams, close, "\u2510", "\\@urcorner", true); 4057 defineSymbol(math, ams, open, "\u2514", "\\@llcorner", true); 4058 defineSymbol(math, ams, close, "\u2518", "\\@lrcorner", true); // AMS Binary Relations 4059 4060 defineSymbol(math, ams, rel, "\u2266", "\\leqq", true); 4061 defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true); 4062 defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true); 4063 defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true); 4064 defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true); 4065 defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true); 4066 defineSymbol(math, ams, bin, "\u22d6", "\\lessdot"); 4067 defineSymbol(math, ams, rel, "\u22d8", "\\lll", true); 4068 defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true); 4069 defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true); 4070 defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true); 4071 defineSymbol(math, ams, rel, "\u2251", "\\doteqdot"); 4072 defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true); 4073 defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true); 4074 defineSymbol(math, ams, rel, "\u223d", "\\backsim", true); 4075 defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true); 4076 defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true); 4077 defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true); 4078 defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true); 4079 defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true); 4080 defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true); 4081 defineSymbol(math, ams, rel, "\u227e", "\\precsim", true); 4082 defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true); 4083 defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft"); 4084 defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq"); 4085 defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true); 4086 defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true); 4087 defineSymbol(math, ams, rel, "\u2323", "\\smallsmile"); 4088 defineSymbol(math, ams, rel, "\u2322", "\\smallfrown"); 4089 defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true); 4090 defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true); 4091 defineSymbol(math, ams, rel, "\u2267", "\\geqq", true); 4092 defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true); 4093 defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true); 4094 defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true); 4095 defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true); 4096 defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot"); 4097 defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true); 4098 defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true); 4099 defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true); 4100 defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true); 4101 defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true); 4102 defineSymbol(math, ams, rel, "\u2257", "\\circeq", true); 4103 defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true); 4104 defineSymbol(math, ams, rel, "\u223c", "\\thicksim"); 4105 defineSymbol(math, ams, rel, "\u2248", "\\thickapprox"); 4106 defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true); 4107 defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true); 4108 defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true); 4109 defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true); 4110 defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true); 4111 defineSymbol(math, ams, rel, "\u227f", "\\succsim", true); 4112 defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true); 4113 defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright"); 4114 defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq"); 4115 defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true); 4116 defineSymbol(math, ams, rel, "\u2223", "\\shortmid"); 4117 defineSymbol(math, ams, rel, "\u2225", "\\shortparallel"); 4118 defineSymbol(math, ams, rel, "\u226c", "\\between", true); 4119 defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true); 4120 defineSymbol(math, ams, rel, "\u221d", "\\varpropto"); 4121 defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom. 4122 // We kept the amssymb atom type, which is rel. 4123 4124 defineSymbol(math, ams, rel, "\u2234", "\\therefore", true); 4125 defineSymbol(math, ams, rel, "\u220d", "\\backepsilon"); 4126 defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom. 4127 // We kept the amssymb atom type, which is rel. 4128 4129 defineSymbol(math, ams, rel, "\u2235", "\\because", true); 4130 defineSymbol(math, ams, rel, "\u22d8", "\\llless"); 4131 defineSymbol(math, ams, rel, "\u22d9", "\\gggtr"); 4132 defineSymbol(math, ams, bin, "\u22b2", "\\lhd"); 4133 defineSymbol(math, ams, bin, "\u22b3", "\\rhd"); 4134 defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true); 4135 defineSymbol(math, main, rel, "\u22c8", "\\Join"); 4136 defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators 4137 4138 defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true); 4139 defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus"); 4140 defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true); 4141 defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true); 4142 defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true); 4143 defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true); 4144 defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true); 4145 defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true); 4146 defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true); 4147 defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true); 4148 defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true); 4149 defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true); 4150 defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true); 4151 defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true); 4152 defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true); 4153 defineSymbol(math, ams, bin, "\u229b", "\\circledast", true); 4154 defineSymbol(math, ams, bin, "\u22c5", "\\centerdot"); 4155 defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true); 4156 defineSymbol(math, ams, bin, "\u22d2", "\\doublecap"); 4157 defineSymbol(math, ams, bin, "\u22d3", "\\doublecup"); 4158 defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows 4159 // Note: unicode-math maps \u21e2 to their own function \rightdasharrow. 4160 // We'll map it to AMS function \dashrightarrow. It produces the same atom. 4161 4162 defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. 4163 4164 defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true); 4165 defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true); 4166 defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true); 4167 defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true); 4168 defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true); 4169 defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true); 4170 defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true); 4171 defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true); 4172 defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. 4173 4174 defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true); 4175 defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true); 4176 defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true); 4177 defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true); 4178 defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true); 4179 defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font 4180 4181 defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font 4182 4183 defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true); 4184 defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true); 4185 defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true); 4186 defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true); 4187 defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true); 4188 defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true); 4189 defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true); 4190 defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. 4191 4192 defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true); 4193 defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true); 4194 defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true); 4195 defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true); 4196 defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true); 4197 defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true); 4198 defineSymbol(math, ams, rel, "\u21dd", "\\leadsto"); 4199 defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true); 4200 defineSymbol(math, ams, rel, "\u21be", "\\restriction"); 4201 defineSymbol(math, main, textord, "\u2018", "`"); 4202 defineSymbol(math, main, textord, "$", "\\$"); 4203 defineSymbol(text$1, main, textord, "$", "\\$"); 4204 defineSymbol(text$1, main, textord, "$", "\\textdollar"); 4205 defineSymbol(math, main, textord, "%", "\\%"); 4206 defineSymbol(text$1, main, textord, "%", "\\%"); 4207 defineSymbol(math, main, textord, "_", "\\_"); 4208 defineSymbol(text$1, main, textord, "_", "\\_"); 4209 defineSymbol(text$1, main, textord, "_", "\\textunderscore"); 4210 defineSymbol(math, main, textord, "\u2220", "\\angle", true); 4211 defineSymbol(math, main, textord, "\u221e", "\\infty", true); 4212 defineSymbol(math, main, textord, "\u2032", "\\prime"); 4213 defineSymbol(math, main, textord, "\u25b3", "\\triangle"); 4214 defineSymbol(math, main, textord, "\u0393", "\\Gamma", true); 4215 defineSymbol(math, main, textord, "\u0394", "\\Delta", true); 4216 defineSymbol(math, main, textord, "\u0398", "\\Theta", true); 4217 defineSymbol(math, main, textord, "\u039b", "\\Lambda", true); 4218 defineSymbol(math, main, textord, "\u039e", "\\Xi", true); 4219 defineSymbol(math, main, textord, "\u03a0", "\\Pi", true); 4220 defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true); 4221 defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true); 4222 defineSymbol(math, main, textord, "\u03a6", "\\Phi", true); 4223 defineSymbol(math, main, textord, "\u03a8", "\\Psi", true); 4224 defineSymbol(math, main, textord, "\u03a9", "\\Omega", true); 4225 defineSymbol(math, main, textord, "A", "\u0391"); 4226 defineSymbol(math, main, textord, "B", "\u0392"); 4227 defineSymbol(math, main, textord, "E", "\u0395"); 4228 defineSymbol(math, main, textord, "Z", "\u0396"); 4229 defineSymbol(math, main, textord, "H", "\u0397"); 4230 defineSymbol(math, main, textord, "I", "\u0399"); 4231 defineSymbol(math, main, textord, "K", "\u039A"); 4232 defineSymbol(math, main, textord, "M", "\u039C"); 4233 defineSymbol(math, main, textord, "N", "\u039D"); 4234 defineSymbol(math, main, textord, "O", "\u039F"); 4235 defineSymbol(math, main, textord, "P", "\u03A1"); 4236 defineSymbol(math, main, textord, "T", "\u03A4"); 4237 defineSymbol(math, main, textord, "X", "\u03A7"); 4238 defineSymbol(math, main, textord, "\u00ac", "\\neg", true); 4239 defineSymbol(math, main, textord, "\u00ac", "\\lnot"); 4240 defineSymbol(math, main, textord, "\u22a4", "\\top"); 4241 defineSymbol(math, main, textord, "\u22a5", "\\bot"); 4242 defineSymbol(math, main, textord, "\u2205", "\\emptyset"); 4243 defineSymbol(math, ams, textord, "\u2205", "\\varnothing"); 4244 defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true); 4245 defineSymbol(math, main, mathord, "\u03b2", "\\beta", true); 4246 defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true); 4247 defineSymbol(math, main, mathord, "\u03b4", "\\delta", true); 4248 defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true); 4249 defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true); 4250 defineSymbol(math, main, mathord, "\u03b7", "\\eta", true); 4251 defineSymbol(math, main, mathord, "\u03b8", "\\theta", true); 4252 defineSymbol(math, main, mathord, "\u03b9", "\\iota", true); 4253 defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true); 4254 defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true); 4255 defineSymbol(math, main, mathord, "\u03bc", "\\mu", true); 4256 defineSymbol(math, main, mathord, "\u03bd", "\\nu", true); 4257 defineSymbol(math, main, mathord, "\u03be", "\\xi", true); 4258 defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true); 4259 defineSymbol(math, main, mathord, "\u03c0", "\\pi", true); 4260 defineSymbol(math, main, mathord, "\u03c1", "\\rho", true); 4261 defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true); 4262 defineSymbol(math, main, mathord, "\u03c4", "\\tau", true); 4263 defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true); 4264 defineSymbol(math, main, mathord, "\u03d5", "\\phi", true); 4265 defineSymbol(math, main, mathord, "\u03c7", "\\chi", true); 4266 defineSymbol(math, main, mathord, "\u03c8", "\\psi", true); 4267 defineSymbol(math, main, mathord, "\u03c9", "\\omega", true); 4268 defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true); 4269 defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true); 4270 defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true); 4271 defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true); 4272 defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true); 4273 defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true); 4274 defineSymbol(math, main, bin, "\u2217", "*"); 4275 defineSymbol(math, main, bin, "+", "+"); 4276 defineSymbol(math, main, bin, "\u2212", "-"); 4277 defineSymbol(math, main, bin, "\u22c5", "\\cdot", true); 4278 defineSymbol(math, main, bin, "\u2218", "\\circ"); 4279 defineSymbol(math, main, bin, "\u00f7", "\\div", true); 4280 defineSymbol(math, main, bin, "\u00b1", "\\pm", true); 4281 defineSymbol(math, main, bin, "\u00d7", "\\times", true); 4282 defineSymbol(math, main, bin, "\u2229", "\\cap", true); 4283 defineSymbol(math, main, bin, "\u222a", "\\cup", true); 4284 defineSymbol(math, main, bin, "\u2216", "\\setminus"); 4285 defineSymbol(math, main, bin, "\u2227", "\\land"); 4286 defineSymbol(math, main, bin, "\u2228", "\\lor"); 4287 defineSymbol(math, main, bin, "\u2227", "\\wedge", true); 4288 defineSymbol(math, main, bin, "\u2228", "\\vee", true); 4289 defineSymbol(math, main, textord, "\u221a", "\\surd"); 4290 defineSymbol(math, main, open, "\u27e8", "\\langle", true); 4291 defineSymbol(math, main, open, "\u2223", "\\lvert"); 4292 defineSymbol(math, main, open, "\u2225", "\\lVert"); 4293 defineSymbol(math, main, close, "?", "?"); 4294 defineSymbol(math, main, close, "!", "!"); 4295 defineSymbol(math, main, close, "\u27e9", "\\rangle", true); 4296 defineSymbol(math, main, close, "\u2223", "\\rvert"); 4297 defineSymbol(math, main, close, "\u2225", "\\rVert"); 4298 defineSymbol(math, main, rel, "=", "="); 4299 defineSymbol(math, main, rel, ":", ":"); 4300 defineSymbol(math, main, rel, "\u2248", "\\approx", true); 4301 defineSymbol(math, main, rel, "\u2245", "\\cong", true); 4302 defineSymbol(math, main, rel, "\u2265", "\\ge"); 4303 defineSymbol(math, main, rel, "\u2265", "\\geq", true); 4304 defineSymbol(math, main, rel, "\u2190", "\\gets"); 4305 defineSymbol(math, main, rel, ">", "\\gt", true); 4306 defineSymbol(math, main, rel, "\u2208", "\\in", true); 4307 defineSymbol(math, main, rel, "\ue020", "\\@not"); 4308 defineSymbol(math, main, rel, "\u2282", "\\subset", true); 4309 defineSymbol(math, main, rel, "\u2283", "\\supset", true); 4310 defineSymbol(math, main, rel, "\u2286", "\\subseteq", true); 4311 defineSymbol(math, main, rel, "\u2287", "\\supseteq", true); 4312 defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true); 4313 defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true); 4314 defineSymbol(math, main, rel, "\u22a8", "\\models"); 4315 defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true); 4316 defineSymbol(math, main, rel, "\u2264", "\\le"); 4317 defineSymbol(math, main, rel, "\u2264", "\\leq", true); 4318 defineSymbol(math, main, rel, "<", "\\lt", true); 4319 defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true); 4320 defineSymbol(math, main, rel, "\u2192", "\\to"); 4321 defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true); 4322 defineSymbol(math, ams, rel, "\u2270", "\\nleq", true); 4323 defineSymbol(math, main, spacing, "\u00a0", "\\ "); 4324 defineSymbol(math, main, spacing, "\u00a0", "~"); 4325 defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% 4326 4327 defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace"); 4328 defineSymbol(text$1, main, spacing, "\u00a0", "\\ "); 4329 defineSymbol(text$1, main, spacing, "\u00a0", " "); 4330 defineSymbol(text$1, main, spacing, "\u00a0", "~"); 4331 defineSymbol(text$1, main, spacing, "\u00a0", "\\space"); 4332 defineSymbol(text$1, main, spacing, "\u00a0", "\\nobreakspace"); 4333 defineSymbol(math, main, spacing, null, "\\nobreak"); 4334 defineSymbol(math, main, spacing, null, "\\allowbreak"); 4335 defineSymbol(math, main, punct, ",", ","); 4336 defineSymbol(math, main, punct, ";", ";"); 4337 defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true); 4338 defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true); 4339 defineSymbol(math, main, bin, "\u2299", "\\odot", true); 4340 defineSymbol(math, main, bin, "\u2295", "\\oplus", true); 4341 defineSymbol(math, main, bin, "\u2297", "\\otimes", true); 4342 defineSymbol(math, main, textord, "\u2202", "\\partial", true); 4343 defineSymbol(math, main, bin, "\u2298", "\\oslash", true); 4344 defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true); 4345 defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true); 4346 defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup"); 4347 defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown"); 4348 defineSymbol(math, main, bin, "\u2020", "\\dagger"); 4349 defineSymbol(math, main, bin, "\u22c4", "\\diamond"); 4350 defineSymbol(math, main, bin, "\u22c6", "\\star"); 4351 defineSymbol(math, main, bin, "\u25c3", "\\triangleleft"); 4352 defineSymbol(math, main, bin, "\u25b9", "\\triangleright"); 4353 defineSymbol(math, main, open, "{", "\\{"); 4354 defineSymbol(text$1, main, textord, "{", "\\{"); 4355 defineSymbol(text$1, main, textord, "{", "\\textbraceleft"); 4356 defineSymbol(math, main, close, "}", "\\}"); 4357 defineSymbol(text$1, main, textord, "}", "\\}"); 4358 defineSymbol(text$1, main, textord, "}", "\\textbraceright"); 4359 defineSymbol(math, main, open, "{", "\\lbrace"); 4360 defineSymbol(math, main, close, "}", "\\rbrace"); 4361 defineSymbol(math, main, open, "[", "\\lbrack", true); 4362 defineSymbol(text$1, main, textord, "[", "\\lbrack", true); 4363 defineSymbol(math, main, close, "]", "\\rbrack", true); 4364 defineSymbol(text$1, main, textord, "]", "\\rbrack", true); 4365 defineSymbol(math, main, open, "(", "\\lparen", true); 4366 defineSymbol(math, main, close, ")", "\\rparen", true); 4367 defineSymbol(text$1, main, textord, "<", "\\textless", true); // in T1 fontenc 4368 4369 defineSymbol(text$1, main, textord, ">", "\\textgreater", true); // in T1 fontenc 4370 4371 defineSymbol(math, main, open, "\u230a", "\\lfloor", true); 4372 defineSymbol(math, main, close, "\u230b", "\\rfloor", true); 4373 defineSymbol(math, main, open, "\u2308", "\\lceil", true); 4374 defineSymbol(math, main, close, "\u2309", "\\rceil", true); 4375 defineSymbol(math, main, textord, "\\", "\\backslash"); 4376 defineSymbol(math, main, textord, "\u2223", "|"); 4377 defineSymbol(math, main, textord, "\u2223", "\\vert"); 4378 defineSymbol(text$1, main, textord, "|", "\\textbar", true); // in T1 fontenc 4379 4380 defineSymbol(math, main, textord, "\u2225", "\\|"); 4381 defineSymbol(math, main, textord, "\u2225", "\\Vert"); 4382 defineSymbol(text$1, main, textord, "\u2225", "\\textbardbl"); 4383 defineSymbol(text$1, main, textord, "~", "\\textasciitilde"); 4384 defineSymbol(text$1, main, textord, "\\", "\\textbackslash"); 4385 defineSymbol(text$1, main, textord, "^", "\\textasciicircum"); 4386 defineSymbol(math, main, rel, "\u2191", "\\uparrow", true); 4387 defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true); 4388 defineSymbol(math, main, rel, "\u2193", "\\downarrow", true); 4389 defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true); 4390 defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true); 4391 defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true); 4392 defineSymbol(math, main, op, "\u2210", "\\coprod"); 4393 defineSymbol(math, main, op, "\u22c1", "\\bigvee"); 4394 defineSymbol(math, main, op, "\u22c0", "\\bigwedge"); 4395 defineSymbol(math, main, op, "\u2a04", "\\biguplus"); 4396 defineSymbol(math, main, op, "\u22c2", "\\bigcap"); 4397 defineSymbol(math, main, op, "\u22c3", "\\bigcup"); 4398 defineSymbol(math, main, op, "\u222b", "\\int"); 4399 defineSymbol(math, main, op, "\u222b", "\\intop"); 4400 defineSymbol(math, main, op, "\u222c", "\\iint"); 4401 defineSymbol(math, main, op, "\u222d", "\\iiint"); 4402 defineSymbol(math, main, op, "\u220f", "\\prod"); 4403 defineSymbol(math, main, op, "\u2211", "\\sum"); 4404 defineSymbol(math, main, op, "\u2a02", "\\bigotimes"); 4405 defineSymbol(math, main, op, "\u2a01", "\\bigoplus"); 4406 defineSymbol(math, main, op, "\u2a00", "\\bigodot"); 4407 defineSymbol(math, main, op, "\u222e", "\\oint"); 4408 defineSymbol(math, main, op, "\u222f", "\\oiint"); 4409 defineSymbol(math, main, op, "\u2230", "\\oiiint"); 4410 defineSymbol(math, main, op, "\u2a06", "\\bigsqcup"); 4411 defineSymbol(math, main, op, "\u222b", "\\smallint"); 4412 defineSymbol(text$1, main, inner, "\u2026", "\\textellipsis"); 4413 defineSymbol(math, main, inner, "\u2026", "\\mathellipsis"); 4414 defineSymbol(text$1, main, inner, "\u2026", "\\ldots", true); 4415 defineSymbol(math, main, inner, "\u2026", "\\ldots", true); 4416 defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true); 4417 defineSymbol(math, main, inner, "\u22f1", "\\ddots", true); 4418 defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); // \vdots is a macro 4419 4420 defineSymbol(math, main, accent, "\u02ca", "\\acute"); 4421 defineSymbol(math, main, accent, "\u02cb", "\\grave"); 4422 defineSymbol(math, main, accent, "\u00a8", "\\ddot"); 4423 defineSymbol(math, main, accent, "\u007e", "\\tilde"); 4424 defineSymbol(math, main, accent, "\u02c9", "\\bar"); 4425 defineSymbol(math, main, accent, "\u02d8", "\\breve"); 4426 defineSymbol(math, main, accent, "\u02c7", "\\check"); 4427 defineSymbol(math, main, accent, "\u005e", "\\hat"); 4428 defineSymbol(math, main, accent, "\u20d7", "\\vec"); 4429 defineSymbol(math, main, accent, "\u02d9", "\\dot"); 4430 defineSymbol(math, main, accent, "\u02da", "\\mathring"); // \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA 4431 4432 defineSymbol(math, main, mathord, "\ue131", "\\@imath"); 4433 defineSymbol(math, main, mathord, "\ue237", "\\@jmath"); 4434 defineSymbol(math, main, textord, "\u0131", "\u0131"); 4435 defineSymbol(math, main, textord, "\u0237", "\u0237"); 4436 defineSymbol(text$1, main, textord, "\u0131", "\\i", true); 4437 defineSymbol(text$1, main, textord, "\u0237", "\\j", true); 4438 defineSymbol(text$1, main, textord, "\u00df", "\\ss", true); 4439 defineSymbol(text$1, main, textord, "\u00e6", "\\ae", true); 4440 defineSymbol(text$1, main, textord, "\u0153", "\\oe", true); 4441 defineSymbol(text$1, main, textord, "\u00f8", "\\o", true); 4442 defineSymbol(text$1, main, textord, "\u00c6", "\\AE", true); 4443 defineSymbol(text$1, main, textord, "\u0152", "\\OE", true); 4444 defineSymbol(text$1, main, textord, "\u00d8", "\\O", true); 4445 defineSymbol(text$1, main, accent, "\u02ca", "\\'"); // acute 4446 4447 defineSymbol(text$1, main, accent, "\u02cb", "\\`"); // grave 4448 4449 defineSymbol(text$1, main, accent, "\u02c6", "\\^"); // circumflex 4450 4451 defineSymbol(text$1, main, accent, "\u02dc", "\\~"); // tilde 4452 4453 defineSymbol(text$1, main, accent, "\u02c9", "\\="); // macron 4454 4455 defineSymbol(text$1, main, accent, "\u02d8", "\\u"); // breve 4456 4457 defineSymbol(text$1, main, accent, "\u02d9", "\\."); // dot above 4458 4459 defineSymbol(text$1, main, accent, "\u02da", "\\r"); // ring above 4460 4461 defineSymbol(text$1, main, accent, "\u02c7", "\\v"); // caron 4462 4463 defineSymbol(text$1, main, accent, "\u00a8", '\\"'); // diaresis 4464 4465 defineSymbol(text$1, main, accent, "\u02dd", "\\H"); // double acute 4466 4467 defineSymbol(text$1, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph 4468 // These ligatures are detected and created in Parser.js's `formLigatures`. 4469 4470 var ligatures = { 4471 "--": true, 4472 "---": true, 4473 "``": true, 4474 "''": true 4475 }; 4476 defineSymbol(text$1, main, textord, "\u2013", "--", true); 4477 defineSymbol(text$1, main, textord, "\u2013", "\\textendash"); 4478 defineSymbol(text$1, main, textord, "\u2014", "---", true); 4479 defineSymbol(text$1, main, textord, "\u2014", "\\textemdash"); 4480 defineSymbol(text$1, main, textord, "\u2018", "`", true); 4481 defineSymbol(text$1, main, textord, "\u2018", "\\textquoteleft"); 4482 defineSymbol(text$1, main, textord, "\u2019", "'", true); 4483 defineSymbol(text$1, main, textord, "\u2019", "\\textquoteright"); 4484 defineSymbol(text$1, main, textord, "\u201c", "``", true); 4485 defineSymbol(text$1, main, textord, "\u201c", "\\textquotedblleft"); 4486 defineSymbol(text$1, main, textord, "\u201d", "''", true); 4487 defineSymbol(text$1, main, textord, "\u201d", "\\textquotedblright"); // \degree from gensymb package 4488 4489 defineSymbol(math, main, textord, "\u00b0", "\\degree", true); 4490 defineSymbol(text$1, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package 4491 4492 defineSymbol(text$1, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math 4493 // mode, but among our fonts, only Main-Regular defines this character "163". 4494 4495 defineSymbol(math, main, textord, "\u00a3", "\\pounds"); 4496 defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true); 4497 defineSymbol(text$1, main, textord, "\u00a3", "\\pounds"); 4498 defineSymbol(text$1, main, textord, "\u00a3", "\\textsterling", true); 4499 defineSymbol(math, ams, textord, "\u2720", "\\maltese"); 4500 defineSymbol(text$1, ams, textord, "\u2720", "\\maltese"); // There are lots of symbols which are the same, so we add them in afterwards. 4501 // All of these are textords in math mode 4502 4503 var mathTextSymbols = "0123456789/@.\""; 4504 4505 for (var i = 0; i < mathTextSymbols.length; i++) { 4506 var ch = mathTextSymbols.charAt(i); 4507 defineSymbol(math, main, textord, ch, ch); 4508 } // All of these are textords in text mode 4509 4510 4511 var textSymbols = "0123456789!@*()-=+\";:?/.,"; 4512 4513 for (var _i = 0; _i < textSymbols.length; _i++) { 4514 var _ch = textSymbols.charAt(_i); 4515 4516 defineSymbol(text$1, main, textord, _ch, _ch); 4517 } // All of these are textords in text mode, and mathords in math mode 4518 4519 4520 var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 4521 4522 for (var _i2 = 0; _i2 < letters.length; _i2++) { 4523 var _ch2 = letters.charAt(_i2); 4524 4525 defineSymbol(math, main, mathord, _ch2, _ch2); 4526 defineSymbol(text$1, main, textord, _ch2, _ch2); 4527 } // Blackboard bold and script letters in Unicode range 4528 4529 4530 defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold 4531 4532 defineSymbol(text$1, ams, textord, "C", "\u2102"); 4533 defineSymbol(math, ams, textord, "H", "\u210D"); 4534 defineSymbol(text$1, ams, textord, "H", "\u210D"); 4535 defineSymbol(math, ams, textord, "N", "\u2115"); 4536 defineSymbol(text$1, ams, textord, "N", "\u2115"); 4537 defineSymbol(math, ams, textord, "P", "\u2119"); 4538 defineSymbol(text$1, ams, textord, "P", "\u2119"); 4539 defineSymbol(math, ams, textord, "Q", "\u211A"); 4540 defineSymbol(text$1, ams, textord, "Q", "\u211A"); 4541 defineSymbol(math, ams, textord, "R", "\u211D"); 4542 defineSymbol(text$1, ams, textord, "R", "\u211D"); 4543 defineSymbol(math, ams, textord, "Z", "\u2124"); 4544 defineSymbol(text$1, ams, textord, "Z", "\u2124"); 4545 defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant 4546 4547 defineSymbol(text$1, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters. 4548 // We support some letters in the Unicode range U+1D400 to U+1D7FF, 4549 // Mathematical Alphanumeric Symbols. 4550 // Some editors do not deal well with wide characters. So don't write the 4551 // string into this file. Instead, create the string from the surrogate pair. 4552 4553 var wideChar = ""; 4554 4555 for (var _i3 = 0; _i3 < letters.length; _i3++) { 4556 var _ch3 = letters.charAt(_i3); // The hex numbers in the next line are a surrogate pair. 4557 // 0xD835 is the high surrogate for all letters in the range we support. 4558 // 0xDC00 is the low surrogate for bold A. 4559 4560 4561 wideChar = String.fromCharCode(0xD835, 0xDC00 + _i3); // A-Z a-z bold 4562 4563 defineSymbol(math, main, mathord, _ch3, wideChar); 4564 defineSymbol(text$1, main, textord, _ch3, wideChar); 4565 wideChar = String.fromCharCode(0xD835, 0xDC34 + _i3); // A-Z a-z italic 4566 4567 defineSymbol(math, main, mathord, _ch3, wideChar); 4568 defineSymbol(text$1, main, textord, _ch3, wideChar); 4569 wideChar = String.fromCharCode(0xD835, 0xDC68 + _i3); // A-Z a-z bold italic 4570 4571 defineSymbol(math, main, mathord, _ch3, wideChar); 4572 defineSymbol(text$1, main, textord, _ch3, wideChar); 4573 wideChar = String.fromCharCode(0xD835, 0xDD04 + _i3); // A-Z a-z Fractur 4574 4575 defineSymbol(math, main, mathord, _ch3, wideChar); 4576 defineSymbol(text$1, main, textord, _ch3, wideChar); 4577 wideChar = String.fromCharCode(0xD835, 0xDDA0 + _i3); // A-Z a-z sans-serif 4578 4579 defineSymbol(math, main, mathord, _ch3, wideChar); 4580 defineSymbol(text$1, main, textord, _ch3, wideChar); 4581 wideChar = String.fromCharCode(0xD835, 0xDDD4 + _i3); // A-Z a-z sans bold 4582 4583 defineSymbol(math, main, mathord, _ch3, wideChar); 4584 defineSymbol(text$1, main, textord, _ch3, wideChar); 4585 wideChar = String.fromCharCode(0xD835, 0xDE08 + _i3); // A-Z a-z sans italic 4586 4587 defineSymbol(math, main, mathord, _ch3, wideChar); 4588 defineSymbol(text$1, main, textord, _ch3, wideChar); 4589 wideChar = String.fromCharCode(0xD835, 0xDE70 + _i3); // A-Z a-z monospace 4590 4591 defineSymbol(math, main, mathord, _ch3, wideChar); 4592 defineSymbol(text$1, main, textord, _ch3, wideChar); 4593 4594 if (_i3 < 26) { 4595 // KaTeX fonts have only capital letters for blackboard bold and script. 4596 // See exception for k below. 4597 wideChar = String.fromCharCode(0xD835, 0xDD38 + _i3); // A-Z double struck 4598 4599 defineSymbol(math, main, mathord, _ch3, wideChar); 4600 defineSymbol(text$1, main, textord, _ch3, wideChar); 4601 wideChar = String.fromCharCode(0xD835, 0xDC9C + _i3); // A-Z script 4602 4603 defineSymbol(math, main, mathord, _ch3, wideChar); 4604 defineSymbol(text$1, main, textord, _ch3, wideChar); 4605 } // TODO: Add bold script when it is supported by a KaTeX font. 4606 4607 } // "k" is the only double struck lower case letter in the KaTeX fonts. 4608 4609 4610 wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck 4611 4612 defineSymbol(math, main, mathord, "k", wideChar); 4613 defineSymbol(text$1, main, textord, "k", wideChar); // Next, some wide character numerals 4614 4615 for (var _i4 = 0; _i4 < 10; _i4++) { 4616 var _ch4 = _i4.toString(); 4617 4618 wideChar = String.fromCharCode(0xD835, 0xDFCE + _i4); // 0-9 bold 4619 4620 defineSymbol(math, main, mathord, _ch4, wideChar); 4621 defineSymbol(text$1, main, textord, _ch4, wideChar); 4622 wideChar = String.fromCharCode(0xD835, 0xDFE2 + _i4); // 0-9 sans serif 4623 4624 defineSymbol(math, main, mathord, _ch4, wideChar); 4625 defineSymbol(text$1, main, textord, _ch4, wideChar); 4626 wideChar = String.fromCharCode(0xD835, 0xDFEC + _i4); // 0-9 bold sans 4627 4628 defineSymbol(math, main, mathord, _ch4, wideChar); 4629 defineSymbol(text$1, main, textord, _ch4, wideChar); 4630 wideChar = String.fromCharCode(0xD835, 0xDFF6 + _i4); // 0-9 monospace 4631 4632 defineSymbol(math, main, mathord, _ch4, wideChar); 4633 defineSymbol(text$1, main, textord, _ch4, wideChar); 4634 } // We add these Latin-1 letters as symbols for backwards-compatibility, 4635 // but they are not actually in the font, nor are they supported by the 4636 // Unicode accent mechanism, so they fall back to Times font and look ugly. 4637 // TODO(edemaine): Fix this. 4638 4639 4640 var extraLatin = "\u00c7\u00d0\u00de\u00e7\u00fe"; 4641 4642 for (var _i5 = 0; _i5 < extraLatin.length; _i5++) { 4643 var _ch5 = extraLatin.charAt(_i5); 4644 4645 defineSymbol(math, main, mathord, _ch5, _ch5); 4646 defineSymbol(text$1, main, textord, _ch5, _ch5); 4647 } 4648 4649 /** 4650 * This file provides support for Unicode range U+1D400 to U+1D7FF, 4651 * Mathematical Alphanumeric Symbols. 4652 * 4653 * Function wideCharacterFont takes a wide character as input and returns 4654 * the font information necessary to render it properly. 4655 */ 4656 /** 4657 * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf 4658 * That document sorts characters into groups by font type, say bold or italic. 4659 * 4660 * In the arrays below, each subarray consists three elements: 4661 * * The CSS class of that group when in math mode. 4662 * * The CSS class of that group when in text mode. 4663 * * The font name, so that KaTeX can get font metrics. 4664 */ 4665 4666 var wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright 4667 ["mathbf", "textbf", "Main-Bold"], // a-z bold upright 4668 ["mathnormal", "textit", "Math-Italic"], // A-Z italic 4669 ["mathnormal", "textit", "Math-Italic"], // a-z italic 4670 ["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic 4671 ["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic 4672 // Map fancy A-Z letters to script, not calligraphic. 4673 // This aligns with unicode-math and math fonts (except Cambria Math). 4674 ["mathscr", "textscr", "Script-Regular"], // A-Z script 4675 ["", "", ""], // a-z script. No font 4676 ["", "", ""], // A-Z bold script. No font 4677 ["", "", ""], // a-z bold script. No font 4678 ["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur 4679 ["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur 4680 ["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck 4681 ["mathbb", "textbb", "AMS-Regular"], // k double-struck 4682 ["", "", ""], // A-Z bold Fraktur No font metrics 4683 ["", "", ""], // a-z bold Fraktur. No font. 4684 ["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif 4685 ["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif 4686 ["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif 4687 ["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif 4688 ["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif 4689 ["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif 4690 ["", "", ""], // A-Z bold italic sans. No font 4691 ["", "", ""], // a-z bold italic sans. No font 4692 ["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace 4693 ["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace 4694 ]; 4695 var wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold 4696 ["", "", ""], // 0-9 double-struck. No KaTeX font. 4697 ["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif 4698 ["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif 4699 ["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace 4700 ]; 4701 var wideCharacterFont = function wideCharacterFont(wideChar, mode) { 4702 // IE doesn't support codePointAt(). So work with the surrogate pair. 4703 var H = wideChar.charCodeAt(0); // high surrogate 4704 4705 var L = wideChar.charCodeAt(1); // low surrogate 4706 4707 var codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000; 4708 var j = mode === "math" ? 0 : 1; // column index for CSS class. 4709 4710 if (0x1D400 <= codePoint && codePoint < 0x1D6A4) { 4711 // wideLatinLetterData contains exactly 26 chars on each row. 4712 // So we can calculate the relevant row. No traverse necessary. 4713 var i = Math.floor((codePoint - 0x1D400) / 26); 4714 return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]]; 4715 } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) { 4716 // Numerals, ten per row. 4717 var _i = Math.floor((codePoint - 0x1D7CE) / 10); 4718 4719 return [wideNumeralData[_i][2], wideNumeralData[_i][j]]; 4720 } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) { 4721 // dotless i or j 4722 return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]]; 4723 } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) { 4724 // Greek letters. Not supported, yet. 4725 return ["", ""]; 4726 } else { 4727 // We don't support any wide characters outside 1D400–1D7FF. 4728 throw new ParseError("Unsupported character: " + wideChar); 4729 } 4730 }; 4731 4732 /** 4733 * This file contains information about the options that the Parser carries 4734 * around with it while parsing. Data is held in an `Options` object, and when 4735 * recursing, a new `Options` object can be created with the `.with*` and 4736 * `.reset` functions. 4737 */ 4738 var sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize]. 4739 // The size mappings are taken from TeX with \normalsize=10pt. 4740 [1, 1, 1], // size1: [5, 5, 5] \tiny 4741 [2, 1, 1], // size2: [6, 5, 5] 4742 [3, 1, 1], // size3: [7, 5, 5] \scriptsize 4743 [4, 2, 1], // size4: [8, 6, 5] \footnotesize 4744 [5, 2, 1], // size5: [9, 6, 5] \small 4745 [6, 3, 1], // size6: [10, 7, 5] \normalsize 4746 [7, 4, 2], // size7: [12, 8, 6] \large 4747 [8, 6, 3], // size8: [14.4, 10, 7] \Large 4748 [9, 7, 6], // size9: [17.28, 12, 10] \LARGE 4749 [10, 8, 7], // size10: [20.74, 14.4, 12] \huge 4750 [11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE 4751 ]; 4752 var sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if 4753 // you change size indexes, change that function. 4754 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488]; 4755 4756 var sizeAtStyle = function sizeAtStyle(size, style) { 4757 return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1]; 4758 }; // In these types, "" (empty string) means "no change". 4759 4760 4761 /** 4762 * This is the main options class. It contains the current style, size, color, 4763 * and font. 4764 * 4765 * Options objects should not be modified. To create a new Options with 4766 * different properties, call a `.having*` method. 4767 */ 4768 class Options { 4769 // A font family applies to a group of fonts (i.e. SansSerif), while a font 4770 // represents a specific font (i.e. SansSerif Bold). 4771 // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm 4772 4773 /** 4774 * The base size index. 4775 */ 4776 constructor(data) { 4777 this.style = void 0; 4778 this.color = void 0; 4779 this.size = void 0; 4780 this.textSize = void 0; 4781 this.phantom = void 0; 4782 this.font = void 0; 4783 this.fontFamily = void 0; 4784 this.fontWeight = void 0; 4785 this.fontShape = void 0; 4786 this.sizeMultiplier = void 0; 4787 this.maxSize = void 0; 4788 this.minRuleThickness = void 0; 4789 this._fontMetrics = void 0; 4790 this.style = data.style; 4791 this.color = data.color; 4792 this.size = data.size || Options.BASESIZE; 4793 this.textSize = data.textSize || this.size; 4794 this.phantom = !!data.phantom; 4795 this.font = data.font || ""; 4796 this.fontFamily = data.fontFamily || ""; 4797 this.fontWeight = data.fontWeight || ''; 4798 this.fontShape = data.fontShape || ''; 4799 this.sizeMultiplier = sizeMultipliers[this.size - 1]; 4800 this.maxSize = data.maxSize; 4801 this.minRuleThickness = data.minRuleThickness; 4802 this._fontMetrics = undefined; 4803 } 4804 /** 4805 * Returns a new options object with the same properties as "this". Properties 4806 * from "extension" will be copied to the new options object. 4807 */ 4808 4809 4810 extend(extension) { 4811 var data = { 4812 style: this.style, 4813 size: this.size, 4814 textSize: this.textSize, 4815 color: this.color, 4816 phantom: this.phantom, 4817 font: this.font, 4818 fontFamily: this.fontFamily, 4819 fontWeight: this.fontWeight, 4820 fontShape: this.fontShape, 4821 maxSize: this.maxSize, 4822 minRuleThickness: this.minRuleThickness 4823 }; 4824 4825 for (var key in extension) { 4826 if (extension.hasOwnProperty(key)) { 4827 data[key] = extension[key]; 4828 } 4829 } 4830 4831 return new Options(data); 4832 } 4833 /** 4834 * Return an options object with the given style. If `this.style === style`, 4835 * returns `this`. 4836 */ 4837 4838 4839 havingStyle(style) { 4840 if (this.style === style) { 4841 return this; 4842 } else { 4843 return this.extend({ 4844 style: style, 4845 size: sizeAtStyle(this.textSize, style) 4846 }); 4847 } 4848 } 4849 /** 4850 * Return an options object with a cramped version of the current style. If 4851 * the current style is cramped, returns `this`. 4852 */ 4853 4854 4855 havingCrampedStyle() { 4856 return this.havingStyle(this.style.cramp()); 4857 } 4858 /** 4859 * Return an options object with the given size and in at least `\textstyle`. 4860 * Returns `this` if appropriate. 4861 */ 4862 4863 4864 havingSize(size) { 4865 if (this.size === size && this.textSize === size) { 4866 return this; 4867 } else { 4868 return this.extend({ 4869 style: this.style.text(), 4870 size: size, 4871 textSize: size, 4872 sizeMultiplier: sizeMultipliers[size - 1] 4873 }); 4874 } 4875 } 4876 /** 4877 * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted, 4878 * changes to at least `\textstyle`. 4879 */ 4880 4881 4882 havingBaseStyle(style) { 4883 style = style || this.style.text(); 4884 var wantSize = sizeAtStyle(Options.BASESIZE, style); 4885 4886 if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) { 4887 return this; 4888 } else { 4889 return this.extend({ 4890 style: style, 4891 size: wantSize 4892 }); 4893 } 4894 } 4895 /** 4896 * Remove the effect of sizing changes such as \Huge. 4897 * Keep the effect of the current style, such as \scriptstyle. 4898 */ 4899 4900 4901 havingBaseSizing() { 4902 var size; 4903 4904 switch (this.style.id) { 4905 case 4: 4906 case 5: 4907 size = 3; // normalsize in scriptstyle 4908 4909 break; 4910 4911 case 6: 4912 case 7: 4913 size = 1; // normalsize in scriptscriptstyle 4914 4915 break; 4916 4917 default: 4918 size = 6; 4919 // normalsize in textstyle or displaystyle 4920 } 4921 4922 return this.extend({ 4923 style: this.style.text(), 4924 size: size 4925 }); 4926 } 4927 /** 4928 * Create a new options object with the given color. 4929 */ 4930 4931 4932 withColor(color) { 4933 return this.extend({ 4934 color: color 4935 }); 4936 } 4937 /** 4938 * Create a new options object with "phantom" set to true. 4939 */ 4940 4941 4942 withPhantom() { 4943 return this.extend({ 4944 phantom: true 4945 }); 4946 } 4947 /** 4948 * Creates a new options object with the given math font or old text font. 4949 * @type {[type]} 4950 */ 4951 4952 4953 withFont(font) { 4954 return this.extend({ 4955 font 4956 }); 4957 } 4958 /** 4959 * Create a new options objects with the given fontFamily. 4960 */ 4961 4962 4963 withTextFontFamily(fontFamily) { 4964 return this.extend({ 4965 fontFamily, 4966 font: "" 4967 }); 4968 } 4969 /** 4970 * Creates a new options object with the given font weight 4971 */ 4972 4973 4974 withTextFontWeight(fontWeight) { 4975 return this.extend({ 4976 fontWeight, 4977 font: "" 4978 }); 4979 } 4980 /** 4981 * Creates a new options object with the given font weight 4982 */ 4983 4984 4985 withTextFontShape(fontShape) { 4986 return this.extend({ 4987 fontShape, 4988 font: "" 4989 }); 4990 } 4991 /** 4992 * Return the CSS sizing classes required to switch from enclosing options 4993 * `oldOptions` to `this`. Returns an array of classes. 4994 */ 4995 4996 4997 sizingClasses(oldOptions) { 4998 if (oldOptions.size !== this.size) { 4999 return ["sizing", "reset-size" + oldOptions.size, "size" + this.size]; 5000 } else { 5001 return []; 5002 } 5003 } 5004 /** 5005 * Return the CSS sizing classes required to switch to the base size. Like 5006 * `this.havingSize(BASESIZE).sizingClasses(this)`. 5007 */ 5008 5009 5010 baseSizingClasses() { 5011 if (this.size !== Options.BASESIZE) { 5012 return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE]; 5013 } else { 5014 return []; 5015 } 5016 } 5017 /** 5018 * Return the font metrics for this size. 5019 */ 5020 5021 5022 fontMetrics() { 5023 if (!this._fontMetrics) { 5024 this._fontMetrics = getGlobalMetrics(this.size); 5025 } 5026 5027 return this._fontMetrics; 5028 } 5029 /** 5030 * Gets the CSS color of the current options object 5031 */ 5032 5033 5034 getColor() { 5035 if (this.phantom) { 5036 return "transparent"; 5037 } else { 5038 return this.color; 5039 } 5040 } 5041 5042 } 5043 5044 Options.BASESIZE = 6; 5045 5046 /** 5047 * This file does conversion between units. In particular, it provides 5048 * calculateSize to convert other units into ems. 5049 */ 5050 // Thus, multiplying a length by this number converts the length from units 5051 // into pts. Dividing the result by ptPerEm gives the number of ems 5052 // *assuming* a font size of ptPerEm (normal size, normal style). 5053 5054 var ptPerUnit = { 5055 // https://en.wikibooks.org/wiki/LaTeX/Lengths and 5056 // https://tex.stackexchange.com/a/8263 5057 "pt": 1, 5058 // TeX point 5059 "mm": 7227 / 2540, 5060 // millimeter 5061 "cm": 7227 / 254, 5062 // centimeter 5063 "in": 72.27, 5064 // inch 5065 "bp": 803 / 800, 5066 // big (PostScript) points 5067 "pc": 12, 5068 // pica 5069 "dd": 1238 / 1157, 5070 // didot 5071 "cc": 14856 / 1157, 5072 // cicero (12 didot) 5073 "nd": 685 / 642, 5074 // new didot 5075 "nc": 1370 / 107, 5076 // new cicero (12 new didot) 5077 "sp": 1 / 65536, 5078 // scaled point (TeX's internal smallest unit) 5079 // https://tex.stackexchange.com/a/41371 5080 "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX 5081 5082 }; // Dictionary of relative units, for fast validity testing. 5083 5084 var relativeUnit = { 5085 "ex": true, 5086 "em": true, 5087 "mu": true 5088 }; 5089 5090 /** 5091 * Determine whether the specified unit (either a string defining the unit 5092 * or a "size" parse node containing a unit field) is valid. 5093 */ 5094 var validUnit = function validUnit(unit) { 5095 if (typeof unit !== "string") { 5096 unit = unit.unit; 5097 } 5098 5099 return unit in ptPerUnit || unit in relativeUnit || unit === "ex"; 5100 }; 5101 /* 5102 * Convert a "size" parse node (with numeric "number" and string "unit" fields, 5103 * as parsed by functions.js argType "size") into a CSS em value for the 5104 * current style/scale. `options` gives the current options. 5105 */ 5106 5107 var calculateSize = function calculateSize(sizeValue, options) { 5108 var scale; 5109 5110 if (sizeValue.unit in ptPerUnit) { 5111 // Absolute units 5112 scale = ptPerUnit[sizeValue.unit] // Convert unit to pt 5113 / options.fontMetrics().ptPerEm // Convert pt to CSS em 5114 / options.sizeMultiplier; // Unscale to make absolute units 5115 } else if (sizeValue.unit === "mu") { 5116 // `mu` units scale with scriptstyle/scriptscriptstyle. 5117 scale = options.fontMetrics().cssEmPerMu; 5118 } else { 5119 // Other relative units always refer to the *textstyle* font 5120 // in the current size. 5121 var unitOptions; 5122 5123 if (options.style.isTight()) { 5124 // isTight() means current style is script/scriptscript. 5125 unitOptions = options.havingStyle(options.style.text()); 5126 } else { 5127 unitOptions = options; 5128 } // TODO: In TeX these units are relative to the quad of the current 5129 // *text* font, e.g. cmr10. KaTeX instead uses values from the 5130 // comparably-sized *Computer Modern symbol* font. At 10pt, these 5131 // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641; 5132 // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$. 5133 // TeX \showlists shows a kern of 1.13889 * fontsize; 5134 // KaTeX shows a kern of 1.171 * fontsize. 5135 5136 5137 if (sizeValue.unit === "ex") { 5138 scale = unitOptions.fontMetrics().xHeight; 5139 } else if (sizeValue.unit === "em") { 5140 scale = unitOptions.fontMetrics().quad; 5141 } else { 5142 throw new ParseError("Invalid unit: '" + sizeValue.unit + "'"); 5143 } 5144 5145 if (unitOptions !== options) { 5146 scale *= unitOptions.sizeMultiplier / options.sizeMultiplier; 5147 } 5148 } 5149 5150 return Math.min(sizeValue.number * scale, options.maxSize); 5151 }; 5152 5153 /* eslint no-console:0 */ 5154 5155 /** 5156 * Looks up the given symbol in fontMetrics, after applying any symbol 5157 * replacements defined in symbol.js 5158 */ 5159 var lookupSymbol = function lookupSymbol(value, // TODO(#963): Use a union type for this. 5160 fontName, mode) { 5161 // Replace the value with its replaced value from symbol.js 5162 if (symbols[mode][value] && symbols[mode][value].replace) { 5163 value = symbols[mode][value].replace; 5164 } 5165 5166 return { 5167 value: value, 5168 metrics: getCharacterMetrics(value, fontName, mode) 5169 }; 5170 }; 5171 /** 5172 * Makes a symbolNode after translation via the list of symbols in symbols.js. 5173 * Correctly pulls out metrics for the character, and optionally takes a list of 5174 * classes to be attached to the node. 5175 * 5176 * TODO: make argument order closer to makeSpan 5177 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which 5178 * should if present come first in `classes`. 5179 * TODO(#953): Make `options` mandatory and always pass it in. 5180 */ 5181 5182 5183 var makeSymbol = function makeSymbol(value, fontName, mode, options, classes) { 5184 var lookup = lookupSymbol(value, fontName, mode); 5185 var metrics = lookup.metrics; 5186 value = lookup.value; 5187 var symbolNode; 5188 5189 if (metrics) { 5190 var italic = metrics.italic; 5191 5192 if (mode === "text" || options && options.font === "mathit") { 5193 italic = 0; 5194 } 5195 5196 symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes); 5197 } else { 5198 // TODO(emily): Figure out a good way to only print this in development 5199 typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'")); 5200 symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes); 5201 } 5202 5203 if (options) { 5204 symbolNode.maxFontSize = options.sizeMultiplier; 5205 5206 if (options.style.isTight()) { 5207 symbolNode.classes.push("mtight"); 5208 } 5209 5210 var color = options.getColor(); 5211 5212 if (color) { 5213 symbolNode.style.color = color; 5214 } 5215 } 5216 5217 return symbolNode; 5218 }; 5219 /** 5220 * Makes a symbol in Main-Regular or AMS-Regular. 5221 * Used for rel, bin, open, close, inner, and punct. 5222 */ 5223 5224 5225 var mathsym = function mathsym(value, mode, options, classes) { 5226 if (classes === void 0) { 5227 classes = []; 5228 } 5229 5230 // Decide what font to render the symbol in by its entry in the symbols 5231 // table. 5232 // Have a special case for when the value = \ because the \ is used as a 5233 // textord in unsupported command errors but cannot be parsed as a regular 5234 // text ordinal and is therefore not present as a symbol in the symbols 5235 // table for text, as well as a special case for boldsymbol because it 5236 // can be used for bold + and - 5237 if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) { 5238 return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"])); 5239 } else if (value === "\\" || symbols[mode][value].font === "main") { 5240 return makeSymbol(value, "Main-Regular", mode, options, classes); 5241 } else { 5242 return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"])); 5243 } 5244 }; 5245 /** 5246 * Determines which of the two font names (Main-Bold and Math-BoldItalic) and 5247 * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol", 5248 * depending on the symbol. Use this function instead of fontMap for font 5249 * "boldsymbol". 5250 */ 5251 5252 5253 var boldsymbol = function boldsymbol(value, mode, options, classes, type) { 5254 if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) { 5255 return { 5256 fontName: "Math-BoldItalic", 5257 fontClass: "boldsymbol" 5258 }; 5259 } else { 5260 // Some glyphs do not exist in Math-BoldItalic so we need to use 5261 // Main-Bold instead. 5262 return { 5263 fontName: "Main-Bold", 5264 fontClass: "mathbf" 5265 }; 5266 } 5267 }; 5268 /** 5269 * Makes either a mathord or textord in the correct font and color. 5270 */ 5271 5272 5273 var makeOrd = function makeOrd(group, options, type) { 5274 var mode = group.mode; 5275 var text = group.text; 5276 var classes = ["mord"]; // Math mode or Old font (i.e. \rm) 5277 5278 var isFont = mode === "math" || mode === "text" && options.font; 5279 var fontOrFamily = isFont ? options.font : options.fontFamily; 5280 5281 if (text.charCodeAt(0) === 0xD835) { 5282 // surrogate pairs get special treatment 5283 var [wideFontName, wideFontClass] = wideCharacterFont(text, mode); 5284 return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass)); 5285 } else if (fontOrFamily) { 5286 var fontName; 5287 var fontClasses; 5288 5289 if (fontOrFamily === "boldsymbol") { 5290 var fontData = boldsymbol(text, mode, options, classes, type); 5291 fontName = fontData.fontName; 5292 fontClasses = [fontData.fontClass]; 5293 } else if (isFont) { 5294 fontName = fontMap[fontOrFamily].fontName; 5295 fontClasses = [fontOrFamily]; 5296 } else { 5297 fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape); 5298 fontClasses = [fontOrFamily, options.fontWeight, options.fontShape]; 5299 } 5300 5301 if (lookupSymbol(text, fontName, mode).metrics) { 5302 return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses)); 5303 } else if (ligatures.hasOwnProperty(text) && fontName.substr(0, 10) === "Typewriter") { 5304 // Deconstruct ligatures in monospace fonts (\texttt, \tt). 5305 var parts = []; 5306 5307 for (var i = 0; i < text.length; i++) { 5308 parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses))); 5309 } 5310 5311 return makeFragment(parts); 5312 } 5313 } // Makes a symbol in the default font for mathords and textords. 5314 5315 5316 if (type === "mathord") { 5317 return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"])); 5318 } else if (type === "textord") { 5319 var font = symbols[mode][text] && symbols[mode][text].font; 5320 5321 if (font === "ams") { 5322 var _fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape); 5323 5324 return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape)); 5325 } else if (font === "main" || !font) { 5326 var _fontName2 = retrieveTextFontName("textrm", options.fontWeight, options.fontShape); 5327 5328 return makeSymbol(text, _fontName2, mode, options, classes.concat(options.fontWeight, options.fontShape)); 5329 } else { 5330 // fonts added by plugins 5331 var _fontName3 = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class 5332 5333 5334 return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, options.fontWeight, options.fontShape)); 5335 } 5336 } else { 5337 throw new Error("unexpected type: " + type + " in makeOrd"); 5338 } 5339 }; 5340 /** 5341 * Returns true if subsequent symbolNodes have the same classes, skew, maxFont, 5342 * and styles. 5343 */ 5344 5345 5346 var canCombine = (prev, next) => { 5347 if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) { 5348 return false; 5349 } // If prev and next both are just "mbin"s or "mord"s we don't combine them 5350 // so that the proper spacing can be preserved. 5351 5352 5353 if (prev.classes.length === 1) { 5354 var cls = prev.classes[0]; 5355 5356 if (cls === "mbin" || cls === "mord") { 5357 return false; 5358 } 5359 } 5360 5361 for (var style in prev.style) { 5362 if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) { 5363 return false; 5364 } 5365 } 5366 5367 for (var _style in next.style) { 5368 if (next.style.hasOwnProperty(_style) && prev.style[_style] !== next.style[_style]) { 5369 return false; 5370 } 5371 } 5372 5373 return true; 5374 }; 5375 /** 5376 * Combine consecutive domTree.symbolNodes into a single symbolNode. 5377 * Note: this function mutates the argument. 5378 */ 5379 5380 5381 var tryCombineChars = chars => { 5382 for (var i = 0; i < chars.length - 1; i++) { 5383 var prev = chars[i]; 5384 var next = chars[i + 1]; 5385 5386 if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) { 5387 prev.text += next.text; 5388 prev.height = Math.max(prev.height, next.height); 5389 prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use 5390 // it to add padding to the right of the span created from 5391 // the combined characters. 5392 5393 prev.italic = next.italic; 5394 chars.splice(i + 1, 1); 5395 i--; 5396 } 5397 } 5398 5399 return chars; 5400 }; 5401 /** 5402 * Calculate the height, depth, and maxFontSize of an element based on its 5403 * children. 5404 */ 5405 5406 5407 var sizeElementFromChildren = function sizeElementFromChildren(elem) { 5408 var height = 0; 5409 var depth = 0; 5410 var maxFontSize = 0; 5411 5412 for (var i = 0; i < elem.children.length; i++) { 5413 var child = elem.children[i]; 5414 5415 if (child.height > height) { 5416 height = child.height; 5417 } 5418 5419 if (child.depth > depth) { 5420 depth = child.depth; 5421 } 5422 5423 if (child.maxFontSize > maxFontSize) { 5424 maxFontSize = child.maxFontSize; 5425 } 5426 } 5427 5428 elem.height = height; 5429 elem.depth = depth; 5430 elem.maxFontSize = maxFontSize; 5431 }; 5432 /** 5433 * Makes a span with the given list of classes, list of children, and options. 5434 * 5435 * TODO(#953): Ensure that `options` is always provided (currently some call 5436 * sites don't pass it) and make the type below mandatory. 5437 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which 5438 * should if present come first in `classes`. 5439 */ 5440 5441 5442 var makeSpan = function makeSpan(classes, children, options, style) { 5443 var span = new Span(classes, children, options, style); 5444 sizeElementFromChildren(span); 5445 return span; 5446 }; // SVG one is simpler -- doesn't require height, depth, max-font setting. 5447 // This is also a separate method for typesafety. 5448 5449 5450 var makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style); 5451 5452 var makeLineSpan = function makeLineSpan(className, options, thickness) { 5453 var line = makeSpan([className], [], options); 5454 line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness); 5455 line.style.borderBottomWidth = line.height + "em"; 5456 line.maxFontSize = 1.0; 5457 return line; 5458 }; 5459 /** 5460 * Makes an anchor with the given href, list of classes, list of children, 5461 * and options. 5462 */ 5463 5464 5465 var makeAnchor = function makeAnchor(href, classes, children, options) { 5466 var anchor = new Anchor(href, classes, children, options); 5467 sizeElementFromChildren(anchor); 5468 return anchor; 5469 }; 5470 /** 5471 * Makes a document fragment with the given list of children. 5472 */ 5473 5474 5475 var makeFragment = function makeFragment(children) { 5476 var fragment = new DocumentFragment(children); 5477 sizeElementFromChildren(fragment); 5478 return fragment; 5479 }; 5480 /** 5481 * Wraps group in a span if it's a document fragment, allowing to apply classes 5482 * and styles 5483 */ 5484 5485 5486 var wrapFragment = function wrapFragment(group, options) { 5487 if (group instanceof DocumentFragment) { 5488 return makeSpan([], [group], options); 5489 } 5490 5491 return group; 5492 }; // These are exact object types to catch typos in the names of the optional fields. 5493 5494 5495 // Computes the updated `children` list and the overall depth. 5496 // 5497 // This helper function for makeVList makes it easier to enforce type safety by 5498 // allowing early exits (returns) in the logic. 5499 var getVListChildrenAndDepth = function getVListChildrenAndDepth(params) { 5500 if (params.positionType === "individualShift") { 5501 var oldChildren = params.children; 5502 var children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be 5503 // shifted to the correct specified shift 5504 5505 var _depth = -oldChildren[0].shift - oldChildren[0].elem.depth; 5506 5507 var currPos = _depth; 5508 5509 for (var i = 1; i < oldChildren.length; i++) { 5510 var diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth; 5511 var size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth); 5512 currPos = currPos + diff; 5513 children.push({ 5514 type: "kern", 5515 size 5516 }); 5517 children.push(oldChildren[i]); 5518 } 5519 5520 return { 5521 children, 5522 depth: _depth 5523 }; 5524 } 5525 5526 var depth; 5527 5528 if (params.positionType === "top") { 5529 // We always start at the bottom, so calculate the bottom by adding up 5530 // all the sizes 5531 var bottom = params.positionData; 5532 5533 for (var _i = 0; _i < params.children.length; _i++) { 5534 var child = params.children[_i]; 5535 bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth; 5536 } 5537 5538 depth = bottom; 5539 } else if (params.positionType === "bottom") { 5540 depth = -params.positionData; 5541 } else { 5542 var firstChild = params.children[0]; 5543 5544 if (firstChild.type !== "elem") { 5545 throw new Error('First child must have type "elem".'); 5546 } 5547 5548 if (params.positionType === "shift") { 5549 depth = -firstChild.elem.depth - params.positionData; 5550 } else if (params.positionType === "firstBaseline") { 5551 depth = -firstChild.elem.depth; 5552 } else { 5553 throw new Error("Invalid positionType " + params.positionType + "."); 5554 } 5555 } 5556 5557 return { 5558 children: params.children, 5559 depth 5560 }; 5561 }; 5562 /** 5563 * Makes a vertical list by stacking elements and kerns on top of each other. 5564 * Allows for many different ways of specifying the positioning method. 5565 * 5566 * See VListParam documentation above. 5567 */ 5568 5569 5570 var makeVList = function makeVList(params, options) { 5571 var { 5572 children, 5573 depth 5574 } = getVListChildrenAndDepth(params); // Create a strut that is taller than any list item. The strut is added to 5575 // each item, where it will determine the item's baseline. Since it has 5576 // `overflow:hidden`, the strut's top edge will sit on the item's line box's 5577 // top edge and the strut's bottom edge will sit on the item's baseline, 5578 // with no additional line-height spacing. This allows the item baseline to 5579 // be positioned precisely without worrying about font ascent and 5580 // line-height. 5581 5582 var pstrutSize = 0; 5583 5584 for (var i = 0; i < children.length; i++) { 5585 var child = children[i]; 5586 5587 if (child.type === "elem") { 5588 var elem = child.elem; 5589 pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height); 5590 } 5591 } 5592 5593 pstrutSize += 2; 5594 var pstrut = makeSpan(["pstrut"], []); 5595 pstrut.style.height = pstrutSize + "em"; // Create a new list of actual children at the correct offsets 5596 5597 var realChildren = []; 5598 var minPos = depth; 5599 var maxPos = depth; 5600 var currPos = depth; 5601 5602 for (var _i2 = 0; _i2 < children.length; _i2++) { 5603 var _child = children[_i2]; 5604 5605 if (_child.type === "kern") { 5606 currPos += _child.size; 5607 } else { 5608 var _elem = _child.elem; 5609 var classes = _child.wrapperClasses || []; 5610 var style = _child.wrapperStyle || {}; 5611 var childWrap = makeSpan(classes, [pstrut, _elem], undefined, style); 5612 childWrap.style.top = -pstrutSize - currPos - _elem.depth + "em"; 5613 5614 if (_child.marginLeft) { 5615 childWrap.style.marginLeft = _child.marginLeft; 5616 } 5617 5618 if (_child.marginRight) { 5619 childWrap.style.marginRight = _child.marginRight; 5620 } 5621 5622 realChildren.push(childWrap); 5623 currPos += _elem.height + _elem.depth; 5624 } 5625 5626 minPos = Math.min(minPos, currPos); 5627 maxPos = Math.max(maxPos, currPos); 5628 } // The vlist contents go in a table-cell with `vertical-align:bottom`. 5629 // This cell's bottom edge will determine the containing table's baseline 5630 // without overly expanding the containing line-box. 5631 5632 5633 var vlist = makeSpan(["vlist"], realChildren); 5634 vlist.style.height = maxPos + "em"; // A second row is used if necessary to represent the vlist's depth. 5635 5636 var rows; 5637 5638 if (minPos < 0) { 5639 // We will define depth in an empty span with display: table-cell. 5640 // It should render with the height that we define. But Chrome, in 5641 // contenteditable mode only, treats that span as if it contains some 5642 // text content. And that min-height over-rides our desired height. 5643 // So we put another empty span inside the depth strut span. 5644 var emptySpan = makeSpan([], []); 5645 var depthStrut = makeSpan(["vlist"], [emptySpan]); 5646 depthStrut.style.height = -minPos + "em"; // Safari wants the first row to have inline content; otherwise it 5647 // puts the bottom of the *second* row on the baseline. 5648 5649 var topStrut = makeSpan(["vlist-s"], [new SymbolNode("\u200b")]); 5650 rows = [makeSpan(["vlist-r"], [vlist, topStrut]), makeSpan(["vlist-r"], [depthStrut])]; 5651 } else { 5652 rows = [makeSpan(["vlist-r"], [vlist])]; 5653 } 5654 5655 var vtable = makeSpan(["vlist-t"], rows); 5656 5657 if (rows.length === 2) { 5658 vtable.classes.push("vlist-t2"); 5659 } 5660 5661 vtable.height = maxPos; 5662 vtable.depth = -minPos; 5663 return vtable; 5664 }; // Glue is a concept from TeX which is a flexible space between elements in 5665 // either a vertical or horizontal list. In KaTeX, at least for now, it's 5666 // static space between elements in a horizontal layout. 5667 5668 5669 var makeGlue = (measurement, options) => { 5670 // Make an empty span for the space 5671 var rule = makeSpan(["mspace"], [], options); 5672 var size = calculateSize(measurement, options); 5673 rule.style.marginRight = size + "em"; 5674 return rule; 5675 }; // Takes font options, and returns the appropriate fontLookup name 5676 5677 5678 var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) { 5679 var baseFontName = ""; 5680 5681 switch (fontFamily) { 5682 case "amsrm": 5683 baseFontName = "AMS"; 5684 break; 5685 5686 case "textrm": 5687 baseFontName = "Main"; 5688 break; 5689 5690 case "textsf": 5691 baseFontName = "SansSerif"; 5692 break; 5693 5694 case "texttt": 5695 baseFontName = "Typewriter"; 5696 break; 5697 5698 default: 5699 baseFontName = fontFamily; 5700 // use fonts added by a plugin 5701 } 5702 5703 var fontStylesName; 5704 5705 if (fontWeight === "textbf" && fontShape === "textit") { 5706 fontStylesName = "BoldItalic"; 5707 } else if (fontWeight === "textbf") { 5708 fontStylesName = "Bold"; 5709 } else if (fontWeight === "textit") { 5710 fontStylesName = "Italic"; 5711 } else { 5712 fontStylesName = "Regular"; 5713 } 5714 5715 return baseFontName + "-" + fontStylesName; 5716 }; 5717 /** 5718 * Maps TeX font commands to objects containing: 5719 * - variant: string used for "mathvariant" attribute in buildMathML.js 5720 * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics 5721 */ 5722 // A map between tex font commands an MathML mathvariant attribute values 5723 5724 5725 var fontMap = { 5726 // styles 5727 "mathbf": { 5728 variant: "bold", 5729 fontName: "Main-Bold" 5730 }, 5731 "mathrm": { 5732 variant: "normal", 5733 fontName: "Main-Regular" 5734 }, 5735 "textit": { 5736 variant: "italic", 5737 fontName: "Main-Italic" 5738 }, 5739 "mathit": { 5740 variant: "italic", 5741 fontName: "Main-Italic" 5742 }, 5743 "mathnormal": { 5744 variant: "italic", 5745 fontName: "Math-Italic" 5746 }, 5747 // "boldsymbol" is missing because they require the use of multiple fonts: 5748 // Math-BoldItalic and Main-Bold. This is handled by a special case in 5749 // makeOrd which ends up calling boldsymbol. 5750 // families 5751 "mathbb": { 5752 variant: "double-struck", 5753 fontName: "AMS-Regular" 5754 }, 5755 "mathcal": { 5756 variant: "script", 5757 fontName: "Caligraphic-Regular" 5758 }, 5759 "mathfrak": { 5760 variant: "fraktur", 5761 fontName: "Fraktur-Regular" 5762 }, 5763 "mathscr": { 5764 variant: "script", 5765 fontName: "Script-Regular" 5766 }, 5767 "mathsf": { 5768 variant: "sans-serif", 5769 fontName: "SansSerif-Regular" 5770 }, 5771 "mathtt": { 5772 variant: "monospace", 5773 fontName: "Typewriter-Regular" 5774 } 5775 }; 5776 var svgData = { 5777 // path, width, height 5778 vec: ["vec", 0.471, 0.714], 5779 // values from the font glyph 5780 oiintSize1: ["oiintSize1", 0.957, 0.499], 5781 // oval to overlay the integrand 5782 oiintSize2: ["oiintSize2", 1.472, 0.659], 5783 oiiintSize1: ["oiiintSize1", 1.304, 0.499], 5784 oiiintSize2: ["oiiintSize2", 1.98, 0.659] 5785 }; 5786 5787 var staticSvg = function staticSvg(value, options) { 5788 // Create a span with inline SVG for the element. 5789 var [pathName, width, height] = svgData[value]; 5790 var path = new PathNode(pathName); 5791 var svgNode = new SvgNode([path], { 5792 "width": width + "em", 5793 "height": height + "em", 5794 // Override CSS rule `.katex svg { width: 100% }` 5795 "style": "width:" + width + "em", 5796 "viewBox": "0 0 " + 1000 * width + " " + 1000 * height, 5797 "preserveAspectRatio": "xMinYMin" 5798 }); 5799 var span = makeSvgSpan(["overlay"], [svgNode], options); 5800 span.height = height; 5801 span.style.height = height + "em"; 5802 span.style.width = width + "em"; 5803 return span; 5804 }; 5805 5806 var buildCommon = { 5807 fontMap, 5808 makeSymbol, 5809 mathsym, 5810 makeSpan, 5811 makeSvgSpan, 5812 makeLineSpan, 5813 makeAnchor, 5814 makeFragment, 5815 wrapFragment, 5816 makeVList, 5817 makeOrd, 5818 makeGlue, 5819 staticSvg, 5820 svgData, 5821 tryCombineChars 5822 }; 5823 5824 /** 5825 * Describes spaces between different classes of atoms. 5826 */ 5827 var thinspace = { 5828 number: 3, 5829 unit: "mu" 5830 }; 5831 var mediumspace = { 5832 number: 4, 5833 unit: "mu" 5834 }; 5835 var thickspace = { 5836 number: 5, 5837 unit: "mu" 5838 }; // Making the type below exact with all optional fields doesn't work due to 5839 // - https://github.com/facebook/flow/issues/4582 5840 // - https://github.com/facebook/flow/issues/5688 5841 // However, since *all* fields are optional, $Shape<> works as suggested in 5688 5842 // above. 5843 5844 // Spacing relationships for display and text styles 5845 var spacings = { 5846 mord: { 5847 mop: thinspace, 5848 mbin: mediumspace, 5849 mrel: thickspace, 5850 minner: thinspace 5851 }, 5852 mop: { 5853 mord: thinspace, 5854 mop: thinspace, 5855 mrel: thickspace, 5856 minner: thinspace 5857 }, 5858 mbin: { 5859 mord: mediumspace, 5860 mop: mediumspace, 5861 mopen: mediumspace, 5862 minner: mediumspace 5863 }, 5864 mrel: { 5865 mord: thickspace, 5866 mop: thickspace, 5867 mopen: thickspace, 5868 minner: thickspace 5869 }, 5870 mopen: {}, 5871 mclose: { 5872 mop: thinspace, 5873 mbin: mediumspace, 5874 mrel: thickspace, 5875 minner: thinspace 5876 }, 5877 mpunct: { 5878 mord: thinspace, 5879 mop: thinspace, 5880 mrel: thickspace, 5881 mopen: thinspace, 5882 mclose: thinspace, 5883 mpunct: thinspace, 5884 minner: thinspace 5885 }, 5886 minner: { 5887 mord: thinspace, 5888 mop: thinspace, 5889 mbin: mediumspace, 5890 mrel: thickspace, 5891 mopen: thinspace, 5892 mpunct: thinspace, 5893 minner: thinspace 5894 } 5895 }; // Spacing relationships for script and scriptscript styles 5896 5897 var tightSpacings = { 5898 mord: { 5899 mop: thinspace 5900 }, 5901 mop: { 5902 mord: thinspace, 5903 mop: thinspace 5904 }, 5905 mbin: {}, 5906 mrel: {}, 5907 mopen: {}, 5908 mclose: { 5909 mop: thinspace 5910 }, 5911 mpunct: {}, 5912 minner: { 5913 mop: thinspace 5914 } 5915 }; 5916 5917 /** Context provided to function handlers for error messages. */ 5918 // Note: reverse the order of the return type union will cause a flow error. 5919 // See https://github.com/facebook/flow/issues/3663. 5920 // More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types) 5921 // whose presence impacts super/subscripting. In this case, ParseNode<"supsub"> 5922 // delegates its HTML building to the HtmlBuilder corresponding to these nodes. 5923 5924 /** 5925 * Final function spec for use at parse time. 5926 * This is almost identical to `FunctionPropSpec`, except it 5927 * 1. includes the function handler, and 5928 * 2. requires all arguments except argTypes. 5929 * It is generated by `defineFunction()` below. 5930 */ 5931 5932 /** 5933 * All registered functions. 5934 * `functions.js` just exports this same dictionary again and makes it public. 5935 * `Parser.js` requires this dictionary. 5936 */ 5937 var _functions = {}; 5938 /** 5939 * All HTML builders. Should be only used in the `define*` and the `build*ML` 5940 * functions. 5941 */ 5942 5943 var _htmlGroupBuilders = {}; 5944 /** 5945 * All MathML builders. Should be only used in the `define*` and the `build*ML` 5946 * functions. 5947 */ 5948 5949 var _mathmlGroupBuilders = {}; 5950 function defineFunction(_ref) { 5951 var { 5952 type, 5953 names, 5954 props, 5955 handler, 5956 htmlBuilder, 5957 mathmlBuilder 5958 } = _ref; 5959 // Set default values of functions 5960 var data = { 5961 type, 5962 numArgs: props.numArgs, 5963 argTypes: props.argTypes, 5964 allowedInArgument: !!props.allowedInArgument, 5965 allowedInText: !!props.allowedInText, 5966 allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, 5967 numOptionalArgs: props.numOptionalArgs || 0, 5968 infix: !!props.infix, 5969 primitive: !!props.primitive, 5970 handler: handler 5971 }; 5972 5973 for (var i = 0; i < names.length; ++i) { 5974 _functions[names[i]] = data; 5975 } 5976 5977 if (type) { 5978 if (htmlBuilder) { 5979 _htmlGroupBuilders[type] = htmlBuilder; 5980 } 5981 5982 if (mathmlBuilder) { 5983 _mathmlGroupBuilders[type] = mathmlBuilder; 5984 } 5985 } 5986 } 5987 /** 5988 * Use this to register only the HTML and MathML builders for a function (e.g. 5989 * if the function's ParseNode is generated in Parser.js rather than via a 5990 * stand-alone handler provided to `defineFunction`). 5991 */ 5992 5993 function defineFunctionBuilders(_ref2) { 5994 var { 5995 type, 5996 htmlBuilder, 5997 mathmlBuilder 5998 } = _ref2; 5999 defineFunction({ 6000 type, 6001 names: [], 6002 props: { 6003 numArgs: 0 6004 }, 6005 6006 handler() { 6007 throw new Error('Should never be called.'); 6008 }, 6009 6010 htmlBuilder, 6011 mathmlBuilder 6012 }); 6013 } 6014 var normalizeArgument = function normalizeArgument(arg) { 6015 return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg; 6016 }; // Since the corresponding buildHTML/buildMathML function expects a 6017 // list of elements, we normalize for different kinds of arguments 6018 6019 var ordargument = function ordargument(arg) { 6020 return arg.type === "ordgroup" ? arg.body : [arg]; 6021 }; 6022 6023 /** 6024 * This file does the main work of building a domTree structure from a parse 6025 * tree. The entry point is the `buildHTML` function, which takes a parse tree. 6026 * Then, the buildExpression, buildGroup, and various groupBuilders functions 6027 * are called, to produce a final HTML tree. 6028 */ 6029 var makeSpan$1 = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`) 6030 // depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6, 6031 // and the text before Rule 19. 6032 6033 var binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"]; 6034 var binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"]; 6035 var styleMap = { 6036 "display": Style$1.DISPLAY, 6037 "text": Style$1.TEXT, 6038 "script": Style$1.SCRIPT, 6039 "scriptscript": Style$1.SCRIPTSCRIPT 6040 }; 6041 var DomEnum = { 6042 mord: "mord", 6043 mop: "mop", 6044 mbin: "mbin", 6045 mrel: "mrel", 6046 mopen: "mopen", 6047 mclose: "mclose", 6048 mpunct: "mpunct", 6049 minner: "minner" 6050 }; 6051 6052 /** 6053 * Take a list of nodes, build them in order, and return a list of the built 6054 * nodes. documentFragments are flattened into their contents, so the 6055 * returned list contains no fragments. `isRealGroup` is true if `expression` 6056 * is a real group (no atoms will be added on either side), as opposed to 6057 * a partial group (e.g. one created by \color). `surrounding` is an array 6058 * consisting type of nodes that will be added to the left and right. 6059 */ 6060 var buildExpression = function buildExpression(expression, options, isRealGroup, surrounding) { 6061 if (surrounding === void 0) { 6062 surrounding = [null, null]; 6063 } 6064 6065 // Parse expressions into `groups`. 6066 var groups = []; 6067 6068 for (var i = 0; i < expression.length; i++) { 6069 var output = buildGroup(expression[i], options); 6070 6071 if (output instanceof DocumentFragment) { 6072 var children = output.children; 6073 groups.push(...children); 6074 } else { 6075 groups.push(output); 6076 } 6077 } // Combine consecutive domTree.symbolNodes into a single symbolNode. 6078 6079 6080 buildCommon.tryCombineChars(groups); // If `expression` is a partial group, let the parent handle spacings 6081 // to avoid processing groups multiple times. 6082 6083 if (!isRealGroup) { 6084 return groups; 6085 } 6086 6087 var glueOptions = options; 6088 6089 if (expression.length === 1) { 6090 var node = expression[0]; 6091 6092 if (node.type === "sizing") { 6093 glueOptions = options.havingSize(node.size); 6094 } else if (node.type === "styling") { 6095 glueOptions = options.havingStyle(styleMap[node.style]); 6096 } 6097 } // Dummy spans for determining spacings between surrounding atoms. 6098 // If `expression` has no atoms on the left or right, class "leftmost" 6099 // or "rightmost", respectively, is used to indicate it. 6100 6101 6102 var dummyPrev = makeSpan$1([surrounding[0] || "leftmost"], [], options); 6103 var dummyNext = makeSpan$1([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element 6104 // of its `classes` array. A later cleanup should ensure this, for 6105 // instance by changing the signature of `makeSpan`. 6106 // Before determining what spaces to insert, perform bin cancellation. 6107 // Binary operators change to ordinary symbols in some contexts. 6108 6109 var isRoot = isRealGroup === "root"; 6110 traverseNonSpaceNodes(groups, (node, prev) => { 6111 var prevType = prev.classes[0]; 6112 var type = node.classes[0]; 6113 6114 if (prevType === "mbin" && utils.contains(binRightCanceller, type)) { 6115 prev.classes[0] = "mord"; 6116 } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) { 6117 node.classes[0] = "mord"; 6118 } 6119 }, { 6120 node: dummyPrev 6121 }, dummyNext, isRoot); 6122 traverseNonSpaceNodes(groups, (node, prev) => { 6123 var prevType = getTypeOfDomTree(prev); 6124 var type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style. 6125 6126 var space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null; 6127 6128 if (space) { 6129 // Insert glue (spacing) after the `prev`. 6130 return buildCommon.makeGlue(space, glueOptions); 6131 } 6132 }, { 6133 node: dummyPrev 6134 }, dummyNext, isRoot); 6135 return groups; 6136 }; // Depth-first traverse non-space `nodes`, calling `callback` with the current and 6137 // previous node as arguments, optionally returning a node to insert after the 6138 // previous node. `prev` is an object with the previous node and `insertAfter` 6139 // function to insert after it. `next` is a node that will be added to the right. 6140 // Used for bin cancellation and inserting spacings. 6141 6142 var traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, prev, next, isRoot) { 6143 if (next) { 6144 // temporarily append the right node, if exists 6145 nodes.push(next); 6146 } 6147 6148 var i = 0; 6149 6150 for (; i < nodes.length; i++) { 6151 var node = nodes[i]; 6152 var partialGroup = checkPartialGroup(node); 6153 6154 if (partialGroup) { 6155 // Recursive DFS 6156 // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array 6157 traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot); 6158 continue; 6159 } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit 6160 // spacing should go between atoms of different classes 6161 6162 6163 var nonspace = !node.hasClass("mspace"); 6164 6165 if (nonspace) { 6166 var result = callback(node, prev.node); 6167 6168 if (result) { 6169 if (prev.insertAfter) { 6170 prev.insertAfter(result); 6171 } else { 6172 // insert at front 6173 nodes.unshift(result); 6174 i++; 6175 } 6176 } 6177 } 6178 6179 if (nonspace) { 6180 prev.node = node; 6181 } else if (isRoot && node.hasClass("newline")) { 6182 prev.node = makeSpan$1(["leftmost"]); // treat like beginning of line 6183 } 6184 6185 prev.insertAfter = (index => n => { 6186 nodes.splice(index + 1, 0, n); 6187 i++; 6188 })(i); 6189 } 6190 6191 if (next) { 6192 nodes.pop(); 6193 } 6194 }; // Check if given node is a partial group, i.e., does not affect spacing around. 6195 6196 6197 var checkPartialGroup = function checkPartialGroup(node) { 6198 if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) { 6199 return node; 6200 } 6201 6202 return null; 6203 }; // Return the outermost node of a domTree. 6204 6205 6206 var getOutermostNode = function getOutermostNode(node, side) { 6207 var partialGroup = checkPartialGroup(node); 6208 6209 if (partialGroup) { 6210 var children = partialGroup.children; 6211 6212 if (children.length) { 6213 if (side === "right") { 6214 return getOutermostNode(children[children.length - 1], "right"); 6215 } else if (side === "left") { 6216 return getOutermostNode(children[0], "left"); 6217 } 6218 } 6219 } 6220 6221 return node; 6222 }; // Return math atom class (mclass) of a domTree. 6223 // If `side` is given, it will get the type of the outermost node at given side. 6224 6225 6226 var getTypeOfDomTree = function getTypeOfDomTree(node, side) { 6227 if (!node) { 6228 return null; 6229 } 6230 6231 if (side) { 6232 node = getOutermostNode(node, side); 6233 } // This makes a lot of assumptions as to where the type of atom 6234 // appears. We should do a better job of enforcing this. 6235 6236 6237 return DomEnum[node.classes[0]] || null; 6238 }; 6239 var makeNullDelimiter = function makeNullDelimiter(options, classes) { 6240 var moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses()); 6241 return makeSpan$1(classes.concat(moreClasses)); 6242 }; 6243 /** 6244 * buildGroup is the function that takes a group and calls the correct groupType 6245 * function for it. It also handles the interaction of size and style changes 6246 * between parents and children. 6247 */ 6248 6249 var buildGroup = function buildGroup(group, options, baseOptions) { 6250 if (!group) { 6251 return makeSpan$1(); 6252 } 6253 6254 if (_htmlGroupBuilders[group.type]) { 6255 // Call the groupBuilders function 6256 // $FlowFixMe 6257 var groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account 6258 // for that size difference. 6259 6260 if (baseOptions && options.size !== baseOptions.size) { 6261 groupNode = makeSpan$1(options.sizingClasses(baseOptions), [groupNode], options); 6262 var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; 6263 groupNode.height *= multiplier; 6264 groupNode.depth *= multiplier; 6265 } 6266 6267 return groupNode; 6268 } else { 6269 throw new ParseError("Got group of unknown type: '" + group.type + "'"); 6270 } 6271 }; 6272 /** 6273 * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`) 6274 * into an unbreakable HTML node of class .base, with proper struts to 6275 * guarantee correct vertical extent. `buildHTML` calls this repeatedly to 6276 * make up the entire expression as a sequence of unbreakable units. 6277 */ 6278 6279 function buildHTMLUnbreakable(children, options) { 6280 // Compute height and depth of this chunk. 6281 var body = makeSpan$1(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at 6282 // the height of the expression, and the bottom of the HTML element 6283 // falls at the depth of the expression. 6284 6285 var strut = makeSpan$1(["strut"]); 6286 strut.style.height = body.height + body.depth + "em"; 6287 strut.style.verticalAlign = -body.depth + "em"; 6288 body.children.unshift(strut); 6289 return body; 6290 } 6291 /** 6292 * Take an entire parse tree, and build it into an appropriate set of HTML 6293 * nodes. 6294 */ 6295 6296 6297 function buildHTML(tree, options) { 6298 // Strip off outer tag wrapper for processing below. 6299 var tag = null; 6300 6301 if (tree.length === 1 && tree[0].type === "tag") { 6302 tag = tree[0].tag; 6303 tree = tree[0].body; 6304 } // Build the expression contained in the tree 6305 6306 6307 var expression = buildExpression(tree, options, "root"); 6308 var eqnNum; 6309 6310 if (expression.length === 2 && expression[1].hasClass("tag")) { 6311 // An environment with automatic equation numbers, e.g. {gather}. 6312 eqnNum = expression.pop(); 6313 } 6314 6315 var children = []; // Create one base node for each chunk between potential line breaks. 6316 // The TeXBook [p.173] says "A formula will be broken only after a 6317 // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary 6318 // operation symbol like $+$ or $-$ or $\times$, where the relation or 6319 // binary operation is on the ``outer level'' of the formula (i.e., not 6320 // enclosed in {...} and not part of an \over construction)." 6321 6322 var parts = []; 6323 6324 for (var i = 0; i < expression.length; i++) { 6325 parts.push(expression[i]); 6326 6327 if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) { 6328 // Put any post-operator glue on same line as operator. 6329 // Watch for \nobreak along the way, and stop at \newline. 6330 var nobreak = false; 6331 6332 while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) { 6333 i++; 6334 parts.push(expression[i]); 6335 6336 if (expression[i].hasClass("nobreak")) { 6337 nobreak = true; 6338 } 6339 } // Don't allow break if \nobreak among the post-operator glue. 6340 6341 6342 if (!nobreak) { 6343 children.push(buildHTMLUnbreakable(parts, options)); 6344 parts = []; 6345 } 6346 } else if (expression[i].hasClass("newline")) { 6347 // Write the line except the newline 6348 parts.pop(); 6349 6350 if (parts.length > 0) { 6351 children.push(buildHTMLUnbreakable(parts, options)); 6352 parts = []; 6353 } // Put the newline at the top level 6354 6355 6356 children.push(expression[i]); 6357 } 6358 } 6359 6360 if (parts.length > 0) { 6361 children.push(buildHTMLUnbreakable(parts, options)); 6362 } // Now, if there was a tag, build it too and append it as a final child. 6363 6364 6365 var tagChild; 6366 6367 if (tag) { 6368 tagChild = buildHTMLUnbreakable(buildExpression(tag, options, true)); 6369 tagChild.classes = ["tag"]; 6370 children.push(tagChild); 6371 } else if (eqnNum) { 6372 children.push(eqnNum); 6373 } 6374 6375 var htmlNode = makeSpan$1(["katex-html"], children); 6376 htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children 6377 // (the height of the enclosing htmlNode) for proper vertical alignment. 6378 6379 if (tagChild) { 6380 var strut = tagChild.children[0]; 6381 strut.style.height = htmlNode.height + htmlNode.depth + "em"; 6382 strut.style.verticalAlign = -htmlNode.depth + "em"; 6383 } 6384 6385 return htmlNode; 6386 } 6387 6388 /** 6389 * These objects store data about MathML nodes. This is the MathML equivalent 6390 * of the types in domTree.js. Since MathML handles its own rendering, and 6391 * since we're mainly using MathML to improve accessibility, we don't manage 6392 * any of the styling state that the plain DOM nodes do. 6393 * 6394 * The `toNode` and `toMarkup` functions work simlarly to how they do in 6395 * domTree.js, creating namespaced DOM nodes and HTML text markup respectively. 6396 */ 6397 function newDocumentFragment(children) { 6398 return new DocumentFragment(children); 6399 } 6400 /** 6401 * This node represents a general purpose MathML node of any type. The 6402 * constructor requires the type of node to create (for example, `"mo"` or 6403 * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags). 6404 */ 6405 6406 class MathNode { 6407 constructor(type, children, classes) { 6408 this.type = void 0; 6409 this.attributes = void 0; 6410 this.children = void 0; 6411 this.classes = void 0; 6412 this.type = type; 6413 this.attributes = {}; 6414 this.children = children || []; 6415 this.classes = classes || []; 6416 } 6417 /** 6418 * Sets an attribute on a MathML node. MathML depends on attributes to convey a 6419 * semantic content, so this is used heavily. 6420 */ 6421 6422 6423 setAttribute(name, value) { 6424 this.attributes[name] = value; 6425 } 6426 /** 6427 * Gets an attribute on a MathML node. 6428 */ 6429 6430 6431 getAttribute(name) { 6432 return this.attributes[name]; 6433 } 6434 /** 6435 * Converts the math node into a MathML-namespaced DOM element. 6436 */ 6437 6438 6439 toNode() { 6440 var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); 6441 6442 for (var attr in this.attributes) { 6443 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 6444 node.setAttribute(attr, this.attributes[attr]); 6445 } 6446 } 6447 6448 if (this.classes.length > 0) { 6449 node.className = createClass(this.classes); 6450 } 6451 6452 for (var i = 0; i < this.children.length; i++) { 6453 node.appendChild(this.children[i].toNode()); 6454 } 6455 6456 return node; 6457 } 6458 /** 6459 * Converts the math node into an HTML markup string. 6460 */ 6461 6462 6463 toMarkup() { 6464 var markup = "<" + this.type; // Add the attributes 6465 6466 for (var attr in this.attributes) { 6467 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 6468 markup += " " + attr + "=\""; 6469 markup += utils.escape(this.attributes[attr]); 6470 markup += "\""; 6471 } 6472 } 6473 6474 if (this.classes.length > 0) { 6475 markup += " class =\"" + utils.escape(createClass(this.classes)) + "\""; 6476 } 6477 6478 markup += ">"; 6479 6480 for (var i = 0; i < this.children.length; i++) { 6481 markup += this.children[i].toMarkup(); 6482 } 6483 6484 markup += "</" + this.type + ">"; 6485 return markup; 6486 } 6487 /** 6488 * Converts the math node into a string, similar to innerText, but escaped. 6489 */ 6490 6491 6492 toText() { 6493 return this.children.map(child => child.toText()).join(""); 6494 } 6495 6496 } 6497 /** 6498 * This node represents a piece of text. 6499 */ 6500 6501 class TextNode { 6502 constructor(text) { 6503 this.text = void 0; 6504 this.text = text; 6505 } 6506 /** 6507 * Converts the text node into a DOM text node. 6508 */ 6509 6510 6511 toNode() { 6512 return document.createTextNode(this.text); 6513 } 6514 /** 6515 * Converts the text node into escaped HTML markup 6516 * (representing the text itself). 6517 */ 6518 6519 6520 toMarkup() { 6521 return utils.escape(this.toText()); 6522 } 6523 /** 6524 * Converts the text node into a string 6525 * (representing the text iteself). 6526 */ 6527 6528 6529 toText() { 6530 return this.text; 6531 } 6532 6533 } 6534 /** 6535 * This node represents a space, but may render as <mspace.../> or as text, 6536 * depending on the width. 6537 */ 6538 6539 class SpaceNode { 6540 /** 6541 * Create a Space node with width given in CSS ems. 6542 */ 6543 constructor(width) { 6544 this.width = void 0; 6545 this.character = void 0; 6546 this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html 6547 // for a table of space-like characters. We use Unicode 6548 // representations instead of &LongNames; as it's not clear how to 6549 // make the latter via document.createTextNode. 6550 6551 if (width >= 0.05555 && width <= 0.05556) { 6552 this.character = "\u200a"; //   6553 } else if (width >= 0.1666 && width <= 0.1667) { 6554 this.character = "\u2009"; //   6555 } else if (width >= 0.2222 && width <= 0.2223) { 6556 this.character = "\u2005"; //   6557 } else if (width >= 0.2777 && width <= 0.2778) { 6558 this.character = "\u2005\u200a"; //    6559 } else if (width >= -0.05556 && width <= -0.05555) { 6560 this.character = "\u200a\u2063"; // ​ 6561 } else if (width >= -0.1667 && width <= -0.1666) { 6562 this.character = "\u2009\u2063"; // ​ 6563 } else if (width >= -0.2223 && width <= -0.2222) { 6564 this.character = "\u205f\u2063"; // ​ 6565 } else if (width >= -0.2778 && width <= -0.2777) { 6566 this.character = "\u2005\u2063"; // ​ 6567 } else { 6568 this.character = null; 6569 } 6570 } 6571 /** 6572 * Converts the math node into a MathML-namespaced DOM element. 6573 */ 6574 6575 6576 toNode() { 6577 if (this.character) { 6578 return document.createTextNode(this.character); 6579 } else { 6580 var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace"); 6581 node.setAttribute("width", this.width + "em"); 6582 return node; 6583 } 6584 } 6585 /** 6586 * Converts the math node into an HTML markup string. 6587 */ 6588 6589 6590 toMarkup() { 6591 if (this.character) { 6592 return "<mtext>" + this.character + "</mtext>"; 6593 } else { 6594 return "<mspace width=\"" + this.width + "em\"/>"; 6595 } 6596 } 6597 /** 6598 * Converts the math node into a string, similar to innerText. 6599 */ 6600 6601 6602 toText() { 6603 if (this.character) { 6604 return this.character; 6605 } else { 6606 return " "; 6607 } 6608 } 6609 6610 } 6611 6612 var mathMLTree = { 6613 MathNode, 6614 TextNode, 6615 SpaceNode, 6616 newDocumentFragment 6617 }; 6618 6619 /** 6620 * This file converts a parse tree into a cooresponding MathML tree. The main 6621 * entry point is the `buildMathML` function, which takes a parse tree from the 6622 * parser. 6623 */ 6624 6625 /** 6626 * Takes a symbol and converts it into a MathML text node after performing 6627 * optional replacement from symbols.js. 6628 */ 6629 var makeText = function makeText(text, mode, options) { 6630 if (symbols[mode][text] && symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.substr(4, 2) === "tt" || options.font && options.font.substr(4, 2) === "tt"))) { 6631 text = symbols[mode][text].replace; 6632 } 6633 6634 return new mathMLTree.TextNode(text); 6635 }; 6636 /** 6637 * Wrap the given array of nodes in an <mrow> node if needed, i.e., 6638 * unless the array has length 1. Always returns a single node. 6639 */ 6640 6641 var makeRow = function makeRow(body) { 6642 if (body.length === 1) { 6643 return body[0]; 6644 } else { 6645 return new mathMLTree.MathNode("mrow", body); 6646 } 6647 }; 6648 /** 6649 * Returns the math variant as a string or null if none is required. 6650 */ 6651 6652 var getVariant = function getVariant(group, options) { 6653 // Handle \text... font specifiers as best we can. 6654 // MathML has a limited list of allowable mathvariant specifiers; see 6655 // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt 6656 if (options.fontFamily === "texttt") { 6657 return "monospace"; 6658 } else if (options.fontFamily === "textsf") { 6659 if (options.fontShape === "textit" && options.fontWeight === "textbf") { 6660 return "sans-serif-bold-italic"; 6661 } else if (options.fontShape === "textit") { 6662 return "sans-serif-italic"; 6663 } else if (options.fontWeight === "textbf") { 6664 return "bold-sans-serif"; 6665 } else { 6666 return "sans-serif"; 6667 } 6668 } else if (options.fontShape === "textit" && options.fontWeight === "textbf") { 6669 return "bold-italic"; 6670 } else if (options.fontShape === "textit") { 6671 return "italic"; 6672 } else if (options.fontWeight === "textbf") { 6673 return "bold"; 6674 } 6675 6676 var font = options.font; 6677 6678 if (!font || font === "mathnormal") { 6679 return null; 6680 } 6681 6682 var mode = group.mode; 6683 6684 if (font === "mathit") { 6685 return "italic"; 6686 } else if (font === "boldsymbol") { 6687 return group.type === "textord" ? "bold" : "bold-italic"; 6688 } else if (font === "mathbf") { 6689 return "bold"; 6690 } else if (font === "mathbb") { 6691 return "double-struck"; 6692 } else if (font === "mathfrak") { 6693 return "fraktur"; 6694 } else if (font === "mathscr" || font === "mathcal") { 6695 // MathML makes no distinction between script and caligrahpic 6696 return "script"; 6697 } else if (font === "mathsf") { 6698 return "sans-serif"; 6699 } else if (font === "mathtt") { 6700 return "monospace"; 6701 } 6702 6703 var text = group.text; 6704 6705 if (utils.contains(["\\imath", "\\jmath"], text)) { 6706 return null; 6707 } 6708 6709 if (symbols[mode][text] && symbols[mode][text].replace) { 6710 text = symbols[mode][text].replace; 6711 } 6712 6713 var fontName = buildCommon.fontMap[font].fontName; 6714 6715 if (getCharacterMetrics(text, fontName, mode)) { 6716 return buildCommon.fontMap[font].variant; 6717 } 6718 6719 return null; 6720 }; 6721 /** 6722 * Takes a list of nodes, builds them, and returns a list of the generated 6723 * MathML nodes. Also combine consecutive <mtext> outputs into a single 6724 * <mtext> tag. 6725 */ 6726 6727 var buildExpression$1 = function buildExpression(expression, options, isOrdgroup) { 6728 if (expression.length === 1) { 6729 var group = buildGroup$1(expression[0], options); 6730 6731 if (isOrdgroup && group instanceof MathNode && group.type === "mo") { 6732 // When TeX writers want to suppress spacing on an operator, 6733 // they often put the operator by itself inside braces. 6734 group.setAttribute("lspace", "0em"); 6735 group.setAttribute("rspace", "0em"); 6736 } 6737 6738 return [group]; 6739 } 6740 6741 var groups = []; 6742 var lastGroup; 6743 6744 for (var i = 0; i < expression.length; i++) { 6745 var _group = buildGroup$1(expression[i], options); 6746 6747 if (_group instanceof MathNode && lastGroup instanceof MathNode) { 6748 // Concatenate adjacent <mtext>s 6749 if (_group.type === 'mtext' && lastGroup.type === 'mtext' && _group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) { 6750 lastGroup.children.push(..._group.children); 6751 continue; // Concatenate adjacent <mn>s 6752 } else if (_group.type === 'mn' && lastGroup.type === 'mn') { 6753 lastGroup.children.push(..._group.children); 6754 continue; // Concatenate <mn>...</mn> followed by <mi>.</mi> 6755 } else if (_group.type === 'mi' && _group.children.length === 1 && lastGroup.type === 'mn') { 6756 var child = _group.children[0]; 6757 6758 if (child instanceof TextNode && child.text === '.') { 6759 lastGroup.children.push(..._group.children); 6760 continue; 6761 } 6762 } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) { 6763 var lastChild = lastGroup.children[0]; 6764 6765 if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (_group.type === 'mo' || _group.type === 'mi' || _group.type === 'mn')) { 6766 var _child = _group.children[0]; 6767 6768 if (_child instanceof TextNode && _child.text.length > 0) { 6769 // Overlay with combining character long solidus 6770 _child.text = _child.text.slice(0, 1) + "\u0338" + _child.text.slice(1); 6771 groups.pop(); 6772 } 6773 } 6774 } 6775 } 6776 6777 groups.push(_group); 6778 lastGroup = _group; 6779 } 6780 6781 return groups; 6782 }; 6783 /** 6784 * Equivalent to buildExpression, but wraps the elements in an <mrow> 6785 * if there's more than one. Returns a single node instead of an array. 6786 */ 6787 6788 var buildExpressionRow = function buildExpressionRow(expression, options, isOrdgroup) { 6789 return makeRow(buildExpression$1(expression, options, isOrdgroup)); 6790 }; 6791 /** 6792 * Takes a group from the parser and calls the appropriate groupBuilders function 6793 * on it to produce a MathML node. 6794 */ 6795 6796 var buildGroup$1 = function buildGroup(group, options) { 6797 if (!group) { 6798 return new mathMLTree.MathNode("mrow"); 6799 } 6800 6801 if (_mathmlGroupBuilders[group.type]) { 6802 // Call the groupBuilders function 6803 // $FlowFixMe 6804 var result = _mathmlGroupBuilders[group.type](group, options); // $FlowFixMe 6805 6806 return result; 6807 } else { 6808 throw new ParseError("Got group of unknown type: '" + group.type + "'"); 6809 } 6810 }; 6811 /** 6812 * Takes a full parse tree and settings and builds a MathML representation of 6813 * it. In particular, we put the elements from building the parse tree into a 6814 * <semantics> tag so we can also include that TeX source as an annotation. 6815 * 6816 * Note that we actually return a domTree element with a `<math>` inside it so 6817 * we can do appropriate styling. 6818 */ 6819 6820 function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) { 6821 var expression = buildExpression$1(tree, options); // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes 6822 // and add spacing nodes. This is necessary only adjacent to math operators 6823 // like \sin or \lim or to subsup elements that contain math operators. 6824 // MathML takes care of the other spacing issues. 6825 // Wrap up the expression in an mrow so it is presented in the semantics 6826 // tag correctly, unless it's a single <mrow> or <mtable>. 6827 6828 var wrapper; 6829 6830 if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) { 6831 wrapper = expression[0]; 6832 } else { 6833 wrapper = new mathMLTree.MathNode("mrow", expression); 6834 } // Build a TeX annotation of the source 6835 6836 6837 var annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]); 6838 annotation.setAttribute("encoding", "application/x-tex"); 6839 var semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); 6840 var math = new mathMLTree.MathNode("math", [semantics]); 6841 math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); 6842 6843 if (isDisplayMode) { 6844 math.setAttribute("display", "block"); 6845 } // You can't style <math> nodes, so we wrap the node in a span. 6846 // NOTE: The span class is not typed to have <math> nodes as children, and 6847 // we don't want to make the children type more generic since the children 6848 // of span are expected to have more fields in `buildHtml` contexts. 6849 6850 6851 var wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe 6852 6853 return buildCommon.makeSpan([wrapperClass], [math]); 6854 } 6855 6856 var optionsFromSettings = function optionsFromSettings(settings) { 6857 return new Options({ 6858 style: settings.displayMode ? Style$1.DISPLAY : Style$1.TEXT, 6859 maxSize: settings.maxSize, 6860 minRuleThickness: settings.minRuleThickness 6861 }); 6862 }; 6863 6864 var displayWrap = function displayWrap(node, settings) { 6865 if (settings.displayMode) { 6866 var classes = ["katex-display"]; 6867 6868 if (settings.leqno) { 6869 classes.push("leqno"); 6870 } 6871 6872 if (settings.fleqn) { 6873 classes.push("fleqn"); 6874 } 6875 6876 node = buildCommon.makeSpan(classes, [node]); 6877 } 6878 6879 return node; 6880 }; 6881 6882 var buildTree = function buildTree(tree, expression, settings) { 6883 var options = optionsFromSettings(settings); 6884 var katexNode; 6885 6886 if (settings.output === "mathml") { 6887 return buildMathML(tree, expression, options, settings.displayMode, true); 6888 } else if (settings.output === "html") { 6889 var htmlNode = buildHTML(tree, options); 6890 katexNode = buildCommon.makeSpan(["katex"], [htmlNode]); 6891 } else { 6892 var mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false); 6893 6894 var _htmlNode = buildHTML(tree, options); 6895 6896 katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, _htmlNode]); 6897 } 6898 6899 return displayWrap(katexNode, settings); 6900 }; 6901 var buildHTMLTree = function buildHTMLTree(tree, expression, settings) { 6902 var options = optionsFromSettings(settings); 6903 var htmlNode = buildHTML(tree, options); 6904 var katexNode = buildCommon.makeSpan(["katex"], [htmlNode]); 6905 return displayWrap(katexNode, settings); 6906 }; 6907 6908 /** 6909 * This file provides support to buildMathML.js and buildHTML.js 6910 * for stretchy wide elements rendered from SVG files 6911 * and other CSS trickery. 6912 */ 6913 var stretchyCodePoint = { 6914 widehat: "^", 6915 widecheck: "ˇ", 6916 widetilde: "~", 6917 utilde: "~", 6918 overleftarrow: "\u2190", 6919 underleftarrow: "\u2190", 6920 xleftarrow: "\u2190", 6921 overrightarrow: "\u2192", 6922 underrightarrow: "\u2192", 6923 xrightarrow: "\u2192", 6924 underbrace: "\u23df", 6925 overbrace: "\u23de", 6926 overgroup: "\u23e0", 6927 undergroup: "\u23e1", 6928 overleftrightarrow: "\u2194", 6929 underleftrightarrow: "\u2194", 6930 xleftrightarrow: "\u2194", 6931 Overrightarrow: "\u21d2", 6932 xRightarrow: "\u21d2", 6933 overleftharpoon: "\u21bc", 6934 xleftharpoonup: "\u21bc", 6935 overrightharpoon: "\u21c0", 6936 xrightharpoonup: "\u21c0", 6937 xLeftarrow: "\u21d0", 6938 xLeftrightarrow: "\u21d4", 6939 xhookleftarrow: "\u21a9", 6940 xhookrightarrow: "\u21aa", 6941 xmapsto: "\u21a6", 6942 xrightharpoondown: "\u21c1", 6943 xleftharpoondown: "\u21bd", 6944 xrightleftharpoons: "\u21cc", 6945 xleftrightharpoons: "\u21cb", 6946 xtwoheadleftarrow: "\u219e", 6947 xtwoheadrightarrow: "\u21a0", 6948 xlongequal: "=", 6949 xtofrom: "\u21c4", 6950 xrightleftarrows: "\u21c4", 6951 xrightequilibrium: "\u21cc", 6952 // Not a perfect match. 6953 xleftequilibrium: "\u21cb", 6954 // None better available. 6955 "\\\\cdrightarrow": "\u2192", 6956 "\\\\cdleftarrow": "\u2190", 6957 "\\\\cdlongequal": "=" 6958 }; 6959 6960 var mathMLnode = function mathMLnode(label) { 6961 var node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label])]); 6962 node.setAttribute("stretchy", "true"); 6963 return node; 6964 }; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts. 6965 // Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>) 6966 // Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>) 6967 // Licensed under the SIL Open Font License, Version 1.1. 6968 // See \nhttp://scripts.sil.org/OFL 6969 // Very Long SVGs 6970 // Many of the KaTeX stretchy wide elements use a long SVG image and an 6971 // overflow: hidden tactic to achieve a stretchy image while avoiding 6972 // distortion of arrowheads or brace corners. 6973 // The SVG typically contains a very long (400 em) arrow. 6974 // The SVG is in a container span that has overflow: hidden, so the span 6975 // acts like a window that exposes only part of the SVG. 6976 // The SVG always has a longer, thinner aspect ratio than the container span. 6977 // After the SVG fills 100% of the height of the container span, 6978 // there is a long arrow shaft left over. That left-over shaft is not shown. 6979 // Instead, it is sliced off because the span's CSS has overflow: hidden. 6980 // Thus, the reader sees an arrow that matches the subject matter width 6981 // without distortion. 6982 // Some functions, such as \cancel, need to vary their aspect ratio. These 6983 // functions do not get the overflow SVG treatment. 6984 // Second Brush Stroke 6985 // Low resolution monitors struggle to display images in fine detail. 6986 // So browsers apply anti-aliasing. A long straight arrow shaft therefore 6987 // will sometimes appear as if it has a blurred edge. 6988 // To mitigate this, these SVG files contain a second "brush-stroke" on the 6989 // arrow shafts. That is, a second long thin rectangular SVG path has been 6990 // written directly on top of each arrow shaft. This reinforcement causes 6991 // some of the screen pixels to display as black instead of the anti-aliased 6992 // gray pixel that a single path would generate. So we get arrow shafts 6993 // whose edges appear to be sharper. 6994 // In the katexImagesData object just below, the dimensions all 6995 // correspond to path geometry inside the relevant SVG. 6996 // For example, \overrightarrow uses the same arrowhead as glyph U+2192 6997 // from the KaTeX Main font. The scaling factor is 1000. 6998 // That is, inside the font, that arrowhead is 522 units tall, which 6999 // corresponds to 0.522 em inside the document. 7000 7001 7002 var katexImagesData = { 7003 // path(s), minWidth, height, align 7004 overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], 7005 overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], 7006 underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], 7007 underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], 7008 xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], 7009 "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"], 7010 // CD minwwidth2.5pc 7011 xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], 7012 "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"], 7013 Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"], 7014 xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"], 7015 xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"], 7016 overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"], 7017 xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"], 7018 xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"], 7019 overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"], 7020 xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"], 7021 xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"], 7022 xlongequal: [["longequal"], 0.888, 334, "xMinYMin"], 7023 "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"], 7024 xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"], 7025 xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"], 7026 overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], 7027 overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548], 7028 underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548], 7029 underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], 7030 xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], 7031 xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560], 7032 xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716], 7033 xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716], 7034 xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522], 7035 xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522], 7036 overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], 7037 underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], 7038 overgroup: [["leftgroup", "rightgroup"], 0.888, 342], 7039 undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342], 7040 xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522], 7041 xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528], 7042 // The next three arrows are from the mhchem package. 7043 // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the 7044 // document as \xrightarrow or \xrightleftharpoons. Those have 7045 // min-length = 1.75em, so we set min-length on these next three to match. 7046 xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], 7047 xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716], 7048 xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716] 7049 }; 7050 7051 var groupLength = function groupLength(arg) { 7052 if (arg.type === "ordgroup") { 7053 return arg.body.length; 7054 } else { 7055 return 1; 7056 } 7057 }; 7058 7059 var svgSpan = function svgSpan(group, options) { 7060 // Create a span with inline SVG for the element. 7061 function buildSvgSpan_() { 7062 var viewBoxWidth = 400000; // default 7063 7064 var label = group.label.substr(1); 7065 7066 if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) { 7067 // Each type in the `if` statement corresponds to one of the ParseNode 7068 // types below. This narrowing is required to access `grp.base`. 7069 // $FlowFixMe 7070 var grp = group; // There are four SVG images available for each function. 7071 // Choose a taller image when there are more characters. 7072 7073 var numChars = groupLength(grp.base); 7074 var viewBoxHeight; 7075 var pathName; 7076 7077 var _height; 7078 7079 if (numChars > 5) { 7080 if (label === "widehat" || label === "widecheck") { 7081 viewBoxHeight = 420; 7082 viewBoxWidth = 2364; 7083 _height = 0.42; 7084 pathName = label + "4"; 7085 } else { 7086 viewBoxHeight = 312; 7087 viewBoxWidth = 2340; 7088 _height = 0.34; 7089 pathName = "tilde4"; 7090 } 7091 } else { 7092 var imgIndex = [1, 1, 2, 2, 3, 3][numChars]; 7093 7094 if (label === "widehat" || label === "widecheck") { 7095 viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex]; 7096 viewBoxHeight = [0, 239, 300, 360, 420][imgIndex]; 7097 _height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex]; 7098 pathName = label + imgIndex; 7099 } else { 7100 viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex]; 7101 viewBoxHeight = [0, 260, 286, 306, 312][imgIndex]; 7102 _height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex]; 7103 pathName = "tilde" + imgIndex; 7104 } 7105 } 7106 7107 var path = new PathNode(pathName); 7108 var svgNode = new SvgNode([path], { 7109 "width": "100%", 7110 "height": _height + "em", 7111 "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight, 7112 "preserveAspectRatio": "none" 7113 }); 7114 return { 7115 span: buildCommon.makeSvgSpan([], [svgNode], options), 7116 minWidth: 0, 7117 height: _height 7118 }; 7119 } else { 7120 var spans = []; 7121 var data = katexImagesData[label]; 7122 var [paths, _minWidth, _viewBoxHeight] = data; 7123 7124 var _height2 = _viewBoxHeight / 1000; 7125 7126 var numSvgChildren = paths.length; 7127 var widthClasses; 7128 var aligns; 7129 7130 if (numSvgChildren === 1) { 7131 // $FlowFixMe: All these cases must be of the 4-tuple type. 7132 var align1 = data[3]; 7133 widthClasses = ["hide-tail"]; 7134 aligns = [align1]; 7135 } else if (numSvgChildren === 2) { 7136 widthClasses = ["halfarrow-left", "halfarrow-right"]; 7137 aligns = ["xMinYMin", "xMaxYMin"]; 7138 } else if (numSvgChildren === 3) { 7139 widthClasses = ["brace-left", "brace-center", "brace-right"]; 7140 aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"]; 7141 } else { 7142 throw new Error("Correct katexImagesData or update code here to support\n " + numSvgChildren + " children."); 7143 } 7144 7145 for (var i = 0; i < numSvgChildren; i++) { 7146 var _path = new PathNode(paths[i]); 7147 7148 var _svgNode = new SvgNode([_path], { 7149 "width": "400em", 7150 "height": _height2 + "em", 7151 "viewBox": "0 0 " + viewBoxWidth + " " + _viewBoxHeight, 7152 "preserveAspectRatio": aligns[i] + " slice" 7153 }); 7154 7155 var _span = buildCommon.makeSvgSpan([widthClasses[i]], [_svgNode], options); 7156 7157 if (numSvgChildren === 1) { 7158 return { 7159 span: _span, 7160 minWidth: _minWidth, 7161 height: _height2 7162 }; 7163 } else { 7164 _span.style.height = _height2 + "em"; 7165 spans.push(_span); 7166 } 7167 } 7168 7169 return { 7170 span: buildCommon.makeSpan(["stretchy"], spans, options), 7171 minWidth: _minWidth, 7172 height: _height2 7173 }; 7174 } 7175 } // buildSvgSpan_() 7176 7177 7178 var { 7179 span, 7180 minWidth, 7181 height 7182 } = buildSvgSpan_(); // Note that we are returning span.depth = 0. 7183 // Any adjustments relative to the baseline must be done in buildHTML. 7184 7185 span.height = height; 7186 span.style.height = height + "em"; 7187 7188 if (minWidth > 0) { 7189 span.style.minWidth = minWidth + "em"; 7190 } 7191 7192 return span; 7193 }; 7194 7195 var encloseSpan = function encloseSpan(inner, label, topPad, bottomPad, options) { 7196 // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl 7197 var img; 7198 var totalHeight = inner.height + inner.depth + topPad + bottomPad; 7199 7200 if (/fbox|color|angl/.test(label)) { 7201 img = buildCommon.makeSpan(["stretchy", label], [], options); 7202 7203 if (label === "fbox") { 7204 var color = options.color && options.getColor(); 7205 7206 if (color) { 7207 img.style.borderColor = color; 7208 } 7209 } 7210 } else { 7211 // \cancel, \bcancel, or \xcancel 7212 // Since \cancel's SVG is inline and it omits the viewBox attribute, 7213 // its stroke-width will not vary with span area. 7214 var lines = []; 7215 7216 if (/^[bx]cancel$/.test(label)) { 7217 lines.push(new LineNode({ 7218 "x1": "0", 7219 "y1": "0", 7220 "x2": "100%", 7221 "y2": "100%", 7222 "stroke-width": "0.046em" 7223 })); 7224 } 7225 7226 if (/^x?cancel$/.test(label)) { 7227 lines.push(new LineNode({ 7228 "x1": "0", 7229 "y1": "100%", 7230 "x2": "100%", 7231 "y2": "0", 7232 "stroke-width": "0.046em" 7233 })); 7234 } 7235 7236 var svgNode = new SvgNode(lines, { 7237 "width": "100%", 7238 "height": totalHeight + "em" 7239 }); 7240 img = buildCommon.makeSvgSpan([], [svgNode], options); 7241 } 7242 7243 img.height = totalHeight; 7244 img.style.height = totalHeight + "em"; 7245 return img; 7246 }; 7247 7248 var stretchy = { 7249 encloseSpan, 7250 mathMLnode, 7251 svgSpan 7252 }; 7253 7254 /** 7255 * Asserts that the node is of the given type and returns it with stricter 7256 * typing. Throws if the node's type does not match. 7257 */ 7258 function assertNodeType(node, type) { 7259 if (!node || node.type !== type) { 7260 throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node))); 7261 } // $FlowFixMe, >=0.125 7262 7263 7264 return node; 7265 } 7266 /** 7267 * Returns the node more strictly typed iff it is of the given type. Otherwise, 7268 * returns null. 7269 */ 7270 7271 function assertSymbolNodeType(node) { 7272 var typedNode = checkSymbolNodeType(node); 7273 7274 if (!typedNode) { 7275 throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node))); 7276 } 7277 7278 return typedNode; 7279 } 7280 /** 7281 * Returns the node more strictly typed iff it is of the given type. Otherwise, 7282 * returns null. 7283 */ 7284 7285 function checkSymbolNodeType(node) { 7286 if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) { 7287 // $FlowFixMe 7288 return node; 7289 } 7290 7291 return null; 7292 } 7293 7294 // NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but 7295 // also "supsub" since an accent can affect super/subscripting. 7296 var htmlBuilder = (grp, options) => { 7297 // Accents are handled in the TeXbook pg. 443, rule 12. 7298 var base; 7299 var group; 7300 var supSubGroup; 7301 7302 if (grp && grp.type === "supsub") { 7303 // If our base is a character box, and we have superscripts and 7304 // subscripts, the supsub will defer to us. In particular, we want 7305 // to attach the superscripts and subscripts to the inner body (so 7306 // that the position of the superscripts and subscripts won't be 7307 // affected by the height of the accent). We accomplish this by 7308 // sticking the base of the accent into the base of the supsub, and 7309 // rendering that, while keeping track of where the accent is. 7310 // The real accent group is the base of the supsub group 7311 group = assertNodeType(grp.base, "accent"); // The character box is the base of the accent group 7312 7313 base = group.base; // Stick the character box into the base of the supsub group 7314 7315 grp.base = base; // Rerender the supsub group with its new base, and store that 7316 // result. 7317 7318 supSubGroup = assertSpan(buildGroup(grp, options)); // reset original base 7319 7320 grp.base = group; 7321 } else { 7322 group = assertNodeType(grp, "accent"); 7323 base = group.base; 7324 } // Build the base group 7325 7326 7327 var body = buildGroup(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character? 7328 7329 var mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the 7330 // nucleus is not a single character, let s = 0; otherwise set s to the 7331 // kern amount for the nucleus followed by the \skewchar of its font." 7332 // Note that our skew metrics are just the kern between each character 7333 // and the skewchar. 7334 7335 var skew = 0; 7336 7337 if (mustShift) { 7338 // If the base is a character box, then we want the skew of the 7339 // innermost character. To do that, we find the innermost character: 7340 var baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it 7341 7342 var baseGroup = buildGroup(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol. 7343 7344 skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we 7345 // removed with getBaseElem might contain things like \color which 7346 // we can't get rid of. 7347 // TODO(emily): Find a better way to get the skew 7348 } // calculate the amount of space between the body and the accent 7349 7350 7351 var clearance = Math.min(body.height, options.fontMetrics().xHeight); // Build the accent 7352 7353 var accentBody; 7354 7355 if (!group.isStretchy) { 7356 var accent; 7357 var width; 7358 7359 if (group.label === "\\vec") { 7360 // Before version 0.9, \vec used the combining font glyph U+20D7. 7361 // But browsers, especially Safari, are not consistent in how they 7362 // render combining characters when not preceded by a character. 7363 // So now we use an SVG. 7364 // If Safari reforms, we should consider reverting to the glyph. 7365 accent = buildCommon.staticSvg("vec", options); 7366 width = buildCommon.svgData.vec[1]; 7367 } else { 7368 accent = buildCommon.makeOrd({ 7369 mode: group.mode, 7370 text: group.label 7371 }, options, "textord"); 7372 accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to 7373 // shift the accent over to a place we don't want. 7374 7375 accent.italic = 0; 7376 width = accent.width; 7377 } 7378 7379 accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be 7380 // at least the width of the accent, and overlap directly onto the 7381 // character without any vertical offset. 7382 7383 var accentFull = group.label === "\\textcircled"; 7384 7385 if (accentFull) { 7386 accentBody.classes.push('accent-full'); 7387 clearance = body.height; 7388 } // Shift the accent over by the skew. 7389 7390 7391 var left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }` 7392 // so that the accent doesn't contribute to the bounding box. 7393 // We need to shift the character by its width (effectively half 7394 // its width) to compensate. 7395 7396 if (!accentFull) { 7397 left -= width / 2; 7398 } 7399 7400 accentBody.style.left = left + "em"; // \textcircled uses the \bigcirc glyph, so it needs some 7401 // vertical adjustment to match LaTeX. 7402 7403 if (group.label === "\\textcircled") { 7404 accentBody.style.top = ".2em"; 7405 } 7406 7407 accentBody = buildCommon.makeVList({ 7408 positionType: "firstBaseline", 7409 children: [{ 7410 type: "elem", 7411 elem: body 7412 }, { 7413 type: "kern", 7414 size: -clearance 7415 }, { 7416 type: "elem", 7417 elem: accentBody 7418 }] 7419 }, options); 7420 } else { 7421 accentBody = stretchy.svgSpan(group, options); 7422 accentBody = buildCommon.makeVList({ 7423 positionType: "firstBaseline", 7424 children: [{ 7425 type: "elem", 7426 elem: body 7427 }, { 7428 type: "elem", 7429 elem: accentBody, 7430 wrapperClasses: ["svg-align"], 7431 wrapperStyle: skew > 0 ? { 7432 width: "calc(100% - " + 2 * skew + "em)", 7433 marginLeft: 2 * skew + "em" 7434 } : undefined 7435 }] 7436 }, options); 7437 } 7438 7439 var accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options); 7440 7441 if (supSubGroup) { 7442 // Here, we replace the "base" child of the supsub with our newly 7443 // generated accent. 7444 supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the 7445 // accent, we manually recalculate height. 7446 7447 supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not. 7448 7449 supSubGroup.classes[0] = "mord"; 7450 return supSubGroup; 7451 } else { 7452 return accentWrap; 7453 } 7454 }; 7455 7456 var mathmlBuilder = (group, options) => { 7457 var accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); 7458 var node = new mathMLTree.MathNode("mover", [buildGroup$1(group.base, options), accentNode]); 7459 node.setAttribute("accent", "true"); 7460 return node; 7461 }; 7462 7463 var NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|")); // Accents 7464 7465 defineFunction({ 7466 type: "accent", 7467 names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"], 7468 props: { 7469 numArgs: 1 7470 }, 7471 handler: (context, args) => { 7472 var base = normalizeArgument(args[0]); 7473 var isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); 7474 var isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck"; 7475 return { 7476 type: "accent", 7477 mode: context.parser.mode, 7478 label: context.funcName, 7479 isStretchy: isStretchy, 7480 isShifty: isShifty, 7481 base: base 7482 }; 7483 }, 7484 htmlBuilder, 7485 mathmlBuilder 7486 }); // Text-mode accents 7487 7488 defineFunction({ 7489 type: "accent", 7490 names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v", "\\textcircled"], 7491 props: { 7492 numArgs: 1, 7493 allowedInText: true, 7494 allowedInMath: false, 7495 argTypes: ["primitive"] 7496 }, 7497 handler: (context, args) => { 7498 var base = args[0]; 7499 return { 7500 type: "accent", 7501 mode: context.parser.mode, 7502 label: context.funcName, 7503 isStretchy: false, 7504 isShifty: true, 7505 base: base 7506 }; 7507 }, 7508 htmlBuilder, 7509 mathmlBuilder 7510 }); 7511 7512 // Horizontal overlap functions 7513 defineFunction({ 7514 type: "accentUnder", 7515 names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"], 7516 props: { 7517 numArgs: 1 7518 }, 7519 handler: (_ref, args) => { 7520 var { 7521 parser, 7522 funcName 7523 } = _ref; 7524 var base = args[0]; 7525 return { 7526 type: "accentUnder", 7527 mode: parser.mode, 7528 label: funcName, 7529 base: base 7530 }; 7531 }, 7532 htmlBuilder: (group, options) => { 7533 // Treat under accents much like underlines. 7534 var innerGroup = buildGroup(group.base, options); 7535 var accentBody = stretchy.svgSpan(group, options); 7536 var kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns 7537 7538 var vlist = buildCommon.makeVList({ 7539 positionType: "top", 7540 positionData: innerGroup.height, 7541 children: [{ 7542 type: "elem", 7543 elem: accentBody, 7544 wrapperClasses: ["svg-align"] 7545 }, { 7546 type: "kern", 7547 size: kern 7548 }, { 7549 type: "elem", 7550 elem: innerGroup 7551 }] 7552 }, options); 7553 return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options); 7554 }, 7555 mathmlBuilder: (group, options) => { 7556 var accentNode = stretchy.mathMLnode(group.label); 7557 var node = new mathMLTree.MathNode("munder", [buildGroup$1(group.base, options), accentNode]); 7558 node.setAttribute("accentunder", "true"); 7559 return node; 7560 } 7561 }); 7562 7563 // Helper function 7564 var paddedNode = group => { 7565 var node = new mathMLTree.MathNode("mpadded", group ? [group] : []); 7566 node.setAttribute("width", "+0.6em"); 7567 node.setAttribute("lspace", "0.3em"); 7568 return node; 7569 }; // Stretchy arrows with an optional argument 7570 7571 7572 defineFunction({ 7573 type: "xArrow", 7574 names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", // The next 3 functions are here to support the mhchem extension. 7575 // Direct use of these functions is discouraged and may break someday. 7576 "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", // The next 3 functions are here only to support the {CD} environment. 7577 "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"], 7578 props: { 7579 numArgs: 1, 7580 numOptionalArgs: 1 7581 }, 7582 7583 handler(_ref, args, optArgs) { 7584 var { 7585 parser, 7586 funcName 7587 } = _ref; 7588 return { 7589 type: "xArrow", 7590 mode: parser.mode, 7591 label: funcName, 7592 body: args[0], 7593 below: optArgs[0] 7594 }; 7595 }, 7596 7597 // Flow is unable to correctly infer the type of `group`, even though it's 7598 // unamibiguously determined from the passed-in `type` above. 7599 htmlBuilder(group, options) { 7600 var style = options.style; // Build the argument groups in the appropriate style. 7601 // Ref: amsmath.dtx: \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}% 7602 // Some groups can return document fragments. Handle those by wrapping 7603 // them in a span. 7604 7605 var newOptions = options.havingStyle(style.sup()); 7606 var upperGroup = buildCommon.wrapFragment(buildGroup(group.body, newOptions, options), options); 7607 var arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd"; 7608 upperGroup.classes.push(arrowPrefix + "-arrow-pad"); 7609 var lowerGroup; 7610 7611 if (group.below) { 7612 // Build the lower group 7613 newOptions = options.havingStyle(style.sub()); 7614 lowerGroup = buildCommon.wrapFragment(buildGroup(group.below, newOptions, options), options); 7615 lowerGroup.classes.push(arrowPrefix + "-arrow-pad"); 7616 } 7617 7618 var arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0. 7619 // The point we want on the math axis is at 0.5 * arrowBody.height. 7620 7621 var arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi 7622 7623 var upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu 7624 7625 if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") { 7626 upperShift -= upperGroup.depth; // shift up if depth encroaches 7627 } // Generate the vlist 7628 7629 7630 var vlist; 7631 7632 if (lowerGroup) { 7633 var lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111; 7634 vlist = buildCommon.makeVList({ 7635 positionType: "individualShift", 7636 children: [{ 7637 type: "elem", 7638 elem: upperGroup, 7639 shift: upperShift 7640 }, { 7641 type: "elem", 7642 elem: arrowBody, 7643 shift: arrowShift 7644 }, { 7645 type: "elem", 7646 elem: lowerGroup, 7647 shift: lowerShift 7648 }] 7649 }, options); 7650 } else { 7651 vlist = buildCommon.makeVList({ 7652 positionType: "individualShift", 7653 children: [{ 7654 type: "elem", 7655 elem: upperGroup, 7656 shift: upperShift 7657 }, { 7658 type: "elem", 7659 elem: arrowBody, 7660 shift: arrowShift 7661 }] 7662 }, options); 7663 } // $FlowFixMe: Replace this with passing "svg-align" into makeVList. 7664 7665 7666 vlist.children[0].children[0].children[1].classes.push("svg-align"); 7667 return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options); 7668 }, 7669 7670 mathmlBuilder(group, options) { 7671 var arrowNode = stretchy.mathMLnode(group.label); 7672 arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em"); 7673 var node; 7674 7675 if (group.body) { 7676 var upperNode = paddedNode(buildGroup$1(group.body, options)); 7677 7678 if (group.below) { 7679 var lowerNode = paddedNode(buildGroup$1(group.below, options)); 7680 node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); 7681 } else { 7682 node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]); 7683 } 7684 } else if (group.below) { 7685 var _lowerNode = paddedNode(buildGroup$1(group.below, options)); 7686 7687 node = new mathMLTree.MathNode("munder", [arrowNode, _lowerNode]); 7688 } else { 7689 // This should never happen. 7690 // Parser.js throws an error if there is no argument. 7691 node = paddedNode(); 7692 node = new mathMLTree.MathNode("mover", [arrowNode, node]); 7693 } 7694 7695 return node; 7696 } 7697 7698 }); 7699 7700 var cdArrowFunctionName = { 7701 ">": "\\\\cdrightarrow", 7702 "<": "\\\\cdleftarrow", 7703 "=": "\\\\cdlongequal", 7704 "A": "\\uparrow", 7705 "V": "\\downarrow", 7706 "|": "\\Vert", 7707 ".": "no arrow" 7708 }; 7709 7710 var newCell = () => { 7711 // Create an empty cell, to be filled below with parse nodes. 7712 // The parseTree from this module must be constructed like the 7713 // one created by parseArray(), so an empty CD cell must 7714 // be a ParseNode<"styling">. And CD is always displaystyle. 7715 // So these values are fixed and flow can do implicit typing. 7716 return { 7717 type: "styling", 7718 body: [], 7719 mode: "math", 7720 style: "display" 7721 }; 7722 }; 7723 7724 var isStartOfArrow = node => { 7725 return node.type === "textord" && node.text === "@"; 7726 }; 7727 7728 var isLabelEnd = (node, endChar) => { 7729 return (node.type === "mathord" || node.type === "atom") && node.text === endChar; 7730 }; 7731 7732 function cdArrow(arrowChar, labels, parser) { 7733 // Return a parse tree of an arrow and its labels. 7734 // This acts in a way similar to a macro expansion. 7735 var funcName = cdArrowFunctionName[arrowChar]; 7736 7737 switch (funcName) { 7738 case "\\\\cdrightarrow": 7739 case "\\\\cdleftarrow": 7740 return parser.callFunction(funcName, [labels[0]], [labels[1]]); 7741 7742 case "\\uparrow": 7743 case "\\downarrow": 7744 { 7745 var leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); 7746 var bareArrow = { 7747 type: "atom", 7748 text: funcName, 7749 mode: "math", 7750 family: "rel" 7751 }; 7752 var sizedArrow = parser.callFunction("\\Big", [bareArrow], []); 7753 var rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); 7754 var arrowGroup = { 7755 type: "ordgroup", 7756 mode: "math", 7757 body: [leftLabel, sizedArrow, rightLabel] 7758 }; 7759 return parser.callFunction("\\\\cdparent", [arrowGroup], []); 7760 } 7761 7762 case "\\\\cdlongequal": 7763 return parser.callFunction("\\\\cdlongequal", [], []); 7764 7765 case "\\Vert": 7766 { 7767 var arrow = { 7768 type: "textord", 7769 text: "\\Vert", 7770 mode: "math" 7771 }; 7772 return parser.callFunction("\\Big", [arrow], []); 7773 } 7774 7775 default: 7776 return { 7777 type: "textord", 7778 text: " ", 7779 mode: "math" 7780 }; 7781 } 7782 } 7783 7784 function parseCD(parser) { 7785 // Get the array's parse nodes with \\ temporarily mapped to \cr. 7786 var parsedRows = []; 7787 parser.gullet.beginGroup(); 7788 parser.gullet.macros.set("\\cr", "\\\\\\relax"); 7789 parser.gullet.beginGroup(); 7790 7791 while (true) { 7792 // eslint-disable-line no-constant-condition 7793 // Get the parse nodes for the next row. 7794 parsedRows.push(parser.parseExpression(false, "\\\\")); 7795 parser.gullet.endGroup(); 7796 parser.gullet.beginGroup(); 7797 var next = parser.fetch().text; 7798 7799 if (next === "&" || next === "\\\\") { 7800 parser.consume(); 7801 } else if (next === "\\end") { 7802 if (parsedRows[parsedRows.length - 1].length === 0) { 7803 parsedRows.pop(); // final row ended in \\ 7804 } 7805 7806 break; 7807 } else { 7808 throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); 7809 } 7810 } 7811 7812 var row = []; 7813 var body = [row]; // Loop thru the parse nodes. Collect them into cells and arrows. 7814 7815 for (var i = 0; i < parsedRows.length; i++) { 7816 // Start a new row. 7817 var rowNodes = parsedRows[i]; // Create the first cell. 7818 7819 var cell = newCell(); 7820 7821 for (var j = 0; j < rowNodes.length; j++) { 7822 if (!isStartOfArrow(rowNodes[j])) { 7823 // If a parseNode is not an arrow, it goes into a cell. 7824 cell.body.push(rowNodes[j]); 7825 } else { 7826 // Parse node j is an "@", the start of an arrow. 7827 // Before starting on the arrow, push the cell into `row`. 7828 row.push(cell); // Now collect parseNodes into an arrow. 7829 // The character after "@" defines the arrow type. 7830 7831 j += 1; 7832 var arrowChar = assertSymbolNodeType(rowNodes[j]).text; // Create two empty label nodes. We may or may not use them. 7833 7834 var labels = new Array(2); 7835 labels[0] = { 7836 type: "ordgroup", 7837 mode: "math", 7838 body: [] 7839 }; 7840 labels[1] = { 7841 type: "ordgroup", 7842 mode: "math", 7843 body: [] 7844 }; // Process the arrow. 7845 7846 if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { 7847 // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take 7848 // two optional labels. E.g. the right-point arrow syntax is 7849 // really: @>{optional label}>{optional label}> 7850 // Collect parseNodes into labels. 7851 for (var labelNum = 0; labelNum < 2; labelNum++) { 7852 var inLabel = true; 7853 7854 for (var k = j + 1; k < rowNodes.length; k++) { 7855 if (isLabelEnd(rowNodes[k], arrowChar)) { 7856 inLabel = false; 7857 j = k; 7858 break; 7859 } 7860 7861 if (isStartOfArrow(rowNodes[k])) { 7862 throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]); 7863 } 7864 7865 labels[labelNum].body.push(rowNodes[k]); 7866 } 7867 7868 if (inLabel) { 7869 // isLabelEnd never returned a true. 7870 throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]); 7871 } 7872 } 7873 } else { 7874 throw new ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]); 7875 } // Now join the arrow to its labels. 7876 7877 7878 var arrow = cdArrow(arrowChar, labels, parser); // Wrap the arrow in ParseNode<"styling">. 7879 // This is done to match parseArray() behavior. 7880 7881 var wrappedArrow = { 7882 type: "styling", 7883 body: [arrow], 7884 mode: "math", 7885 style: "display" // CD is always displaystyle. 7886 7887 }; 7888 row.push(wrappedArrow); // In CD's syntax, cells are implicit. That is, everything that 7889 // is not an arrow gets collected into a cell. So create an empty 7890 // cell now. It will collect upcoming parseNodes. 7891 7892 cell = newCell(); 7893 } 7894 } 7895 7896 if (i % 2 === 0) { 7897 // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell 7898 // The last cell is not yet pushed into `row`, so: 7899 row.push(cell); 7900 } else { 7901 // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow 7902 // Remove the empty cell that was placed at the beginning of `row`. 7903 row.shift(); 7904 } 7905 7906 row = []; 7907 body.push(row); 7908 } // End row group 7909 7910 7911 parser.gullet.endGroup(); // End array group defining \\ 7912 7913 parser.gullet.endGroup(); // define column separation. 7914 7915 var cols = new Array(body[0].length).fill({ 7916 type: "align", 7917 align: "c", 7918 pregap: 0.25, 7919 // CD package sets \enskip between columns. 7920 postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em. 7921 7922 }); 7923 return { 7924 type: "array", 7925 mode: "math", 7926 body, 7927 arraystretch: 1, 7928 addJot: true, 7929 rowGaps: [null], 7930 cols, 7931 colSeparationType: "CD", 7932 hLinesBeforeRow: new Array(body.length + 1).fill([]) 7933 }; 7934 } // The functions below are not available for general use. 7935 // They are here only for internal use by the {CD} environment in placing labels 7936 // next to vertical arrows. 7937 // We don't need any such functions for horizontal arrows because we can reuse 7938 // the functionality that already exists for extensible arrows. 7939 7940 defineFunction({ 7941 type: "cdlabel", 7942 names: ["\\\\cdleft", "\\\\cdright"], 7943 props: { 7944 numArgs: 1 7945 }, 7946 7947 handler(_ref, args) { 7948 var { 7949 parser, 7950 funcName 7951 } = _ref; 7952 return { 7953 type: "cdlabel", 7954 mode: parser.mode, 7955 side: funcName.slice(4), 7956 label: args[0] 7957 }; 7958 }, 7959 7960 htmlBuilder(group, options) { 7961 var newOptions = options.havingStyle(options.style.sup()); 7962 var label = buildCommon.wrapFragment(buildGroup(group.label, newOptions, options), options); 7963 label.classes.push("cd-label-" + group.side); 7964 label.style.bottom = 0.8 - label.depth + "em"; // Zero out label height & depth, so vertical align of arrow is set 7965 // by the arrow height, not by the label. 7966 7967 label.height = 0; 7968 label.depth = 0; 7969 return label; 7970 }, 7971 7972 mathmlBuilder(group, options) { 7973 var label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, options)]); 7974 label = new mathMLTree.MathNode("mpadded", [label]); 7975 label.setAttribute("width", "0"); 7976 7977 if (group.side === "left") { 7978 label.setAttribute("lspace", "-1width"); 7979 } // We have to guess at vertical alignment. We know the arrow is 1.8em tall, 7980 // But we don't know the height or depth of the label. 7981 7982 7983 label.setAttribute("voffset", "0.7em"); 7984 label = new mathMLTree.MathNode("mstyle", [label]); 7985 label.setAttribute("displaystyle", "false"); 7986 label.setAttribute("scriptlevel", "1"); 7987 return label; 7988 } 7989 7990 }); 7991 defineFunction({ 7992 type: "cdlabelparent", 7993 names: ["\\\\cdparent"], 7994 props: { 7995 numArgs: 1 7996 }, 7997 7998 handler(_ref2, args) { 7999 var { 8000 parser 8001 } = _ref2; 8002 return { 8003 type: "cdlabelparent", 8004 mode: parser.mode, 8005 fragment: args[0] 8006 }; 8007 }, 8008 8009 htmlBuilder(group, options) { 8010 // Wrap the vertical arrow and its labels. 8011 // The parent gets position: relative. The child gets position: absolute. 8012 // So CSS can locate the label correctly. 8013 var parent = buildCommon.wrapFragment(buildGroup(group.fragment, options), options); 8014 parent.classes.push("cd-vert-arrow"); 8015 return parent; 8016 }, 8017 8018 mathmlBuilder(group, options) { 8019 return new mathMLTree.MathNode("mrow", [buildGroup$1(group.fragment, options)]); 8020 } 8021 8022 }); 8023 8024 // {123} and converts into symbol with code 123. It is used by the *macro* 8025 // \char defined in macros.js. 8026 8027 defineFunction({ 8028 type: "textord", 8029 names: ["\\@char"], 8030 props: { 8031 numArgs: 1, 8032 allowedInText: true 8033 }, 8034 8035 handler(_ref, args) { 8036 var { 8037 parser 8038 } = _ref; 8039 var arg = assertNodeType(args[0], "ordgroup"); 8040 var group = arg.body; 8041 var number = ""; 8042 8043 for (var i = 0; i < group.length; i++) { 8044 var node = assertNodeType(group[i], "textord"); 8045 number += node.text; 8046 } 8047 8048 var code = parseInt(number); 8049 8050 if (isNaN(code)) { 8051 throw new ParseError("\\@char has non-numeric argument " + number); 8052 } 8053 8054 return { 8055 type: "textord", 8056 mode: parser.mode, 8057 text: String.fromCharCode(code) 8058 }; 8059 } 8060 8061 }); 8062 8063 var htmlBuilder$1 = (group, options) => { 8064 var elements = buildExpression(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains. 8065 // To accomplish this, we wrap the results in a fragment, so the inner 8066 // elements will be able to directly interact with their neighbors. For 8067 // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3` 8068 8069 return buildCommon.makeFragment(elements); 8070 }; 8071 8072 var mathmlBuilder$1 = (group, options) => { 8073 var inner = buildExpression$1(group.body, options.withColor(group.color)); 8074 var node = new mathMLTree.MathNode("mstyle", inner); 8075 node.setAttribute("mathcolor", group.color); 8076 return node; 8077 }; 8078 8079 defineFunction({ 8080 type: "color", 8081 names: ["\\textcolor"], 8082 props: { 8083 numArgs: 2, 8084 allowedInText: true, 8085 argTypes: ["color", "original"] 8086 }, 8087 8088 handler(_ref, args) { 8089 var { 8090 parser 8091 } = _ref; 8092 var color = assertNodeType(args[0], "color-token").color; 8093 var body = args[1]; 8094 return { 8095 type: "color", 8096 mode: parser.mode, 8097 color, 8098 body: ordargument(body) 8099 }; 8100 }, 8101 8102 htmlBuilder: htmlBuilder$1, 8103 mathmlBuilder: mathmlBuilder$1 8104 }); 8105 defineFunction({ 8106 type: "color", 8107 names: ["\\color"], 8108 props: { 8109 numArgs: 1, 8110 allowedInText: true, 8111 argTypes: ["color"] 8112 }, 8113 8114 handler(_ref2, args) { 8115 var { 8116 parser, 8117 breakOnTokenText 8118 } = _ref2; 8119 var color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current 8120 // color, mimicking the behavior of color.sty. 8121 // This is currently used just to correctly color a \right 8122 // that follows a \color command. 8123 8124 parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored. 8125 8126 var body = parser.parseExpression(true, breakOnTokenText); 8127 return { 8128 type: "color", 8129 mode: parser.mode, 8130 color, 8131 body 8132 }; 8133 }, 8134 8135 htmlBuilder: htmlBuilder$1, 8136 mathmlBuilder: mathmlBuilder$1 8137 }); 8138 8139 // Row breaks within tabular environments, and line breaks at top level 8140 8141 defineFunction({ 8142 type: "cr", 8143 names: ["\\\\"], 8144 props: { 8145 numArgs: 0, 8146 numOptionalArgs: 1, 8147 argTypes: ["size"], 8148 allowedInText: true 8149 }, 8150 8151 handler(_ref, args, optArgs) { 8152 var { 8153 parser 8154 } = _ref; 8155 var size = optArgs[0]; 8156 var newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode"); 8157 return { 8158 type: "cr", 8159 mode: parser.mode, 8160 newLine, 8161 size: size && assertNodeType(size, "size").value 8162 }; 8163 }, 8164 8165 // The following builders are called only at the top level, 8166 // not within tabular/array environments. 8167 htmlBuilder(group, options) { 8168 var span = buildCommon.makeSpan(["mspace"], [], options); 8169 8170 if (group.newLine) { 8171 span.classes.push("newline"); 8172 8173 if (group.size) { 8174 span.style.marginTop = calculateSize(group.size, options) + "em"; 8175 } 8176 } 8177 8178 return span; 8179 }, 8180 8181 mathmlBuilder(group, options) { 8182 var node = new mathMLTree.MathNode("mspace"); 8183 8184 if (group.newLine) { 8185 node.setAttribute("linebreak", "newline"); 8186 8187 if (group.size) { 8188 node.setAttribute("height", calculateSize(group.size, options) + "em"); 8189 } 8190 } 8191 8192 return node; 8193 } 8194 8195 }); 8196 8197 var globalMap = { 8198 "\\global": "\\global", 8199 "\\long": "\\\\globallong", 8200 "\\\\globallong": "\\\\globallong", 8201 "\\def": "\\gdef", 8202 "\\gdef": "\\gdef", 8203 "\\edef": "\\xdef", 8204 "\\xdef": "\\xdef", 8205 "\\let": "\\\\globallet", 8206 "\\futurelet": "\\\\globalfuture" 8207 }; 8208 8209 var checkControlSequence = tok => { 8210 var name = tok.text; 8211 8212 if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { 8213 throw new ParseError("Expected a control sequence", tok); 8214 } 8215 8216 return name; 8217 }; 8218 8219 var getRHS = parser => { 8220 var tok = parser.gullet.popToken(); 8221 8222 if (tok.text === "=") { 8223 // consume optional equals 8224 tok = parser.gullet.popToken(); 8225 8226 if (tok.text === " ") { 8227 // consume one optional space 8228 tok = parser.gullet.popToken(); 8229 } 8230 } 8231 8232 return tok; 8233 }; 8234 8235 var letCommand = (parser, name, tok, global) => { 8236 var macro = parser.gullet.macros.get(tok.text); 8237 8238 if (macro == null) { 8239 // don't expand it later even if a macro with the same name is defined 8240 // e.g., \let\foo=\frac \def\frac{\relax} \frac12 8241 tok.noexpand = true; 8242 macro = { 8243 tokens: [tok], 8244 numArgs: 0, 8245 // reproduce the same behavior in expansion 8246 unexpandable: !parser.gullet.isExpandable(tok.text) 8247 }; 8248 } 8249 8250 parser.gullet.macros.set(name, macro, global); 8251 }; // <assignment> -> <non-macro assignment>|<macro assignment> 8252 // <non-macro assignment> -> <simple assignment>|\global<non-macro assignment> 8253 // <macro assignment> -> <definition>|<prefix><macro assignment> 8254 // <prefix> -> \global|\long|\outer 8255 8256 8257 defineFunction({ 8258 type: "internal", 8259 names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly 8260 ], 8261 props: { 8262 numArgs: 0, 8263 allowedInText: true 8264 }, 8265 8266 handler(_ref) { 8267 var { 8268 parser, 8269 funcName 8270 } = _ref; 8271 parser.consumeSpaces(); 8272 var token = parser.fetch(); 8273 8274 if (globalMap[token.text]) { 8275 // KaTeX doesn't have \par, so ignore \long 8276 if (funcName === "\\global" || funcName === "\\\\globallong") { 8277 token.text = globalMap[token.text]; 8278 } 8279 8280 return assertNodeType(parser.parseFunction(), "internal"); 8281 } 8282 8283 throw new ParseError("Invalid token after macro prefix", token); 8284 } 8285 8286 }); // Basic support for macro definitions: \def, \gdef, \edef, \xdef 8287 // <definition> -> <def><control sequence><definition text> 8288 // <def> -> \def|\gdef|\edef|\xdef 8289 // <definition text> -> <parameter text><left brace><balanced text><right brace> 8290 8291 defineFunction({ 8292 type: "internal", 8293 names: ["\\def", "\\gdef", "\\edef", "\\xdef"], 8294 props: { 8295 numArgs: 0, 8296 allowedInText: true, 8297 primitive: true 8298 }, 8299 8300 handler(_ref2) { 8301 var { 8302 parser, 8303 funcName 8304 } = _ref2; 8305 var tok = parser.gullet.popToken(); 8306 var name = tok.text; 8307 8308 if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { 8309 throw new ParseError("Expected a control sequence", tok); 8310 } 8311 8312 var numArgs = 0; 8313 var insert; 8314 var delimiters = [[]]; // <parameter text> contains no braces 8315 8316 while (parser.gullet.future().text !== "{") { 8317 tok = parser.gullet.popToken(); 8318 8319 if (tok.text === "#") { 8320 // If the very last character of the <parameter text> is #, so that 8321 // this # is immediately followed by {, TeX will behave as if the { 8322 // had been inserted at the right end of both the parameter text 8323 // and the replacement text. 8324 if (parser.gullet.future().text === "{") { 8325 insert = parser.gullet.future(); 8326 delimiters[numArgs].push("{"); 8327 break; 8328 } // A parameter, the first appearance of # must be followed by 1, 8329 // the next by 2, and so on; up to nine #’s are allowed 8330 8331 8332 tok = parser.gullet.popToken(); 8333 8334 if (!/^[1-9]$/.test(tok.text)) { 8335 throw new ParseError("Invalid argument number \"" + tok.text + "\""); 8336 } 8337 8338 if (parseInt(tok.text) !== numArgs + 1) { 8339 throw new ParseError("Argument number \"" + tok.text + "\" out of order"); 8340 } 8341 8342 numArgs++; 8343 delimiters.push([]); 8344 } else if (tok.text === "EOF") { 8345 throw new ParseError("Expected a macro definition"); 8346 } else { 8347 delimiters[numArgs].push(tok.text); 8348 } 8349 } // replacement text, enclosed in '{' and '}' and properly nested 8350 8351 8352 var { 8353 tokens 8354 } = parser.gullet.consumeArg(); 8355 8356 if (insert) { 8357 tokens.unshift(insert); 8358 } 8359 8360 if (funcName === "\\edef" || funcName === "\\xdef") { 8361 tokens = parser.gullet.expandTokens(tokens); 8362 tokens.reverse(); // to fit in with stack order 8363 } // Final arg is the expansion of the macro 8364 8365 8366 parser.gullet.macros.set(name, { 8367 tokens, 8368 numArgs, 8369 delimiters 8370 }, funcName === globalMap[funcName]); 8371 return { 8372 type: "internal", 8373 mode: parser.mode 8374 }; 8375 } 8376 8377 }); // <simple assignment> -> <let assignment> 8378 // <let assignment> -> \futurelet<control sequence><token><token> 8379 // | \let<control sequence><equals><one optional space><token> 8380 // <equals> -> <optional spaces>|<optional spaces>= 8381 8382 defineFunction({ 8383 type: "internal", 8384 names: ["\\let", "\\\\globallet" // can’t be entered directly 8385 ], 8386 props: { 8387 numArgs: 0, 8388 allowedInText: true, 8389 primitive: true 8390 }, 8391 8392 handler(_ref3) { 8393 var { 8394 parser, 8395 funcName 8396 } = _ref3; 8397 var name = checkControlSequence(parser.gullet.popToken()); 8398 parser.gullet.consumeSpaces(); 8399 var tok = getRHS(parser); 8400 letCommand(parser, name, tok, funcName === "\\\\globallet"); 8401 return { 8402 type: "internal", 8403 mode: parser.mode 8404 }; 8405 } 8406 8407 }); // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf 8408 8409 defineFunction({ 8410 type: "internal", 8411 names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly 8412 ], 8413 props: { 8414 numArgs: 0, 8415 allowedInText: true, 8416 primitive: true 8417 }, 8418 8419 handler(_ref4) { 8420 var { 8421 parser, 8422 funcName 8423 } = _ref4; 8424 var name = checkControlSequence(parser.gullet.popToken()); 8425 var middle = parser.gullet.popToken(); 8426 var tok = parser.gullet.popToken(); 8427 letCommand(parser, name, tok, funcName === "\\\\globalfuture"); 8428 parser.gullet.pushToken(tok); 8429 parser.gullet.pushToken(middle); 8430 return { 8431 type: "internal", 8432 mode: parser.mode 8433 }; 8434 } 8435 8436 }); 8437 8438 /** 8439 * This file deals with creating delimiters of various sizes. The TeXbook 8440 * discusses these routines on page 441-442, in the "Another subroutine sets box 8441 * x to a specified variable delimiter" paragraph. 8442 * 8443 * There are three main routines here. `makeSmallDelim` makes a delimiter in the 8444 * normal font, but in either text, script, or scriptscript style. 8445 * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1, 8446 * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of 8447 * smaller pieces that are stacked on top of one another. 8448 * 8449 * The functions take a parameter `center`, which determines if the delimiter 8450 * should be centered around the axis. 8451 * 8452 * Then, there are three exposed functions. `sizedDelim` makes a delimiter in 8453 * one of the given sizes. This is used for things like `\bigl`. 8454 * `customSizedDelim` makes a delimiter with a given total height+depth. It is 8455 * called in places like `\sqrt`. `leftRightDelim` makes an appropriate 8456 * delimiter which surrounds an expression of a given height an depth. It is 8457 * used in `\left` and `\right`. 8458 */ 8459 8460 /** 8461 * Get the metrics for a given symbol and font, after transformation (i.e. 8462 * after following replacement from symbols.js) 8463 */ 8464 var getMetrics = function getMetrics(symbol, font, mode) { 8465 var replace = symbols.math[symbol] && symbols.math[symbol].replace; 8466 var metrics = getCharacterMetrics(replace || symbol, font, mode); 8467 8468 if (!metrics) { 8469 throw new Error("Unsupported symbol " + symbol + " and font size " + font + "."); 8470 } 8471 8472 return metrics; 8473 }; 8474 /** 8475 * Puts a delimiter span in a given style, and adds appropriate height, depth, 8476 * and maxFontSizes. 8477 */ 8478 8479 8480 var styleWrap = function styleWrap(delim, toStyle, options, classes) { 8481 var newOptions = options.havingBaseStyle(toStyle); 8482 var span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options); 8483 var delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier; 8484 span.height *= delimSizeMultiplier; 8485 span.depth *= delimSizeMultiplier; 8486 span.maxFontSize = newOptions.sizeMultiplier; 8487 return span; 8488 }; 8489 8490 var centerSpan = function centerSpan(span, options, style) { 8491 var newOptions = options.havingBaseStyle(style); 8492 var shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight; 8493 span.classes.push("delimcenter"); 8494 span.style.top = shift + "em"; 8495 span.height -= shift; 8496 span.depth += shift; 8497 }; 8498 /** 8499 * Makes a small delimiter. This is a delimiter that comes in the Main-Regular 8500 * font, but is restyled to either be in textstyle, scriptstyle, or 8501 * scriptscriptstyle. 8502 */ 8503 8504 8505 var makeSmallDelim = function makeSmallDelim(delim, style, center, options, mode, classes) { 8506 var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options); 8507 var span = styleWrap(text, style, options, classes); 8508 8509 if (center) { 8510 centerSpan(span, options, style); 8511 } 8512 8513 return span; 8514 }; 8515 /** 8516 * Builds a symbol in the given font size (note size is an integer) 8517 */ 8518 8519 8520 var mathrmSize = function mathrmSize(value, size, mode, options) { 8521 return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options); 8522 }; 8523 /** 8524 * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2, 8525 * Size3, or Size4 fonts. It is always rendered in textstyle. 8526 */ 8527 8528 8529 var makeLargeDelim = function makeLargeDelim(delim, size, center, options, mode, classes) { 8530 var inner = mathrmSize(delim, size, mode, options); 8531 var span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), Style$1.TEXT, options, classes); 8532 8533 if (center) { 8534 centerSpan(span, options, Style$1.TEXT); 8535 } 8536 8537 return span; 8538 }; 8539 /** 8540 * Make a span from a font glyph with the given offset and in the given font. 8541 * This is used in makeStackedDelim to make the stacking pieces for the delimiter. 8542 */ 8543 8544 8545 var makeGlyphSpan = function makeGlyphSpan(symbol, font, mode) { 8546 var sizeClass; // Apply the correct CSS class to choose the right font. 8547 8548 if (font === "Size1-Regular") { 8549 sizeClass = "delim-size1"; 8550 } else 8551 /* if (font === "Size4-Regular") */ 8552 { 8553 sizeClass = "delim-size4"; 8554 } 8555 8556 var corner = buildCommon.makeSpan(["delimsizinginner", sizeClass], [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); // Since this will be passed into `makeVList` in the end, wrap the element 8557 // in the appropriate tag that VList uses. 8558 8559 return { 8560 type: "elem", 8561 elem: corner 8562 }; 8563 }; 8564 8565 var makeInner = function makeInner(ch, height, options) { 8566 // Create a span with inline SVG for the inner part of a tall stacked delimiter. 8567 var width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4].toFixed(3) : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4].toFixed(3); 8568 var path = new PathNode("inner", innerPath(ch, Math.round(1000 * height))); 8569 var svgNode = new SvgNode([path], { 8570 "width": width + "em", 8571 "height": height + "em", 8572 // Override CSS rule `.katex svg { width: 100% }` 8573 "style": "width:" + width + "em", 8574 "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height), 8575 "preserveAspectRatio": "xMinYMin" 8576 }); 8577 var span = buildCommon.makeSvgSpan([], [svgNode], options); 8578 span.height = height; 8579 span.style.height = height + "em"; 8580 span.style.width = width + "em"; 8581 return { 8582 type: "elem", 8583 elem: span 8584 }; 8585 }; // Helpers for makeStackedDelim 8586 8587 8588 var lapInEms = 0.008; 8589 var lap = { 8590 type: "kern", 8591 size: -1 * lapInEms 8592 }; 8593 var verts = ["|", "\\lvert", "\\rvert", "\\vert"]; 8594 var doubleVerts = ["\\|", "\\lVert", "\\rVert", "\\Vert"]; 8595 /** 8596 * Make a stacked delimiter out of a given delimiter, with the total height at 8597 * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook. 8598 */ 8599 8600 var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, options, mode, classes) { 8601 // There are four parts, the top, an optional middle, a repeated part, and a 8602 // bottom. 8603 var top; 8604 var middle; 8605 var repeat; 8606 var bottom; 8607 top = repeat = bottom = delim; 8608 middle = null; // Also keep track of what font the delimiters are in 8609 8610 var font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use 8611 // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the 8612 // repeats of the arrows 8613 8614 if (delim === "\\uparrow") { 8615 repeat = bottom = "\u23d0"; 8616 } else if (delim === "\\Uparrow") { 8617 repeat = bottom = "\u2016"; 8618 } else if (delim === "\\downarrow") { 8619 top = repeat = "\u23d0"; 8620 } else if (delim === "\\Downarrow") { 8621 top = repeat = "\u2016"; 8622 } else if (delim === "\\updownarrow") { 8623 top = "\\uparrow"; 8624 repeat = "\u23d0"; 8625 bottom = "\\downarrow"; 8626 } else if (delim === "\\Updownarrow") { 8627 top = "\\Uparrow"; 8628 repeat = "\u2016"; 8629 bottom = "\\Downarrow"; 8630 } else if (utils.contains(verts, delim)) { 8631 repeat = "\u2223"; 8632 } else if (utils.contains(doubleVerts, delim)) { 8633 repeat = "\u2225"; 8634 } else if (delim === "[" || delim === "\\lbrack") { 8635 top = "\u23a1"; 8636 repeat = "\u23a2"; 8637 bottom = "\u23a3"; 8638 font = "Size4-Regular"; 8639 } else if (delim === "]" || delim === "\\rbrack") { 8640 top = "\u23a4"; 8641 repeat = "\u23a5"; 8642 bottom = "\u23a6"; 8643 font = "Size4-Regular"; 8644 } else if (delim === "\\lfloor" || delim === "\u230a") { 8645 repeat = top = "\u23a2"; 8646 bottom = "\u23a3"; 8647 font = "Size4-Regular"; 8648 } else if (delim === "\\lceil" || delim === "\u2308") { 8649 top = "\u23a1"; 8650 repeat = bottom = "\u23a2"; 8651 font = "Size4-Regular"; 8652 } else if (delim === "\\rfloor" || delim === "\u230b") { 8653 repeat = top = "\u23a5"; 8654 bottom = "\u23a6"; 8655 font = "Size4-Regular"; 8656 } else if (delim === "\\rceil" || delim === "\u2309") { 8657 top = "\u23a4"; 8658 repeat = bottom = "\u23a5"; 8659 font = "Size4-Regular"; 8660 } else if (delim === "(" || delim === "\\lparen") { 8661 top = "\u239b"; 8662 repeat = "\u239c"; 8663 bottom = "\u239d"; 8664 font = "Size4-Regular"; 8665 } else if (delim === ")" || delim === "\\rparen") { 8666 top = "\u239e"; 8667 repeat = "\u239f"; 8668 bottom = "\u23a0"; 8669 font = "Size4-Regular"; 8670 } else if (delim === "\\{" || delim === "\\lbrace") { 8671 top = "\u23a7"; 8672 middle = "\u23a8"; 8673 bottom = "\u23a9"; 8674 repeat = "\u23aa"; 8675 font = "Size4-Regular"; 8676 } else if (delim === "\\}" || delim === "\\rbrace") { 8677 top = "\u23ab"; 8678 middle = "\u23ac"; 8679 bottom = "\u23ad"; 8680 repeat = "\u23aa"; 8681 font = "Size4-Regular"; 8682 } else if (delim === "\\lgroup" || delim === "\u27ee") { 8683 top = "\u23a7"; 8684 bottom = "\u23a9"; 8685 repeat = "\u23aa"; 8686 font = "Size4-Regular"; 8687 } else if (delim === "\\rgroup" || delim === "\u27ef") { 8688 top = "\u23ab"; 8689 bottom = "\u23ad"; 8690 repeat = "\u23aa"; 8691 font = "Size4-Regular"; 8692 } else if (delim === "\\lmoustache" || delim === "\u23b0") { 8693 top = "\u23a7"; 8694 bottom = "\u23ad"; 8695 repeat = "\u23aa"; 8696 font = "Size4-Regular"; 8697 } else if (delim === "\\rmoustache" || delim === "\u23b1") { 8698 top = "\u23ab"; 8699 bottom = "\u23a9"; 8700 repeat = "\u23aa"; 8701 font = "Size4-Regular"; 8702 } // Get the metrics of the four sections 8703 8704 8705 var topMetrics = getMetrics(top, font, mode); 8706 var topHeightTotal = topMetrics.height + topMetrics.depth; 8707 var repeatMetrics = getMetrics(repeat, font, mode); 8708 var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; 8709 var bottomMetrics = getMetrics(bottom, font, mode); 8710 var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; 8711 var middleHeightTotal = 0; 8712 var middleFactor = 1; 8713 8714 if (middle !== null) { 8715 var middleMetrics = getMetrics(middle, font, mode); 8716 middleHeightTotal = middleMetrics.height + middleMetrics.depth; 8717 middleFactor = 2; // repeat symmetrically above and below middle 8718 } // Calcuate the minimal height that the delimiter can have. 8719 // It is at least the size of the top, bottom, and optional middle combined. 8720 8721 8722 var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need 8723 8724 var repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols 8725 8726 var realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note 8727 // that in this context, "center" means that the delimiter should be 8728 // centered around the axis in the current style, while normally it is 8729 // centered around the axis in textstyle. 8730 8731 var axisHeight = options.fontMetrics().axisHeight; 8732 8733 if (center) { 8734 axisHeight *= options.sizeMultiplier; 8735 } // Calculate the depth 8736 8737 8738 var depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist 8739 // Keep a list of the pieces of the stacked delimiter 8740 8741 var stack = []; // Add the bottom symbol 8742 8743 stack.push(makeGlyphSpan(bottom, font, mode)); 8744 stack.push(lap); // overlap 8745 8746 if (middle === null) { 8747 // The middle section will be an SVG. Make it an extra 0.016em tall. 8748 // We'll overlap by 0.008em at top and bottom. 8749 var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms; 8750 stack.push(makeInner(repeat, innerHeight, options)); 8751 } else { 8752 // When there is a middle bit, we need the middle part and two repeated 8753 // sections 8754 var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms; 8755 8756 stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace. 8757 8758 stack.push(lap); 8759 stack.push(makeGlyphSpan(middle, font, mode)); 8760 stack.push(lap); 8761 stack.push(makeInner(repeat, _innerHeight, options)); 8762 } // Add the top symbol 8763 8764 8765 stack.push(lap); 8766 stack.push(makeGlyphSpan(top, font, mode)); // Finally, build the vlist 8767 8768 var newOptions = options.havingBaseStyle(Style$1.TEXT); 8769 var inner = buildCommon.makeVList({ 8770 positionType: "bottom", 8771 positionData: depth, 8772 children: stack 8773 }, newOptions); 8774 return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), Style$1.TEXT, options, classes); 8775 }; // All surds have 0.08em padding above the viniculum inside the SVG. 8776 // That keeps browser span height rounding error from pinching the line. 8777 8778 8779 var vbPad = 80; // padding above the surd, measured inside the viewBox. 8780 8781 var emPad = 0.08; // padding, in ems, measured in the document. 8782 8783 var sqrtSvg = function sqrtSvg(sqrtName, height, viewBoxHeight, extraViniculum, options) { 8784 var path = sqrtPath(sqrtName, extraViniculum, viewBoxHeight); 8785 var pathNode = new PathNode(sqrtName, path); 8786 var svg = new SvgNode([pathNode], { 8787 // Note: 1000:1 ratio of viewBox to document em width. 8788 "width": "400em", 8789 "height": height + "em", 8790 "viewBox": "0 0 400000 " + viewBoxHeight, 8791 "preserveAspectRatio": "xMinYMin slice" 8792 }); 8793 return buildCommon.makeSvgSpan(["hide-tail"], [svg], options); 8794 }; 8795 /** 8796 * Make a sqrt image of the given height, 8797 */ 8798 8799 8800 var makeSqrtImage = function makeSqrtImage(height, options) { 8801 // Define a newOptions that removes the effect of size changes such as \Huge. 8802 // We don't pick different a height surd for \Huge. For it, we scale up. 8803 var newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds. 8804 8805 var delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions); 8806 var sizeMultiplier = newOptions.sizeMultiplier; // default 8807 // The standard sqrt SVGs each have a 0.04em thick viniculum. 8808 // If Settings.minRuleThickness is larger than that, we add extraViniculum. 8809 8810 var extraViniculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol. 8811 8812 var span; 8813 var spanHeight = 0; 8814 var texHeight = 0; 8815 var viewBoxHeight = 0; 8816 var advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd. 8817 // Then browser rounding error on the parent span height will not 8818 // encroach on the ink of the viniculum. But that padding is not 8819 // included in the TeX-like `height` used for calculation of 8820 // vertical alignment. So texHeight = span.height < span.style.height. 8821 8822 if (delim.type === "small") { 8823 // Get an SVG that is derived from glyph U+221A in font KaTeX-Main. 8824 // 1000 unit normal glyph height. 8825 viewBoxHeight = 1000 + 1000 * extraViniculum + vbPad; 8826 8827 if (height < 1.0) { 8828 sizeMultiplier = 1.0; // mimic a \textfont radical 8829 } else if (height < 1.4) { 8830 sizeMultiplier = 0.7; // mimic a \scriptfont radical 8831 } 8832 8833 spanHeight = (1.0 + extraViniculum + emPad) / sizeMultiplier; 8834 texHeight = (1.00 + extraViniculum) / sizeMultiplier; 8835 span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraViniculum, options); 8836 span.style.minWidth = "0.853em"; 8837 advanceWidth = 0.833 / sizeMultiplier; // from the font. 8838 } else if (delim.type === "large") { 8839 // These SVGs come from fonts: KaTeX_Size1, _Size2, etc. 8840 viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size]; 8841 texHeight = (sizeToMaxHeight[delim.size] + extraViniculum) / sizeMultiplier; 8842 spanHeight = (sizeToMaxHeight[delim.size] + extraViniculum + emPad) / sizeMultiplier; 8843 span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraViniculum, options); 8844 span.style.minWidth = "1.02em"; 8845 advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font. 8846 } else { 8847 // Tall sqrt. In TeX, this would be stacked using multiple glyphs. 8848 // We'll use a single SVG to accomplish the same thing. 8849 spanHeight = height + extraViniculum + emPad; 8850 texHeight = height + extraViniculum; 8851 viewBoxHeight = Math.floor(1000 * height + extraViniculum) + vbPad; 8852 span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraViniculum, options); 8853 span.style.minWidth = "0.742em"; 8854 advanceWidth = 1.056; 8855 } 8856 8857 span.height = texHeight; 8858 span.style.height = spanHeight + "em"; 8859 return { 8860 span, 8861 advanceWidth, 8862 // Calculate the actual line width. 8863 // This actually should depend on the chosen font -- e.g. \boldmath 8864 // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and 8865 // have thicker rules. 8866 ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraViniculum) * sizeMultiplier 8867 }; 8868 }; // There are three kinds of delimiters, delimiters that stack when they become 8869 // too large 8870 8871 8872 var stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack 8873 8874 var stackAlwaysDelimiters = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"]; // and delimiters that never stack 8875 8876 var stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of 8877 // $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ 8878 // Used to create stacked delimiters of appropriate sizes in makeSizedDelim. 8879 8880 var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; 8881 /** 8882 * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4. 8883 */ 8884 8885 var makeSizedDelim = function makeSizedDelim(delim, size, options, mode, classes) { 8886 // < and > turn into \langle and \rangle in delimiters 8887 if (delim === "<" || delim === "\\lt" || delim === "\u27e8") { 8888 delim = "\\langle"; 8889 } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") { 8890 delim = "\\rangle"; 8891 } // Sized delimiters are never centered. 8892 8893 8894 if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) { 8895 return makeLargeDelim(delim, size, false, options, mode, classes); 8896 } else if (utils.contains(stackAlwaysDelimiters, delim)) { 8897 return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes); 8898 } else { 8899 throw new ParseError("Illegal delimiter: '" + delim + "'"); 8900 } 8901 }; 8902 /** 8903 * There are three different sequences of delimiter sizes that the delimiters 8904 * follow depending on the kind of delimiter. This is used when creating custom 8905 * sized delimiters to decide whether to create a small, large, or stacked 8906 * delimiter. 8907 * 8908 * In real TeX, these sequences aren't explicitly defined, but are instead 8909 * defined inside the font metrics. Since there are only three sequences that 8910 * are possible for the delimiters that TeX defines, it is easier to just encode 8911 * them explicitly here. 8912 */ 8913 8914 8915 // Delimiters that never stack try small delimiters and large delimiters only 8916 var stackNeverDelimiterSequence = [{ 8917 type: "small", 8918 style: Style$1.SCRIPTSCRIPT 8919 }, { 8920 type: "small", 8921 style: Style$1.SCRIPT 8922 }, { 8923 type: "small", 8924 style: Style$1.TEXT 8925 }, { 8926 type: "large", 8927 size: 1 8928 }, { 8929 type: "large", 8930 size: 2 8931 }, { 8932 type: "large", 8933 size: 3 8934 }, { 8935 type: "large", 8936 size: 4 8937 }]; // Delimiters that always stack try the small delimiters first, then stack 8938 8939 var stackAlwaysDelimiterSequence = [{ 8940 type: "small", 8941 style: Style$1.SCRIPTSCRIPT 8942 }, { 8943 type: "small", 8944 style: Style$1.SCRIPT 8945 }, { 8946 type: "small", 8947 style: Style$1.TEXT 8948 }, { 8949 type: "stack" 8950 }]; // Delimiters that stack when large try the small and then large delimiters, and 8951 // stack afterwards 8952 8953 var stackLargeDelimiterSequence = [{ 8954 type: "small", 8955 style: Style$1.SCRIPTSCRIPT 8956 }, { 8957 type: "small", 8958 style: Style$1.SCRIPT 8959 }, { 8960 type: "small", 8961 style: Style$1.TEXT 8962 }, { 8963 type: "large", 8964 size: 1 8965 }, { 8966 type: "large", 8967 size: 2 8968 }, { 8969 type: "large", 8970 size: 3 8971 }, { 8972 type: "large", 8973 size: 4 8974 }, { 8975 type: "stack" 8976 }]; 8977 /** 8978 * Get the font used in a delimiter based on what kind of delimiter it is. 8979 * TODO(#963) Use more specific font family return type once that is introduced. 8980 */ 8981 8982 var delimTypeToFont = function delimTypeToFont(type) { 8983 if (type.type === "small") { 8984 return "Main-Regular"; 8985 } else if (type.type === "large") { 8986 return "Size" + type.size + "-Regular"; 8987 } else if (type.type === "stack") { 8988 return "Size4-Regular"; 8989 } else { 8990 throw new Error("Add support for delim type '" + type.type + "' here."); 8991 } 8992 }; 8993 /** 8994 * Traverse a sequence of types of delimiters to decide what kind of delimiter 8995 * should be used to create a delimiter of the given height+depth. 8996 */ 8997 8998 8999 var traverseSequence = function traverseSequence(delim, height, sequence, options) { 9000 // Here, we choose the index we should start at in the sequences. In smaller 9001 // sizes (which correspond to larger numbers in style.size) we start earlier 9002 // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts 9003 // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2 9004 var start = Math.min(2, 3 - options.style.size); 9005 9006 for (var i = start; i < sequence.length; i++) { 9007 if (sequence[i].type === "stack") { 9008 // This is always the last delimiter, so we just break the loop now. 9009 break; 9010 } 9011 9012 var metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math"); 9013 var heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we 9014 // account for the style change size. 9015 9016 if (sequence[i].type === "small") { 9017 var newOptions = options.havingBaseStyle(sequence[i].style); 9018 heightDepth *= newOptions.sizeMultiplier; 9019 } // Check if the delimiter at this size works for the given height. 9020 9021 9022 if (heightDepth > height) { 9023 return sequence[i]; 9024 } 9025 } // If we reached the end of the sequence, return the last sequence element. 9026 9027 9028 return sequence[sequence.length - 1]; 9029 }; 9030 /** 9031 * Make a delimiter of a given height+depth, with optional centering. Here, we 9032 * traverse the sequences, and create a delimiter that the sequence tells us to. 9033 */ 9034 9035 9036 var makeCustomSizedDelim = function makeCustomSizedDelim(delim, height, center, options, mode, classes) { 9037 if (delim === "<" || delim === "\\lt" || delim === "\u27e8") { 9038 delim = "\\langle"; 9039 } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") { 9040 delim = "\\rangle"; 9041 } // Decide what sequence to use 9042 9043 9044 var sequence; 9045 9046 if (utils.contains(stackNeverDelimiters, delim)) { 9047 sequence = stackNeverDelimiterSequence; 9048 } else if (utils.contains(stackLargeDelimiters, delim)) { 9049 sequence = stackLargeDelimiterSequence; 9050 } else { 9051 sequence = stackAlwaysDelimiterSequence; 9052 } // Look through the sequence 9053 9054 9055 var delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs. 9056 // Depending on the sequence element we decided on, call the 9057 // appropriate function. 9058 9059 if (delimType.type === "small") { 9060 return makeSmallDelim(delim, delimType.style, center, options, mode, classes); 9061 } else if (delimType.type === "large") { 9062 return makeLargeDelim(delim, delimType.size, center, options, mode, classes); 9063 } else 9064 /* if (delimType.type === "stack") */ 9065 { 9066 return makeStackedDelim(delim, height, center, options, mode, classes); 9067 } 9068 }; 9069 /** 9070 * Make a delimiter for use with `\left` and `\right`, given a height and depth 9071 * of an expression that the delimiters surround. 9072 */ 9073 9074 9075 var makeLeftRightDelim = function makeLeftRightDelim(delim, height, depth, options, mode, classes) { 9076 // We always center \left/\right delimiters, so the axis is always shifted 9077 var axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right 9078 9079 var delimiterFactor = 901; 9080 var delimiterExtend = 5.0 / options.fontMetrics().ptPerEm; 9081 var maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight); 9082 var totalHeight = Math.max( // In real TeX, calculations are done using integral values which are 9083 // 65536 per pt, or 655360 per em. So, the division here truncates in 9084 // TeX but doesn't here, producing different results. If we wanted to 9085 // exactly match TeX's calculation, we could do 9086 // Math.floor(655360 * maxDistFromAxis / 500) * 9087 // delimiterFactor / 655360 9088 // (To see the difference, compare 9089 // x^{x^{\left(\rule{0.1em}{0.68em}\right)}} 9090 // in TeX and KaTeX) 9091 maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total 9092 // height 9093 9094 return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes); 9095 }; 9096 9097 var delimiter = { 9098 sqrtImage: makeSqrtImage, 9099 sizedDelim: makeSizedDelim, 9100 sizeToMaxHeight: sizeToMaxHeight, 9101 customSizedDelim: makeCustomSizedDelim, 9102 leftRightDelim: makeLeftRightDelim 9103 }; 9104 9105 // Extra data needed for the delimiter handler down below 9106 var delimiterSizes = { 9107 "\\bigl": { 9108 mclass: "mopen", 9109 size: 1 9110 }, 9111 "\\Bigl": { 9112 mclass: "mopen", 9113 size: 2 9114 }, 9115 "\\biggl": { 9116 mclass: "mopen", 9117 size: 3 9118 }, 9119 "\\Biggl": { 9120 mclass: "mopen", 9121 size: 4 9122 }, 9123 "\\bigr": { 9124 mclass: "mclose", 9125 size: 1 9126 }, 9127 "\\Bigr": { 9128 mclass: "mclose", 9129 size: 2 9130 }, 9131 "\\biggr": { 9132 mclass: "mclose", 9133 size: 3 9134 }, 9135 "\\Biggr": { 9136 mclass: "mclose", 9137 size: 4 9138 }, 9139 "\\bigm": { 9140 mclass: "mrel", 9141 size: 1 9142 }, 9143 "\\Bigm": { 9144 mclass: "mrel", 9145 size: 2 9146 }, 9147 "\\biggm": { 9148 mclass: "mrel", 9149 size: 3 9150 }, 9151 "\\Biggm": { 9152 mclass: "mrel", 9153 size: 4 9154 }, 9155 "\\big": { 9156 mclass: "mord", 9157 size: 1 9158 }, 9159 "\\Big": { 9160 mclass: "mord", 9161 size: 2 9162 }, 9163 "\\bigg": { 9164 mclass: "mord", 9165 size: 3 9166 }, 9167 "\\Bigg": { 9168 mclass: "mord", 9169 size: 4 9170 } 9171 }; 9172 var delimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]; 9173 9174 // Delimiter functions 9175 function checkDelimiter(delim, context) { 9176 var symDelim = checkSymbolNodeType(delim); 9177 9178 if (symDelim && utils.contains(delimiters, symDelim.text)) { 9179 return symDelim; 9180 } else if (symDelim) { 9181 throw new ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim); 9182 } else { 9183 throw new ParseError("Invalid delimiter type '" + delim.type + "'", delim); 9184 } 9185 } 9186 9187 defineFunction({ 9188 type: "delimsizing", 9189 names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"], 9190 props: { 9191 numArgs: 1, 9192 argTypes: ["primitive"] 9193 }, 9194 handler: (context, args) => { 9195 var delim = checkDelimiter(args[0], context); 9196 return { 9197 type: "delimsizing", 9198 mode: context.parser.mode, 9199 size: delimiterSizes[context.funcName].size, 9200 mclass: delimiterSizes[context.funcName].mclass, 9201 delim: delim.text 9202 }; 9203 }, 9204 htmlBuilder: (group, options) => { 9205 if (group.delim === ".") { 9206 // Empty delimiters still count as elements, even though they don't 9207 // show anything. 9208 return buildCommon.makeSpan([group.mclass]); 9209 } // Use delimiter.sizedDelim to generate the delimiter. 9210 9211 9212 return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]); 9213 }, 9214 mathmlBuilder: group => { 9215 var children = []; 9216 9217 if (group.delim !== ".") { 9218 children.push(makeText(group.delim, group.mode)); 9219 } 9220 9221 var node = new mathMLTree.MathNode("mo", children); 9222 9223 if (group.mclass === "mopen" || group.mclass === "mclose") { 9224 // Only some of the delimsizing functions act as fences, and they 9225 // return "mopen" or "mclose" mclass. 9226 node.setAttribute("fence", "true"); 9227 } else { 9228 // Explicitly disable fencing if it's not a fence, to override the 9229 // defaults. 9230 node.setAttribute("fence", "false"); 9231 } 9232 9233 node.setAttribute("stretchy", "true"); 9234 node.setAttribute("minsize", delimiter.sizeToMaxHeight[group.size] + "em"); 9235 node.setAttribute("maxsize", delimiter.sizeToMaxHeight[group.size] + "em"); 9236 return node; 9237 } 9238 }); 9239 9240 function assertParsed(group) { 9241 if (!group.body) { 9242 throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); 9243 } 9244 } 9245 9246 defineFunction({ 9247 type: "leftright-right", 9248 names: ["\\right"], 9249 props: { 9250 numArgs: 1, 9251 primitive: true 9252 }, 9253 handler: (context, args) => { 9254 // \left case below triggers parsing of \right in 9255 // `const right = parser.parseFunction();` 9256 // uses this return value. 9257 var color = context.parser.gullet.macros.get("\\current@color"); 9258 9259 if (color && typeof color !== "string") { 9260 throw new ParseError("\\current@color set to non-string in \\right"); 9261 } 9262 9263 return { 9264 type: "leftright-right", 9265 mode: context.parser.mode, 9266 delim: checkDelimiter(args[0], context).text, 9267 color // undefined if not set via \color 9268 9269 }; 9270 } 9271 }); 9272 defineFunction({ 9273 type: "leftright", 9274 names: ["\\left"], 9275 props: { 9276 numArgs: 1, 9277 primitive: true 9278 }, 9279 handler: (context, args) => { 9280 var delim = checkDelimiter(args[0], context); 9281 var parser = context.parser; // Parse out the implicit body 9282 9283 ++parser.leftrightDepth; // parseExpression stops before '\\right' 9284 9285 var body = parser.parseExpression(false); 9286 --parser.leftrightDepth; // Check the next token 9287 9288 parser.expect("\\right", false); 9289 var right = assertNodeType(parser.parseFunction(), "leftright-right"); 9290 return { 9291 type: "leftright", 9292 mode: parser.mode, 9293 body, 9294 left: delim.text, 9295 right: right.delim, 9296 rightColor: right.color 9297 }; 9298 }, 9299 htmlBuilder: (group, options) => { 9300 assertParsed(group); // Build the inner expression 9301 9302 var inner = buildExpression(group.body, options, true, ["mopen", "mclose"]); 9303 var innerHeight = 0; 9304 var innerDepth = 0; 9305 var hadMiddle = false; // Calculate its height and depth 9306 9307 for (var i = 0; i < inner.length; i++) { 9308 // Property `isMiddle` not defined on `span`. See comment in 9309 // "middle"'s htmlBuilder. 9310 // $FlowFixMe 9311 if (inner[i].isMiddle) { 9312 hadMiddle = true; 9313 } else { 9314 innerHeight = Math.max(inner[i].height, innerHeight); 9315 innerDepth = Math.max(inner[i].depth, innerDepth); 9316 } 9317 } // The size of delimiters is the same, regardless of what style we are 9318 // in. Thus, to correctly calculate the size of delimiter we need around 9319 // a group, we scale down the inner size based on the size. 9320 9321 9322 innerHeight *= options.sizeMultiplier; 9323 innerDepth *= options.sizeMultiplier; 9324 var leftDelim; 9325 9326 if (group.left === ".") { 9327 // Empty delimiters in \left and \right make null delimiter spaces. 9328 leftDelim = makeNullDelimiter(options, ["mopen"]); 9329 } else { 9330 // Otherwise, use leftRightDelim to generate the correct sized 9331 // delimiter. 9332 leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]); 9333 } // Add it to the beginning of the expression 9334 9335 9336 inner.unshift(leftDelim); // Handle middle delimiters 9337 9338 if (hadMiddle) { 9339 for (var _i = 1; _i < inner.length; _i++) { 9340 var middleDelim = inner[_i]; // Property `isMiddle` not defined on `span`. See comment in 9341 // "middle"'s htmlBuilder. 9342 // $FlowFixMe 9343 9344 var isMiddle = middleDelim.isMiddle; 9345 9346 if (isMiddle) { 9347 // Apply the options that were active when \middle was called 9348 inner[_i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []); 9349 } 9350 } 9351 } 9352 9353 var rightDelim; // Same for the right delimiter, but using color specified by \color 9354 9355 if (group.right === ".") { 9356 rightDelim = makeNullDelimiter(options, ["mclose"]); 9357 } else { 9358 var colorOptions = group.rightColor ? options.withColor(group.rightColor) : options; 9359 rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]); 9360 } // Add it to the end of the expression. 9361 9362 9363 inner.push(rightDelim); 9364 return buildCommon.makeSpan(["minner"], inner, options); 9365 }, 9366 mathmlBuilder: (group, options) => { 9367 assertParsed(group); 9368 var inner = buildExpression$1(group.body, options); 9369 9370 if (group.left !== ".") { 9371 var leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); 9372 leftNode.setAttribute("fence", "true"); 9373 inner.unshift(leftNode); 9374 } 9375 9376 if (group.right !== ".") { 9377 var rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); 9378 rightNode.setAttribute("fence", "true"); 9379 9380 if (group.rightColor) { 9381 rightNode.setAttribute("mathcolor", group.rightColor); 9382 } 9383 9384 inner.push(rightNode); 9385 } 9386 9387 return makeRow(inner); 9388 } 9389 }); 9390 defineFunction({ 9391 type: "middle", 9392 names: ["\\middle"], 9393 props: { 9394 numArgs: 1, 9395 primitive: true 9396 }, 9397 handler: (context, args) => { 9398 var delim = checkDelimiter(args[0], context); 9399 9400 if (!context.parser.leftrightDepth) { 9401 throw new ParseError("\\middle without preceding \\left", delim); 9402 } 9403 9404 return { 9405 type: "middle", 9406 mode: context.parser.mode, 9407 delim: delim.text 9408 }; 9409 }, 9410 htmlBuilder: (group, options) => { 9411 var middleDelim; 9412 9413 if (group.delim === ".") { 9414 middleDelim = makeNullDelimiter(options, []); 9415 } else { 9416 middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []); 9417 var isMiddle = { 9418 delim: group.delim, 9419 options 9420 }; // Property `isMiddle` not defined on `span`. It is only used in 9421 // this file above. 9422 // TODO: Fix this violation of the `span` type and possibly rename 9423 // things since `isMiddle` sounds like a boolean, but is a struct. 9424 // $FlowFixMe 9425 9426 middleDelim.isMiddle = isMiddle; 9427 } 9428 9429 return middleDelim; 9430 }, 9431 mathmlBuilder: (group, options) => { 9432 // A Firefox \middle will strech a character vertically only if it 9433 // is in the fence part of the operator dictionary at: 9434 // https://www.w3.org/TR/MathML3/appendixc.html. 9435 // So we need to avoid U+2223 and use plain "|" instead. 9436 var textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode); 9437 var middleNode = new mathMLTree.MathNode("mo", [textNode]); 9438 middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each <mo> element. 9439 // \middle should get delimiter spacing instead. 9440 9441 middleNode.setAttribute("lspace", "0.05em"); 9442 middleNode.setAttribute("rspace", "0.05em"); 9443 return middleNode; 9444 } 9445 }); 9446 9447 var htmlBuilder$2 = (group, options) => { 9448 // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase 9449 // Some groups can return document fragments. Handle those by wrapping 9450 // them in a span. 9451 var inner = buildCommon.wrapFragment(buildGroup(group.body, options), options); 9452 var label = group.label.substr(1); 9453 var scale = options.sizeMultiplier; 9454 var img; 9455 var imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different 9456 // depending on whether the subject is wider than it is tall, or vice versa. 9457 // We don't know the width of a group, so as a proxy, we test if 9458 // the subject is a single character. This captures most of the 9459 // subjects that should get the "tall" treatment. 9460 9461 var isSingleChar = utils.isCharacterBox(group.body); 9462 9463 if (label === "sout") { 9464 img = buildCommon.makeSpan(["stretchy", "sout"]); 9465 img.height = options.fontMetrics().defaultRuleThickness / scale; 9466 imgShift = -0.5 * options.fontMetrics().xHeight; 9467 } else if (label === "phase") { 9468 // Set a couple of dimensions from the steinmetz package. 9469 var lineWeight = calculateSize({ 9470 number: 0.6, 9471 unit: "pt" 9472 }, options); 9473 var clearance = calculateSize({ 9474 number: 0.35, 9475 unit: "ex" 9476 }, options); // Prevent size changes like \Huge from affecting line thickness 9477 9478 var newOptions = options.havingBaseSizing(); 9479 scale = scale / newOptions.sizeMultiplier; 9480 var angleHeight = inner.height + inner.depth + lineWeight + clearance; // Reserve a left pad for the angle. 9481 9482 inner.style.paddingLeft = angleHeight / 2 + lineWeight + "em"; // Create an SVG 9483 9484 var viewBoxHeight = Math.floor(1000 * angleHeight * scale); 9485 var path = phasePath(viewBoxHeight); 9486 var svgNode = new SvgNode([new PathNode("phase", path)], { 9487 "width": "400em", 9488 "height": viewBoxHeight / 1000 + "em", 9489 "viewBox": "0 0 400000 " + viewBoxHeight, 9490 "preserveAspectRatio": "xMinYMin slice" 9491 }); // Wrap it in a span with overflow: hidden. 9492 9493 img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options); 9494 img.style.height = angleHeight + "em"; 9495 imgShift = inner.depth + lineWeight + clearance; 9496 } else { 9497 // Add horizontal padding 9498 if (/cancel/.test(label)) { 9499 if (!isSingleChar) { 9500 inner.classes.push("cancel-pad"); 9501 } 9502 } else if (label === "angl") { 9503 inner.classes.push("anglpad"); 9504 } else { 9505 inner.classes.push("boxpad"); 9506 } // Add vertical padding 9507 9508 9509 var topPad = 0; 9510 var bottomPad = 0; 9511 var ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2" 9512 9513 if (/box/.test(label)) { 9514 ruleThickness = Math.max(options.fontMetrics().fboxrule, // default 9515 options.minRuleThickness // User override. 9516 ); 9517 topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness); 9518 bottomPad = topPad; 9519 } else if (label === "angl") { 9520 ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness); 9521 topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself. 9522 9523 bottomPad = Math.max(0, 0.25 - inner.depth); 9524 } else { 9525 topPad = isSingleChar ? 0.2 : 0; 9526 bottomPad = topPad; 9527 } 9528 9529 img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options); 9530 9531 if (/fbox|boxed|fcolorbox/.test(label)) { 9532 img.style.borderStyle = "solid"; 9533 img.style.borderWidth = ruleThickness + "em"; 9534 } else if (label === "angl" && ruleThickness !== 0.049) { 9535 img.style.borderTopWidth = ruleThickness + "em"; 9536 img.style.borderRightWidth = ruleThickness + "em"; 9537 } 9538 9539 imgShift = inner.depth + bottomPad; 9540 9541 if (group.backgroundColor) { 9542 img.style.backgroundColor = group.backgroundColor; 9543 9544 if (group.borderColor) { 9545 img.style.borderColor = group.borderColor; 9546 } 9547 } 9548 } 9549 9550 var vlist; 9551 9552 if (group.backgroundColor) { 9553 vlist = buildCommon.makeVList({ 9554 positionType: "individualShift", 9555 children: [// Put the color background behind inner; 9556 { 9557 type: "elem", 9558 elem: img, 9559 shift: imgShift 9560 }, { 9561 type: "elem", 9562 elem: inner, 9563 shift: 0 9564 }] 9565 }, options); 9566 } else { 9567 var classes = /cancel|phase/.test(label) ? ["svg-align"] : []; 9568 vlist = buildCommon.makeVList({ 9569 positionType: "individualShift", 9570 children: [// Write the \cancel stroke on top of inner. 9571 { 9572 type: "elem", 9573 elem: inner, 9574 shift: 0 9575 }, { 9576 type: "elem", 9577 elem: img, 9578 shift: imgShift, 9579 wrapperClasses: classes 9580 }] 9581 }, options); 9582 } 9583 9584 if (/cancel/.test(label)) { 9585 // The cancel package documentation says that cancel lines add their height 9586 // to the expression, but tests show that isn't how it actually works. 9587 vlist.height = inner.height; 9588 vlist.depth = inner.depth; 9589 } 9590 9591 if (/cancel/.test(label) && !isSingleChar) { 9592 // cancel does not create horiz space for its line extension. 9593 return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options); 9594 } else { 9595 return buildCommon.makeSpan(["mord"], [vlist], options); 9596 } 9597 }; 9598 9599 var mathmlBuilder$2 = (group, options) => { 9600 var fboxsep = 0; 9601 var node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup$1(group.body, options)]); 9602 9603 switch (group.label) { 9604 case "\\cancel": 9605 node.setAttribute("notation", "updiagonalstrike"); 9606 break; 9607 9608 case "\\bcancel": 9609 node.setAttribute("notation", "downdiagonalstrike"); 9610 break; 9611 9612 case "\\phase": 9613 node.setAttribute("notation", "phasorangle"); 9614 break; 9615 9616 case "\\sout": 9617 node.setAttribute("notation", "horizontalstrike"); 9618 break; 9619 9620 case "\\fbox": 9621 node.setAttribute("notation", "box"); 9622 break; 9623 9624 case "\\angl": 9625 node.setAttribute("notation", "actuarial"); 9626 break; 9627 9628 case "\\fcolorbox": 9629 case "\\colorbox": 9630 // <menclose> doesn't have a good notation option. So use <mpadded> 9631 // instead. Set some attributes that come included with <menclose>. 9632 fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm; 9633 node.setAttribute("width", "+" + 2 * fboxsep + "pt"); 9634 node.setAttribute("height", "+" + 2 * fboxsep + "pt"); 9635 node.setAttribute("lspace", fboxsep + "pt"); // 9636 9637 node.setAttribute("voffset", fboxsep + "pt"); 9638 9639 if (group.label === "\\fcolorbox") { 9640 var thk = Math.max(options.fontMetrics().fboxrule, // default 9641 options.minRuleThickness // user override 9642 ); 9643 node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor)); 9644 } 9645 9646 break; 9647 9648 case "\\xcancel": 9649 node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); 9650 break; 9651 } 9652 9653 if (group.backgroundColor) { 9654 node.setAttribute("mathbackground", group.backgroundColor); 9655 } 9656 9657 return node; 9658 }; 9659 9660 defineFunction({ 9661 type: "enclose", 9662 names: ["\\colorbox"], 9663 props: { 9664 numArgs: 2, 9665 allowedInText: true, 9666 argTypes: ["color", "text"] 9667 }, 9668 9669 handler(_ref, args, optArgs) { 9670 var { 9671 parser, 9672 funcName 9673 } = _ref; 9674 var color = assertNodeType(args[0], "color-token").color; 9675 var body = args[1]; 9676 return { 9677 type: "enclose", 9678 mode: parser.mode, 9679 label: funcName, 9680 backgroundColor: color, 9681 body 9682 }; 9683 }, 9684 9685 htmlBuilder: htmlBuilder$2, 9686 mathmlBuilder: mathmlBuilder$2 9687 }); 9688 defineFunction({ 9689 type: "enclose", 9690 names: ["\\fcolorbox"], 9691 props: { 9692 numArgs: 3, 9693 allowedInText: true, 9694 argTypes: ["color", "color", "text"] 9695 }, 9696 9697 handler(_ref2, args, optArgs) { 9698 var { 9699 parser, 9700 funcName 9701 } = _ref2; 9702 var borderColor = assertNodeType(args[0], "color-token").color; 9703 var backgroundColor = assertNodeType(args[1], "color-token").color; 9704 var body = args[2]; 9705 return { 9706 type: "enclose", 9707 mode: parser.mode, 9708 label: funcName, 9709 backgroundColor, 9710 borderColor, 9711 body 9712 }; 9713 }, 9714 9715 htmlBuilder: htmlBuilder$2, 9716 mathmlBuilder: mathmlBuilder$2 9717 }); 9718 defineFunction({ 9719 type: "enclose", 9720 names: ["\\fbox"], 9721 props: { 9722 numArgs: 1, 9723 argTypes: ["hbox"], 9724 allowedInText: true 9725 }, 9726 9727 handler(_ref3, args) { 9728 var { 9729 parser 9730 } = _ref3; 9731 return { 9732 type: "enclose", 9733 mode: parser.mode, 9734 label: "\\fbox", 9735 body: args[0] 9736 }; 9737 } 9738 9739 }); 9740 defineFunction({ 9741 type: "enclose", 9742 names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"], 9743 props: { 9744 numArgs: 1 9745 }, 9746 9747 handler(_ref4, args) { 9748 var { 9749 parser, 9750 funcName 9751 } = _ref4; 9752 var body = args[0]; 9753 return { 9754 type: "enclose", 9755 mode: parser.mode, 9756 label: funcName, 9757 body 9758 }; 9759 }, 9760 9761 htmlBuilder: htmlBuilder$2, 9762 mathmlBuilder: mathmlBuilder$2 9763 }); 9764 defineFunction({ 9765 type: "enclose", 9766 names: ["\\angl"], 9767 props: { 9768 numArgs: 1, 9769 argTypes: ["hbox"], 9770 allowedInText: false 9771 }, 9772 9773 handler(_ref5, args) { 9774 var { 9775 parser 9776 } = _ref5; 9777 return { 9778 type: "enclose", 9779 mode: parser.mode, 9780 label: "\\angl", 9781 body: args[0] 9782 }; 9783 } 9784 9785 }); 9786 9787 /** 9788 * All registered environments. 9789 * `environments.js` exports this same dictionary again and makes it public. 9790 * `Parser.js` requires this dictionary via `environments.js`. 9791 */ 9792 var _environments = {}; 9793 function defineEnvironment(_ref) { 9794 var { 9795 type, 9796 names, 9797 props, 9798 handler, 9799 htmlBuilder, 9800 mathmlBuilder 9801 } = _ref; 9802 // Set default values of environments. 9803 var data = { 9804 type, 9805 numArgs: props.numArgs || 0, 9806 allowedInText: false, 9807 numOptionalArgs: 0, 9808 handler 9809 }; 9810 9811 for (var i = 0; i < names.length; ++i) { 9812 // TODO: The value type of _environments should be a type union of all 9813 // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is 9814 // an existential type. 9815 _environments[names[i]] = data; 9816 } 9817 9818 if (htmlBuilder) { 9819 _htmlGroupBuilders[type] = htmlBuilder; 9820 } 9821 9822 if (mathmlBuilder) { 9823 _mathmlGroupBuilders[type] = mathmlBuilder; 9824 } 9825 } 9826 9827 // Helper functions 9828 function getHLines(parser) { 9829 // Return an array. The array length = number of hlines. 9830 // Each element in the array tells if the line is dashed. 9831 var hlineInfo = []; 9832 parser.consumeSpaces(); 9833 var nxt = parser.fetch().text; 9834 9835 while (nxt === "\\hline" || nxt === "\\hdashline") { 9836 parser.consume(); 9837 hlineInfo.push(nxt === "\\hdashline"); 9838 parser.consumeSpaces(); 9839 nxt = parser.fetch().text; 9840 } 9841 9842 return hlineInfo; 9843 } 9844 9845 var validateAmsEnvironmentContext = context => { 9846 var settings = context.parser.settings; 9847 9848 if (!settings.displayMode) { 9849 throw new ParseError("{" + context.envName + "} can be used only in" + " display mode."); 9850 } 9851 }; 9852 /** 9853 * Parse the body of the environment, with rows delimited by \\ and 9854 * columns delimited by &, and create a nested list in row-major order 9855 * with one group per cell. If given an optional argument style 9856 * ("text", "display", etc.), then each cell is cast into that style. 9857 */ 9858 9859 9860 function parseArray(parser, _ref, style) { 9861 var { 9862 hskipBeforeAndAfter, 9863 addJot, 9864 cols, 9865 arraystretch, 9866 colSeparationType, 9867 addEqnNum, 9868 singleRow, 9869 maxNumCols, 9870 leqno 9871 } = _ref; 9872 parser.gullet.beginGroup(); 9873 9874 if (!singleRow) { 9875 // \cr is equivalent to \\ without the optional size argument (see below) 9876 // TODO: provide helpful error when \cr is used outside array environment 9877 parser.gullet.macros.set("\\cr", "\\\\\\relax"); 9878 } // Get current arraystretch if it's not set by the environment 9879 9880 9881 if (!arraystretch) { 9882 var stretch = parser.gullet.expandMacroAsText("\\arraystretch"); 9883 9884 if (stretch == null) { 9885 // Default \arraystretch from lttab.dtx 9886 arraystretch = 1; 9887 } else { 9888 arraystretch = parseFloat(stretch); 9889 9890 if (!arraystretch || arraystretch < 0) { 9891 throw new ParseError("Invalid \\arraystretch: " + stretch); 9892 } 9893 } 9894 } // Start group for first cell 9895 9896 9897 parser.gullet.beginGroup(); 9898 var row = []; 9899 var body = [row]; 9900 var rowGaps = []; 9901 var hLinesBeforeRow = []; // Test for \hline at the top of the array. 9902 9903 hLinesBeforeRow.push(getHLines(parser)); 9904 9905 while (true) { 9906 // eslint-disable-line no-constant-condition 9907 // Parse each cell in its own group (namespace) 9908 var cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); 9909 parser.gullet.endGroup(); 9910 parser.gullet.beginGroup(); 9911 cell = { 9912 type: "ordgroup", 9913 mode: parser.mode, 9914 body: cell 9915 }; 9916 9917 if (style) { 9918 cell = { 9919 type: "styling", 9920 mode: parser.mode, 9921 style, 9922 body: [cell] 9923 }; 9924 } 9925 9926 row.push(cell); 9927 var next = parser.fetch().text; 9928 9929 if (next === "&") { 9930 if (maxNumCols && row.length === maxNumCols) { 9931 if (singleRow || colSeparationType) { 9932 // {equation} or {split} 9933 throw new ParseError("Too many tab characters: &", parser.nextToken); 9934 } else { 9935 // {array} environment 9936 parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument."); 9937 } 9938 } 9939 9940 parser.consume(); 9941 } else if (next === "\\end") { 9942 // Arrays terminate newlines with `\crcr` which consumes a `\cr` if 9943 // the last line is empty. 9944 // NOTE: Currently, `cell` is the last item added into `row`. 9945 if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0) { 9946 body.pop(); 9947 } 9948 9949 if (hLinesBeforeRow.length < body.length + 1) { 9950 hLinesBeforeRow.push([]); 9951 } 9952 9953 break; 9954 } else if (next === "\\\\") { 9955 parser.consume(); 9956 var size = void 0; // \def\Let@{\let\\\math@cr} 9957 // \def\math@cr{...\math@cr@} 9958 // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} 9959 // \def\math@cr@@[#1]{...\math@cr@@@...} 9960 // \def\math@cr@@@{\cr} 9961 9962 if (parser.gullet.future().text !== " ") { 9963 size = parser.parseSizeGroup(true); 9964 } 9965 9966 rowGaps.push(size ? size.value : null); // check for \hline(s) following the row separator 9967 9968 hLinesBeforeRow.push(getHLines(parser)); 9969 row = []; 9970 body.push(row); 9971 } else { 9972 throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); 9973 } 9974 } // End cell group 9975 9976 9977 parser.gullet.endGroup(); // End array group defining \cr 9978 9979 parser.gullet.endGroup(); 9980 return { 9981 type: "array", 9982 mode: parser.mode, 9983 addJot, 9984 arraystretch, 9985 body, 9986 cols, 9987 rowGaps, 9988 hskipBeforeAndAfter, 9989 hLinesBeforeRow, 9990 colSeparationType, 9991 addEqnNum, 9992 leqno 9993 }; 9994 } // Decides on a style for cells in an array according to whether the given 9995 // environment name starts with the letter 'd'. 9996 9997 9998 function dCellStyle(envName) { 9999 if (envName.substr(0, 1) === "d") { 10000 return "display"; 10001 } else { 10002 return "text"; 10003 } 10004 } 10005 10006 var htmlBuilder$3 = function htmlBuilder(group, options) { 10007 var r; 10008 var c; 10009 var nr = group.body.length; 10010 var hLinesBeforeRow = group.hLinesBeforeRow; 10011 var nc = 0; 10012 var body = new Array(nr); 10013 var hlines = []; 10014 var ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em. 10015 options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override. 10016 ); // Horizontal spacing 10017 10018 var pt = 1 / options.fontMetrics().ptPerEm; 10019 var arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls 10020 10021 if (group.colSeparationType && group.colSeparationType === "small") { 10022 // We're in a {smallmatrix}. Default column space is \thickspace, 10023 // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}. 10024 // But that needs adjustment because LaTeX applies \scriptstyle to the 10025 // entire array, including the colspace, but this function applies 10026 // \scriptstyle only inside each element. 10027 var localMultiplier = options.havingStyle(Style$1.SCRIPT).sizeMultiplier; 10028 arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier); 10029 } // Vertical spacing 10030 10031 10032 var baselineskip = group.colSeparationType === "CD" ? calculateSize({ 10033 number: 3, 10034 unit: "ex" 10035 }, options) : 12 * pt; // see size10.clo 10036 // Default \jot from ltmath.dtx 10037 // TODO(edemaine): allow overriding \jot via \setlength (#687) 10038 10039 var jot = 3 * pt; 10040 var arrayskip = group.arraystretch * baselineskip; 10041 var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and 10042 10043 var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx 10044 10045 var totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any. 10046 10047 function setHLinePos(hlinesInGap) { 10048 for (var i = 0; i < hlinesInGap.length; ++i) { 10049 if (i > 0) { 10050 totalHeight += 0.25; 10051 } 10052 10053 hlines.push({ 10054 pos: totalHeight, 10055 isDashed: hlinesInGap[i] 10056 }); 10057 } 10058 } 10059 10060 setHLinePos(hLinesBeforeRow[0]); 10061 10062 for (r = 0; r < group.body.length; ++r) { 10063 var inrow = group.body[r]; 10064 var height = arstrutHeight; // \@array adds an \@arstrut 10065 10066 var depth = arstrutDepth; // to each tow (via the template) 10067 10068 if (nc < inrow.length) { 10069 nc = inrow.length; 10070 } 10071 10072 var outrow = new Array(inrow.length); 10073 10074 for (c = 0; c < inrow.length; ++c) { 10075 var elt = buildGroup(inrow[c], options); 10076 10077 if (depth < elt.depth) { 10078 depth = elt.depth; 10079 } 10080 10081 if (height < elt.height) { 10082 height = elt.height; 10083 } 10084 10085 outrow[c] = elt; 10086 } 10087 10088 var rowGap = group.rowGaps[r]; 10089 var gap = 0; 10090 10091 if (rowGap) { 10092 gap = calculateSize(rowGap, options); 10093 10094 if (gap > 0) { 10095 // \@argarraycr 10096 gap += arstrutDepth; 10097 10098 if (depth < gap) { 10099 depth = gap; // \@xargarraycr 10100 } 10101 10102 gap = 0; 10103 } 10104 } // In AMS multiline environments such as aligned and gathered, rows 10105 // correspond to lines that have additional \jot added to the 10106 // \baselineskip via \openup. 10107 10108 10109 if (group.addJot) { 10110 depth += jot; 10111 } 10112 10113 outrow.height = height; 10114 outrow.depth = depth; 10115 totalHeight += height; 10116 outrow.pos = totalHeight; 10117 totalHeight += depth + gap; // \@yargarraycr 10118 10119 body[r] = outrow; // Set a position for \hline(s), if any. 10120 10121 setHLinePos(hLinesBeforeRow[r + 1]); 10122 } 10123 10124 var offset = totalHeight / 2 + options.fontMetrics().axisHeight; 10125 var colDescriptions = group.cols || []; 10126 var cols = []; 10127 var colSep; 10128 var colDescrNum; 10129 var eqnNumSpans = []; 10130 10131 if (group.addEqnNum) { 10132 // An environment with automatic equation numbers. 10133 // Create node(s) that will trigger CSS counter increment. 10134 for (r = 0; r < nr; ++r) { 10135 var rw = body[r]; 10136 var shift = rw.pos - offset; 10137 var eqnTag = buildCommon.makeSpan(["eqn-num"], [], options); 10138 eqnTag.depth = rw.depth; 10139 eqnTag.height = rw.height; 10140 eqnNumSpans.push({ 10141 type: "elem", 10142 elem: eqnTag, 10143 shift 10144 }); 10145 } 10146 } 10147 10148 for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column 10149 // descriptions, so trailing separators don't get lost. 10150 c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) { 10151 var colDescr = colDescriptions[colDescrNum] || {}; 10152 var firstSeparator = true; 10153 10154 while (colDescr.type === "separator") { 10155 // If there is more than one separator in a row, add a space 10156 // between them. 10157 if (!firstSeparator) { 10158 colSep = buildCommon.makeSpan(["arraycolsep"], []); 10159 colSep.style.width = options.fontMetrics().doubleRuleSep + "em"; 10160 cols.push(colSep); 10161 } 10162 10163 if (colDescr.separator === "|" || colDescr.separator === ":") { 10164 var lineType = colDescr.separator === "|" ? "solid" : "dashed"; 10165 var separator = buildCommon.makeSpan(["vertical-separator"], [], options); 10166 separator.style.height = totalHeight + "em"; 10167 separator.style.borderRightWidth = ruleThickness + "em"; 10168 separator.style.borderRightStyle = lineType; 10169 separator.style.margin = "0 -" + ruleThickness / 2 + "em"; 10170 separator.style.verticalAlign = -(totalHeight - offset) + "em"; 10171 cols.push(separator); 10172 } else { 10173 throw new ParseError("Invalid separator type: " + colDescr.separator); 10174 } 10175 10176 colDescrNum++; 10177 colDescr = colDescriptions[colDescrNum] || {}; 10178 firstSeparator = false; 10179 } 10180 10181 if (c >= nc) { 10182 continue; 10183 } 10184 10185 var sepwidth = void 0; 10186 10187 if (c > 0 || group.hskipBeforeAndAfter) { 10188 sepwidth = utils.deflt(colDescr.pregap, arraycolsep); 10189 10190 if (sepwidth !== 0) { 10191 colSep = buildCommon.makeSpan(["arraycolsep"], []); 10192 colSep.style.width = sepwidth + "em"; 10193 cols.push(colSep); 10194 } 10195 } 10196 10197 var col = []; 10198 10199 for (r = 0; r < nr; ++r) { 10200 var row = body[r]; 10201 var elem = row[c]; 10202 10203 if (!elem) { 10204 continue; 10205 } 10206 10207 var _shift = row.pos - offset; 10208 10209 elem.depth = row.depth; 10210 elem.height = row.height; 10211 col.push({ 10212 type: "elem", 10213 elem: elem, 10214 shift: _shift 10215 }); 10216 } 10217 10218 col = buildCommon.makeVList({ 10219 positionType: "individualShift", 10220 children: col 10221 }, options); 10222 col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]); 10223 cols.push(col); 10224 10225 if (c < nc - 1 || group.hskipBeforeAndAfter) { 10226 sepwidth = utils.deflt(colDescr.postgap, arraycolsep); 10227 10228 if (sepwidth !== 0) { 10229 colSep = buildCommon.makeSpan(["arraycolsep"], []); 10230 colSep.style.width = sepwidth + "em"; 10231 cols.push(colSep); 10232 } 10233 } 10234 } 10235 10236 body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any. 10237 10238 if (hlines.length > 0) { 10239 var line = buildCommon.makeLineSpan("hline", options, ruleThickness); 10240 var dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness); 10241 var vListElems = [{ 10242 type: "elem", 10243 elem: body, 10244 shift: 0 10245 }]; 10246 10247 while (hlines.length > 0) { 10248 var hline = hlines.pop(); 10249 var lineShift = hline.pos - offset; 10250 10251 if (hline.isDashed) { 10252 vListElems.push({ 10253 type: "elem", 10254 elem: dashes, 10255 shift: lineShift 10256 }); 10257 } else { 10258 vListElems.push({ 10259 type: "elem", 10260 elem: line, 10261 shift: lineShift 10262 }); 10263 } 10264 } 10265 10266 body = buildCommon.makeVList({ 10267 positionType: "individualShift", 10268 children: vListElems 10269 }, options); 10270 } 10271 10272 if (!group.addEqnNum) { 10273 return buildCommon.makeSpan(["mord"], [body], options); 10274 } else { 10275 var eqnNumCol = buildCommon.makeVList({ 10276 positionType: "individualShift", 10277 children: eqnNumSpans 10278 }, options); 10279 eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options); 10280 return buildCommon.makeFragment([body, eqnNumCol]); 10281 } 10282 }; 10283 10284 var alignMap = { 10285 c: "center ", 10286 l: "left ", 10287 r: "right " 10288 }; 10289 10290 var mathmlBuilder$3 = function mathmlBuilder(group, options) { 10291 var tbl = []; 10292 var glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]); 10293 var tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]); 10294 10295 for (var i = 0; i < group.body.length; i++) { 10296 var rw = group.body[i]; 10297 var row = []; 10298 10299 for (var j = 0; j < rw.length; j++) { 10300 row.push(new mathMLTree.MathNode("mtd", [buildGroup$1(rw[j], options)])); 10301 } 10302 10303 if (group.addEqnNum) { 10304 row.unshift(glue); 10305 row.push(glue); 10306 10307 if (group.leqno) { 10308 row.unshift(tag); 10309 } else { 10310 row.push(tag); 10311 } 10312 } 10313 10314 tbl.push(new mathMLTree.MathNode("mtr", row)); 10315 } 10316 10317 var table = new mathMLTree.MathNode("mtable", tbl); // Set column alignment, row spacing, column spacing, and 10318 // array lines by setting attributes on the table element. 10319 // Set the row spacing. In MathML, we specify a gap distance. 10320 // We do not use rowGap[] because MathML automatically increases 10321 // cell height with the height/depth of the element content. 10322 // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. 10323 // We simulate this by adding (arraystretch - 1)em to the gap. This 10324 // does a reasonable job of adjusting arrays containing 1 em tall content. 10325 // The 0.16 and 0.09 values are found emprically. They produce an array 10326 // similar to LaTeX and in which content does not interfere with \hines. 10327 10328 var gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray} 10329 : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); 10330 table.setAttribute("rowspacing", gap.toFixed(4) + "em"); // MathML table lines go only between cells. 10331 // To place a line on an edge we'll use <menclose>, if necessary. 10332 10333 var menclose = ""; 10334 var align = ""; 10335 10336 if (group.cols && group.cols.length > 0) { 10337 // Find column alignment, column spacing, and vertical lines. 10338 var cols = group.cols; 10339 var columnLines = ""; 10340 var prevTypeWasAlign = false; 10341 var iStart = 0; 10342 var iEnd = cols.length; 10343 10344 if (cols[0].type === "separator") { 10345 menclose += "top "; 10346 iStart = 1; 10347 } 10348 10349 if (cols[cols.length - 1].type === "separator") { 10350 menclose += "bottom "; 10351 iEnd -= 1; 10352 } 10353 10354 for (var _i = iStart; _i < iEnd; _i++) { 10355 if (cols[_i].type === "align") { 10356 align += alignMap[cols[_i].align]; 10357 10358 if (prevTypeWasAlign) { 10359 columnLines += "none "; 10360 } 10361 10362 prevTypeWasAlign = true; 10363 } else if (cols[_i].type === "separator") { 10364 // MathML accepts only single lines between cells. 10365 // So we read only the first of consecutive separators. 10366 if (prevTypeWasAlign) { 10367 columnLines += cols[_i].separator === "|" ? "solid " : "dashed "; 10368 prevTypeWasAlign = false; 10369 } 10370 } 10371 } 10372 10373 table.setAttribute("columnalign", align.trim()); 10374 10375 if (/[sd]/.test(columnLines)) { 10376 table.setAttribute("columnlines", columnLines.trim()); 10377 } 10378 } // Set column spacing. 10379 10380 10381 if (group.colSeparationType === "align") { 10382 var _cols = group.cols || []; 10383 10384 var spacing = ""; 10385 10386 for (var _i2 = 1; _i2 < _cols.length; _i2++) { 10387 spacing += _i2 % 2 ? "0em " : "1em "; 10388 } 10389 10390 table.setAttribute("columnspacing", spacing.trim()); 10391 } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") { 10392 table.setAttribute("columnspacing", "0em"); 10393 } else if (group.colSeparationType === "small") { 10394 table.setAttribute("columnspacing", "0.2778em"); 10395 } else if (group.colSeparationType === "CD") { 10396 table.setAttribute("columnspacing", "0.5em"); 10397 } else { 10398 table.setAttribute("columnspacing", "1em"); 10399 } // Address \hline and \hdashline 10400 10401 10402 var rowLines = ""; 10403 var hlines = group.hLinesBeforeRow; 10404 menclose += hlines[0].length > 0 ? "left " : ""; 10405 menclose += hlines[hlines.length - 1].length > 0 ? "right " : ""; 10406 10407 for (var _i3 = 1; _i3 < hlines.length - 1; _i3++) { 10408 rowLines += hlines[_i3].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element. 10409 : hlines[_i3][0] ? "dashed " : "solid "; 10410 } 10411 10412 if (/[sd]/.test(rowLines)) { 10413 table.setAttribute("rowlines", rowLines.trim()); 10414 } 10415 10416 if (menclose !== "") { 10417 table = new mathMLTree.MathNode("menclose", [table]); 10418 table.setAttribute("notation", menclose.trim()); 10419 } 10420 10421 if (group.arraystretch && group.arraystretch < 1) { 10422 // A small array. Wrap in scriptstyle so row gap is not too large. 10423 table = new mathMLTree.MathNode("mstyle", [table]); 10424 table.setAttribute("scriptlevel", "1"); 10425 } 10426 10427 return table; 10428 }; // Convenience function for align, align*, aligned, alignat, alignat*, alignedat. 10429 10430 10431 var alignedHandler = function alignedHandler(context, args) { 10432 if (context.envName.indexOf("ed") === -1) { 10433 validateAmsEnvironmentContext(context); 10434 } 10435 10436 var cols = []; 10437 var separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align"; 10438 var res = parseArray(context.parser, { 10439 cols, 10440 addJot: true, 10441 addEqnNum: context.envName === "align" || context.envName === "alignat", 10442 colSeparationType: separationType, 10443 maxNumCols: context.envName === "split" ? 2 : undefined, 10444 leqno: context.parser.settings.leqno 10445 }, "display"); // Determining number of columns. 10446 // 1. If the first argument is given, we use it as a number of columns, 10447 // and makes sure that each row doesn't exceed that number. 10448 // 2. Otherwise, just count number of columns = maximum number 10449 // of cells in each row ("aligned" mode -- isAligned will be true). 10450 // 10451 // At the same time, prepend empty group {} at beginning of every second 10452 // cell in each row (starting with second cell) so that operators become 10453 // binary. This behavior is implemented in amsmath's \start@aligned. 10454 10455 var numMaths; 10456 var numCols = 0; 10457 var emptyGroup = { 10458 type: "ordgroup", 10459 mode: context.mode, 10460 body: [] 10461 }; 10462 10463 if (args[0] && args[0].type === "ordgroup") { 10464 var arg0 = ""; 10465 10466 for (var i = 0; i < args[0].body.length; i++) { 10467 var textord = assertNodeType(args[0].body[i], "textord"); 10468 arg0 += textord.text; 10469 } 10470 10471 numMaths = Number(arg0); 10472 numCols = numMaths * 2; 10473 } 10474 10475 var isAligned = !numCols; 10476 res.body.forEach(function (row) { 10477 for (var _i4 = 1; _i4 < row.length; _i4 += 2) { 10478 // Modify ordgroup node within styling node 10479 var styling = assertNodeType(row[_i4], "styling"); 10480 var ordgroup = assertNodeType(styling.body[0], "ordgroup"); 10481 ordgroup.body.unshift(emptyGroup); 10482 } 10483 10484 if (!isAligned) { 10485 // Case 1 10486 var curMaths = row.length / 2; 10487 10488 if (numMaths < curMaths) { 10489 throw new ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]); 10490 } 10491 } else if (numCols < row.length) { 10492 // Case 2 10493 numCols = row.length; 10494 } 10495 }); // Adjusting alignment. 10496 // In aligned mode, we add one \qquad between columns; 10497 // otherwise we add nothing. 10498 10499 for (var _i5 = 0; _i5 < numCols; ++_i5) { 10500 var align = "r"; 10501 var pregap = 0; 10502 10503 if (_i5 % 2 === 1) { 10504 align = "l"; 10505 } else if (_i5 > 0 && isAligned) { 10506 // "aligned" mode. 10507 pregap = 1; // add one \quad 10508 } 10509 10510 cols[_i5] = { 10511 type: "align", 10512 align: align, 10513 pregap: pregap, 10514 postgap: 0 10515 }; 10516 } 10517 10518 res.colSeparationType = isAligned ? "align" : "alignat"; 10519 return res; 10520 }; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation 10521 // is part of the source2e.pdf file of LaTeX2e source documentation. 10522 // {darray} is an {array} environment where cells are set in \displaystyle, 10523 // as defined in nccmath.sty. 10524 10525 10526 defineEnvironment({ 10527 type: "array", 10528 names: ["array", "darray"], 10529 props: { 10530 numArgs: 1 10531 }, 10532 10533 handler(context, args) { 10534 // Since no types are specified above, the two possibilities are 10535 // - The argument is wrapped in {} or [], in which case Parser's 10536 // parseGroup() returns an "ordgroup" wrapping some symbol node. 10537 // - The argument is a bare symbol node. 10538 var symNode = checkSymbolNodeType(args[0]); 10539 var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; 10540 var cols = colalign.map(function (nde) { 10541 var node = assertSymbolNodeType(nde); 10542 var ca = node.text; 10543 10544 if ("lcr".indexOf(ca) !== -1) { 10545 return { 10546 type: "align", 10547 align: ca 10548 }; 10549 } else if (ca === "|") { 10550 return { 10551 type: "separator", 10552 separator: "|" 10553 }; 10554 } else if (ca === ":") { 10555 return { 10556 type: "separator", 10557 separator: ":" 10558 }; 10559 } 10560 10561 throw new ParseError("Unknown column alignment: " + ca, nde); 10562 }); 10563 var res = { 10564 cols, 10565 hskipBeforeAndAfter: true, 10566 // \@preamble in lttab.dtx 10567 maxNumCols: cols.length 10568 }; 10569 return parseArray(context.parser, res, dCellStyle(context.envName)); 10570 }, 10571 10572 htmlBuilder: htmlBuilder$3, 10573 mathmlBuilder: mathmlBuilder$3 10574 }); // The matrix environments of amsmath builds on the array environment 10575 // of LaTeX, which is discussed above. 10576 // The mathtools package adds starred versions of the same environments. 10577 // These have an optional argument to choose left|center|right justification. 10578 10579 defineEnvironment({ 10580 type: "array", 10581 names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"], 10582 props: { 10583 numArgs: 0 10584 }, 10585 10586 handler(context) { 10587 var delimiters = { 10588 "matrix": null, 10589 "pmatrix": ["(", ")"], 10590 "bmatrix": ["[", "]"], 10591 "Bmatrix": ["\\{", "\\}"], 10592 "vmatrix": ["|", "|"], 10593 "Vmatrix": ["\\Vert", "\\Vert"] 10594 }[context.envName.replace("*", "")]; // \hskip -\arraycolsep in amsmath 10595 10596 var colAlign = "c"; 10597 var payload = { 10598 hskipBeforeAndAfter: false, 10599 cols: [{ 10600 type: "align", 10601 align: colAlign 10602 }] 10603 }; 10604 10605 if (context.envName.charAt(context.envName.length - 1) === "*") { 10606 // It's one of the mathtools starred functions. 10607 // Parse the optional alignment argument. 10608 var parser = context.parser; 10609 parser.consumeSpaces(); 10610 10611 if (parser.fetch().text === "[") { 10612 parser.consume(); 10613 parser.consumeSpaces(); 10614 colAlign = parser.fetch().text; 10615 10616 if ("lcr".indexOf(colAlign) === -1) { 10617 throw new ParseError("Expected l or c or r", parser.nextToken); 10618 } 10619 10620 parser.consume(); 10621 parser.consumeSpaces(); 10622 parser.expect("]"); 10623 parser.consume(); 10624 payload.cols = [{ 10625 type: "align", 10626 align: colAlign 10627 }]; 10628 } 10629 } 10630 10631 var res = parseArray(context.parser, payload, dCellStyle(context.envName)); // Populate cols with the correct number of column alignment specs. 10632 10633 res.cols = new Array(res.body[0].length).fill({ 10634 type: "align", 10635 align: colAlign 10636 }); 10637 return delimiters ? { 10638 type: "leftright", 10639 mode: context.mode, 10640 body: [res], 10641 left: delimiters[0], 10642 right: delimiters[1], 10643 rightColor: undefined // \right uninfluenced by \color in array 10644 10645 } : res; 10646 }, 10647 10648 htmlBuilder: htmlBuilder$3, 10649 mathmlBuilder: mathmlBuilder$3 10650 }); 10651 defineEnvironment({ 10652 type: "array", 10653 names: ["smallmatrix"], 10654 props: { 10655 numArgs: 0 10656 }, 10657 10658 handler(context) { 10659 var payload = { 10660 arraystretch: 0.5 10661 }; 10662 var res = parseArray(context.parser, payload, "script"); 10663 res.colSeparationType = "small"; 10664 return res; 10665 }, 10666 10667 htmlBuilder: htmlBuilder$3, 10668 mathmlBuilder: mathmlBuilder$3 10669 }); 10670 defineEnvironment({ 10671 type: "array", 10672 names: ["subarray"], 10673 props: { 10674 numArgs: 1 10675 }, 10676 10677 handler(context, args) { 10678 // Parsing of {subarray} is similar to {array} 10679 var symNode = checkSymbolNodeType(args[0]); 10680 var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; 10681 var cols = colalign.map(function (nde) { 10682 var node = assertSymbolNodeType(nde); 10683 var ca = node.text; // {subarray} only recognizes "l" & "c" 10684 10685 if ("lc".indexOf(ca) !== -1) { 10686 return { 10687 type: "align", 10688 align: ca 10689 }; 10690 } 10691 10692 throw new ParseError("Unknown column alignment: " + ca, nde); 10693 }); 10694 10695 if (cols.length > 1) { 10696 throw new ParseError("{subarray} can contain only one column"); 10697 } 10698 10699 var res = { 10700 cols, 10701 hskipBeforeAndAfter: false, 10702 arraystretch: 0.5 10703 }; 10704 res = parseArray(context.parser, res, "script"); 10705 10706 if (res.body.length > 0 && res.body[0].length > 1) { 10707 throw new ParseError("{subarray} can contain only one column"); 10708 } 10709 10710 return res; 10711 }, 10712 10713 htmlBuilder: htmlBuilder$3, 10714 mathmlBuilder: mathmlBuilder$3 10715 }); // A cases environment (in amsmath.sty) is almost equivalent to 10716 // \def\arraystretch{1.2}% 10717 // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. 10718 // {dcases} is a {cases} environment where cells are set in \displaystyle, 10719 // as defined in mathtools.sty. 10720 // {rcases} is another mathtools environment. It's brace is on the right side. 10721 10722 defineEnvironment({ 10723 type: "array", 10724 names: ["cases", "dcases", "rcases", "drcases"], 10725 props: { 10726 numArgs: 0 10727 }, 10728 10729 handler(context) { 10730 var payload = { 10731 arraystretch: 1.2, 10732 cols: [{ 10733 type: "align", 10734 align: "l", 10735 pregap: 0, 10736 // TODO(kevinb) get the current style. 10737 // For now we use the metrics for TEXT style which is what we were 10738 // doing before. Before attempting to get the current style we 10739 // should look at TeX's behavior especially for \over and matrices. 10740 postgap: 1.0 10741 /* 1em quad */ 10742 10743 }, { 10744 type: "align", 10745 align: "l", 10746 pregap: 0, 10747 postgap: 0 10748 }] 10749 }; 10750 var res = parseArray(context.parser, payload, dCellStyle(context.envName)); 10751 return { 10752 type: "leftright", 10753 mode: context.mode, 10754 body: [res], 10755 left: context.envName.indexOf("r") > -1 ? "." : "\\{", 10756 right: context.envName.indexOf("r") > -1 ? "\\}" : ".", 10757 rightColor: undefined 10758 }; 10759 }, 10760 10761 htmlBuilder: htmlBuilder$3, 10762 mathmlBuilder: mathmlBuilder$3 10763 }); // In the align environment, one uses ampersands, &, to specify number of 10764 // columns in each row, and to locate spacing between each column. 10765 // align gets automatic numbering. align* and aligned do not. 10766 // The alignedat environment can be used in math mode. 10767 // Note that we assume \nomallineskiplimit to be zero, 10768 // so that \strut@ is the same as \strut. 10769 10770 defineEnvironment({ 10771 type: "array", 10772 names: ["align", "align*", "aligned", "split"], 10773 props: { 10774 numArgs: 0 10775 }, 10776 handler: alignedHandler, 10777 htmlBuilder: htmlBuilder$3, 10778 mathmlBuilder: mathmlBuilder$3 10779 }); // A gathered environment is like an array environment with one centered 10780 // column, but where rows are considered lines so get \jot line spacing 10781 // and contents are set in \displaystyle. 10782 10783 defineEnvironment({ 10784 type: "array", 10785 names: ["gathered", "gather", "gather*"], 10786 props: { 10787 numArgs: 0 10788 }, 10789 10790 handler(context) { 10791 if (utils.contains(["gather", "gather*"], context.envName)) { 10792 validateAmsEnvironmentContext(context); 10793 } 10794 10795 var res = { 10796 cols: [{ 10797 type: "align", 10798 align: "c" 10799 }], 10800 addJot: true, 10801 colSeparationType: "gather", 10802 addEqnNum: context.envName === "gather", 10803 leqno: context.parser.settings.leqno 10804 }; 10805 return parseArray(context.parser, res, "display"); 10806 }, 10807 10808 htmlBuilder: htmlBuilder$3, 10809 mathmlBuilder: mathmlBuilder$3 10810 }); // alignat environment is like an align environment, but one must explicitly 10811 // specify maximum number of columns in each row, and can adjust spacing between 10812 // each columns. 10813 10814 defineEnvironment({ 10815 type: "array", 10816 names: ["alignat", "alignat*", "alignedat"], 10817 props: { 10818 numArgs: 1 10819 }, 10820 handler: alignedHandler, 10821 htmlBuilder: htmlBuilder$3, 10822 mathmlBuilder: mathmlBuilder$3 10823 }); 10824 defineEnvironment({ 10825 type: "array", 10826 names: ["equation", "equation*"], 10827 props: { 10828 numArgs: 0 10829 }, 10830 10831 handler(context) { 10832 validateAmsEnvironmentContext(context); 10833 var res = { 10834 addEqnNum: context.envName === "equation", 10835 singleRow: true, 10836 maxNumCols: 1, 10837 leqno: context.parser.settings.leqno 10838 }; 10839 return parseArray(context.parser, res, "display"); 10840 }, 10841 10842 htmlBuilder: htmlBuilder$3, 10843 mathmlBuilder: mathmlBuilder$3 10844 }); 10845 defineEnvironment({ 10846 type: "array", 10847 names: ["CD"], 10848 props: { 10849 numArgs: 0 10850 }, 10851 10852 handler(context) { 10853 validateAmsEnvironmentContext(context); 10854 return parseCD(context.parser); 10855 }, 10856 10857 htmlBuilder: htmlBuilder$3, 10858 mathmlBuilder: mathmlBuilder$3 10859 }); // Catch \hline outside array environment 10860 10861 defineFunction({ 10862 type: "text", 10863 // Doesn't matter what this is. 10864 names: ["\\hline", "\\hdashline"], 10865 props: { 10866 numArgs: 0, 10867 allowedInText: true, 10868 allowedInMath: true 10869 }, 10870 10871 handler(context, args) { 10872 throw new ParseError(context.funcName + " valid only within array environment"); 10873 } 10874 10875 }); 10876 10877 var environments = _environments; 10878 10879 // defineEnvironment definitions. 10880 10881 defineFunction({ 10882 type: "environment", 10883 names: ["\\begin", "\\end"], 10884 props: { 10885 numArgs: 1, 10886 argTypes: ["text"] 10887 }, 10888 10889 handler(_ref, args) { 10890 var { 10891 parser, 10892 funcName 10893 } = _ref; 10894 var nameGroup = args[0]; 10895 10896 if (nameGroup.type !== "ordgroup") { 10897 throw new ParseError("Invalid environment name", nameGroup); 10898 } 10899 10900 var envName = ""; 10901 10902 for (var i = 0; i < nameGroup.body.length; ++i) { 10903 envName += assertNodeType(nameGroup.body[i], "textord").text; 10904 } 10905 10906 if (funcName === "\\begin") { 10907 // begin...end is similar to left...right 10908 if (!environments.hasOwnProperty(envName)) { 10909 throw new ParseError("No such environment: " + envName, nameGroup); 10910 } // Build the environment object. Arguments and other information will 10911 // be made available to the begin and end methods using properties. 10912 10913 10914 var env = environments[envName]; 10915 var { 10916 args: _args, 10917 optArgs 10918 } = parser.parseArguments("\\begin{" + envName + "}", env); 10919 var context = { 10920 mode: parser.mode, 10921 envName, 10922 parser 10923 }; 10924 var result = env.handler(context, _args, optArgs); 10925 parser.expect("\\end", false); 10926 var endNameToken = parser.nextToken; 10927 var end = assertNodeType(parser.parseFunction(), "environment"); 10928 10929 if (end.name !== envName) { 10930 throw new ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken); 10931 } // $FlowFixMe, "environment" handler returns an environment ParseNode 10932 10933 10934 return result; 10935 } 10936 10937 return { 10938 type: "environment", 10939 mode: parser.mode, 10940 name: envName, 10941 nameGroup 10942 }; 10943 } 10944 10945 }); 10946 10947 var makeSpan$2 = buildCommon.makeSpan; 10948 10949 function htmlBuilder$4(group, options) { 10950 var elements = buildExpression(group.body, options, true); 10951 return makeSpan$2([group.mclass], elements, options); 10952 } 10953 10954 function mathmlBuilder$4(group, options) { 10955 var node; 10956 var inner = buildExpression$1(group.body, options); 10957 10958 if (group.mclass === "minner") { 10959 return mathMLTree.newDocumentFragment(inner); 10960 } else if (group.mclass === "mord") { 10961 if (group.isCharacterBox) { 10962 node = inner[0]; 10963 node.type = "mi"; 10964 } else { 10965 node = new mathMLTree.MathNode("mi", inner); 10966 } 10967 } else { 10968 if (group.isCharacterBox) { 10969 node = inner[0]; 10970 node.type = "mo"; 10971 } else { 10972 node = new mathMLTree.MathNode("mo", inner); 10973 } // Set spacing based on what is the most likely adjacent atom type. 10974 // See TeXbook p170. 10975 10976 10977 if (group.mclass === "mbin") { 10978 node.attributes.lspace = "0.22em"; // medium space 10979 10980 node.attributes.rspace = "0.22em"; 10981 } else if (group.mclass === "mpunct") { 10982 node.attributes.lspace = "0em"; 10983 node.attributes.rspace = "0.17em"; // thinspace 10984 } else if (group.mclass === "mopen" || group.mclass === "mclose") { 10985 node.attributes.lspace = "0em"; 10986 node.attributes.rspace = "0em"; 10987 } // MathML <mo> default space is 5/18 em, so <mrel> needs no action. 10988 // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo 10989 10990 } 10991 10992 return node; 10993 } // Math class commands except \mathop 10994 10995 10996 defineFunction({ 10997 type: "mclass", 10998 names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"], 10999 props: { 11000 numArgs: 1, 11001 primitive: true 11002 }, 11003 11004 handler(_ref, args) { 11005 var { 11006 parser, 11007 funcName 11008 } = _ref; 11009 var body = args[0]; 11010 return { 11011 type: "mclass", 11012 mode: parser.mode, 11013 mclass: "m" + funcName.substr(5), 11014 // TODO(kevinb): don't prefix with 'm' 11015 body: ordargument(body), 11016 isCharacterBox: utils.isCharacterBox(body) 11017 }; 11018 }, 11019 11020 htmlBuilder: htmlBuilder$4, 11021 mathmlBuilder: mathmlBuilder$4 11022 }); 11023 var binrelClass = arg => { 11024 // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. 11025 // (by rendering separately and with {}s before and after, and measuring 11026 // the change in spacing). We'll do roughly the same by detecting the 11027 // atom type directly. 11028 var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; 11029 11030 if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { 11031 return "m" + atom.family; 11032 } else { 11033 return "mord"; 11034 } 11035 }; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. 11036 // This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. 11037 11038 defineFunction({ 11039 type: "mclass", 11040 names: ["\\@binrel"], 11041 props: { 11042 numArgs: 2 11043 }, 11044 11045 handler(_ref2, args) { 11046 var { 11047 parser 11048 } = _ref2; 11049 return { 11050 type: "mclass", 11051 mode: parser.mode, 11052 mclass: binrelClass(args[0]), 11053 body: ordargument(args[1]), 11054 isCharacterBox: utils.isCharacterBox(args[1]) 11055 }; 11056 } 11057 11058 }); // Build a relation or stacked op by placing one symbol on top of another 11059 11060 defineFunction({ 11061 type: "mclass", 11062 names: ["\\stackrel", "\\overset", "\\underset"], 11063 props: { 11064 numArgs: 2 11065 }, 11066 11067 handler(_ref3, args) { 11068 var { 11069 parser, 11070 funcName 11071 } = _ref3; 11072 var baseArg = args[1]; 11073 var shiftedArg = args[0]; 11074 var mclass; 11075 11076 if (funcName !== "\\stackrel") { 11077 // LaTeX applies \binrel spacing to \overset and \underset. 11078 mclass = binrelClass(baseArg); 11079 } else { 11080 mclass = "mrel"; // for \stackrel 11081 } 11082 11083 var baseOp = { 11084 type: "op", 11085 mode: baseArg.mode, 11086 limits: true, 11087 alwaysHandleSupSub: true, 11088 parentIsSupSub: false, 11089 symbol: false, 11090 suppressBaseShift: funcName !== "\\stackrel", 11091 body: ordargument(baseArg) 11092 }; 11093 var supsub = { 11094 type: "supsub", 11095 mode: shiftedArg.mode, 11096 base: baseOp, 11097 sup: funcName === "\\underset" ? null : shiftedArg, 11098 sub: funcName === "\\underset" ? shiftedArg : null 11099 }; 11100 return { 11101 type: "mclass", 11102 mode: parser.mode, 11103 mclass, 11104 body: [supsub], 11105 isCharacterBox: utils.isCharacterBox(supsub) 11106 }; 11107 }, 11108 11109 htmlBuilder: htmlBuilder$4, 11110 mathmlBuilder: mathmlBuilder$4 11111 }); 11112 11113 // TODO(kevinb): implement \\sl and \\sc 11114 11115 var htmlBuilder$5 = (group, options) => { 11116 var font = group.font; 11117 var newOptions = options.withFont(font); 11118 return buildGroup(group.body, newOptions); 11119 }; 11120 11121 var mathmlBuilder$5 = (group, options) => { 11122 var font = group.font; 11123 var newOptions = options.withFont(font); 11124 return buildGroup$1(group.body, newOptions); 11125 }; 11126 11127 var fontAliases = { 11128 "\\Bbb": "\\mathbb", 11129 "\\bold": "\\mathbf", 11130 "\\frak": "\\mathfrak", 11131 "\\bm": "\\boldsymbol" 11132 }; 11133 defineFunction({ 11134 type: "font", 11135 names: [// styles, except \boldsymbol defined below 11136 "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", // families 11137 "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below 11138 "\\Bbb", "\\bold", "\\frak"], 11139 props: { 11140 numArgs: 1, 11141 allowedInArgument: true 11142 }, 11143 handler: (_ref, args) => { 11144 var { 11145 parser, 11146 funcName 11147 } = _ref; 11148 var body = normalizeArgument(args[0]); 11149 var func = funcName; 11150 11151 if (func in fontAliases) { 11152 func = fontAliases[func]; 11153 } 11154 11155 return { 11156 type: "font", 11157 mode: parser.mode, 11158 font: func.slice(1), 11159 body 11160 }; 11161 }, 11162 htmlBuilder: htmlBuilder$5, 11163 mathmlBuilder: mathmlBuilder$5 11164 }); 11165 defineFunction({ 11166 type: "mclass", 11167 names: ["\\boldsymbol", "\\bm"], 11168 props: { 11169 numArgs: 1 11170 }, 11171 handler: (_ref2, args) => { 11172 var { 11173 parser 11174 } = _ref2; 11175 var body = args[0]; 11176 var isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the 11177 // argument's bin|rel|ord status 11178 11179 return { 11180 type: "mclass", 11181 mode: parser.mode, 11182 mclass: binrelClass(body), 11183 body: [{ 11184 type: "font", 11185 mode: parser.mode, 11186 font: "boldsymbol", 11187 body 11188 }], 11189 isCharacterBox: isCharacterBox 11190 }; 11191 } 11192 }); // Old font changing functions 11193 11194 defineFunction({ 11195 type: "font", 11196 names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], 11197 props: { 11198 numArgs: 0, 11199 allowedInText: true 11200 }, 11201 handler: (_ref3, args) => { 11202 var { 11203 parser, 11204 funcName, 11205 breakOnTokenText 11206 } = _ref3; 11207 var { 11208 mode 11209 } = parser; 11210 var body = parser.parseExpression(true, breakOnTokenText); 11211 var style = "math" + funcName.slice(1); 11212 return { 11213 type: "font", 11214 mode: mode, 11215 font: style, 11216 body: { 11217 type: "ordgroup", 11218 mode: parser.mode, 11219 body 11220 } 11221 }; 11222 }, 11223 htmlBuilder: htmlBuilder$5, 11224 mathmlBuilder: mathmlBuilder$5 11225 }); 11226 11227 var adjustStyle = (size, originalStyle) => { 11228 // Figure out what style this fraction should be in based on the 11229 // function used 11230 var style = originalStyle; 11231 11232 if (size === "display") { 11233 // Get display style as a default. 11234 // If incoming style is sub/sup, use style.text() to get correct size. 11235 style = style.id >= Style$1.SCRIPT.id ? style.text() : Style$1.DISPLAY; 11236 } else if (size === "text" && style.size === Style$1.DISPLAY.size) { 11237 // We're in a \tfrac but incoming style is displaystyle, so: 11238 style = Style$1.TEXT; 11239 } else if (size === "script") { 11240 style = Style$1.SCRIPT; 11241 } else if (size === "scriptscript") { 11242 style = Style$1.SCRIPTSCRIPT; 11243 } 11244 11245 return style; 11246 }; 11247 11248 var htmlBuilder$6 = (group, options) => { 11249 // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). 11250 var style = adjustStyle(group.size, options.style); 11251 var nstyle = style.fracNum(); 11252 var dstyle = style.fracDen(); 11253 var newOptions; 11254 newOptions = options.havingStyle(nstyle); 11255 var numerm = buildGroup(group.numer, newOptions, options); 11256 11257 if (group.continued) { 11258 // \cfrac inserts a \strut into the numerator. 11259 // Get \strut dimensions from TeXbook page 353. 11260 var hStrut = 8.5 / options.fontMetrics().ptPerEm; 11261 var dStrut = 3.5 / options.fontMetrics().ptPerEm; 11262 numerm.height = numerm.height < hStrut ? hStrut : numerm.height; 11263 numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth; 11264 } 11265 11266 newOptions = options.havingStyle(dstyle); 11267 var denomm = buildGroup(group.denom, newOptions, options); 11268 var rule; 11269 var ruleWidth; 11270 var ruleSpacing; 11271 11272 if (group.hasBarLine) { 11273 if (group.barSize) { 11274 ruleWidth = calculateSize(group.barSize, options); 11275 rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth); 11276 } else { 11277 rule = buildCommon.makeLineSpan("frac-line", options); 11278 } 11279 11280 ruleWidth = rule.height; 11281 ruleSpacing = rule.height; 11282 } else { 11283 rule = null; 11284 ruleWidth = 0; 11285 ruleSpacing = options.fontMetrics().defaultRuleThickness; 11286 } // Rule 15b 11287 11288 11289 var numShift; 11290 var clearance; 11291 var denomShift; 11292 11293 if (style.size === Style$1.DISPLAY.size || group.size === "display") { 11294 numShift = options.fontMetrics().num1; 11295 11296 if (ruleWidth > 0) { 11297 clearance = 3 * ruleSpacing; 11298 } else { 11299 clearance = 7 * ruleSpacing; 11300 } 11301 11302 denomShift = options.fontMetrics().denom1; 11303 } else { 11304 if (ruleWidth > 0) { 11305 numShift = options.fontMetrics().num2; 11306 clearance = ruleSpacing; 11307 } else { 11308 numShift = options.fontMetrics().num3; 11309 clearance = 3 * ruleSpacing; 11310 } 11311 11312 denomShift = options.fontMetrics().denom2; 11313 } 11314 11315 var frac; 11316 11317 if (!rule) { 11318 // Rule 15c 11319 var candidateClearance = numShift - numerm.depth - (denomm.height - denomShift); 11320 11321 if (candidateClearance < clearance) { 11322 numShift += 0.5 * (clearance - candidateClearance); 11323 denomShift += 0.5 * (clearance - candidateClearance); 11324 } 11325 11326 frac = buildCommon.makeVList({ 11327 positionType: "individualShift", 11328 children: [{ 11329 type: "elem", 11330 elem: denomm, 11331 shift: denomShift 11332 }, { 11333 type: "elem", 11334 elem: numerm, 11335 shift: -numShift 11336 }] 11337 }, options); 11338 } else { 11339 // Rule 15d 11340 var axisHeight = options.fontMetrics().axisHeight; 11341 11342 if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) { 11343 numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth)); 11344 } 11345 11346 if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) { 11347 denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift)); 11348 } 11349 11350 var midShift = -(axisHeight - 0.5 * ruleWidth); 11351 frac = buildCommon.makeVList({ 11352 positionType: "individualShift", 11353 children: [{ 11354 type: "elem", 11355 elem: denomm, 11356 shift: denomShift 11357 }, { 11358 type: "elem", 11359 elem: rule, 11360 shift: midShift 11361 }, { 11362 type: "elem", 11363 elem: numerm, 11364 shift: -numShift 11365 }] 11366 }, options); 11367 } // Since we manually change the style sometimes (with \dfrac or \tfrac), 11368 // account for the possible size change here. 11369 11370 11371 newOptions = options.havingStyle(style); 11372 frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier; 11373 frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e 11374 11375 var delimSize; 11376 11377 if (style.size === Style$1.DISPLAY.size) { 11378 delimSize = options.fontMetrics().delim1; 11379 } else { 11380 delimSize = options.fontMetrics().delim2; 11381 } 11382 11383 var leftDelim; 11384 var rightDelim; 11385 11386 if (group.leftDelim == null) { 11387 leftDelim = makeNullDelimiter(options, ["mopen"]); 11388 } else { 11389 leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]); 11390 } 11391 11392 if (group.continued) { 11393 rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac 11394 } else if (group.rightDelim == null) { 11395 rightDelim = makeNullDelimiter(options, ["mclose"]); 11396 } else { 11397 rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]); 11398 } 11399 11400 return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options); 11401 }; 11402 11403 var mathmlBuilder$6 = (group, options) => { 11404 var node = new mathMLTree.MathNode("mfrac", [buildGroup$1(group.numer, options), buildGroup$1(group.denom, options)]); 11405 11406 if (!group.hasBarLine) { 11407 node.setAttribute("linethickness", "0px"); 11408 } else if (group.barSize) { 11409 var ruleWidth = calculateSize(group.barSize, options); 11410 node.setAttribute("linethickness", ruleWidth + "em"); 11411 } 11412 11413 var style = adjustStyle(group.size, options.style); 11414 11415 if (style.size !== options.style.size) { 11416 node = new mathMLTree.MathNode("mstyle", [node]); 11417 var isDisplay = style.size === Style$1.DISPLAY.size ? "true" : "false"; 11418 node.setAttribute("displaystyle", isDisplay); 11419 node.setAttribute("scriptlevel", "0"); 11420 } 11421 11422 if (group.leftDelim != null || group.rightDelim != null) { 11423 var withDelims = []; 11424 11425 if (group.leftDelim != null) { 11426 var leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]); 11427 leftOp.setAttribute("fence", "true"); 11428 withDelims.push(leftOp); 11429 } 11430 11431 withDelims.push(node); 11432 11433 if (group.rightDelim != null) { 11434 var rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]); 11435 rightOp.setAttribute("fence", "true"); 11436 withDelims.push(rightOp); 11437 } 11438 11439 return makeRow(withDelims); 11440 } 11441 11442 return node; 11443 }; 11444 11445 defineFunction({ 11446 type: "genfrac", 11447 names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly 11448 "\\\\bracefrac", "\\\\brackfrac" // ditto 11449 ], 11450 props: { 11451 numArgs: 2, 11452 allowedInArgument: true 11453 }, 11454 handler: (_ref, args) => { 11455 var { 11456 parser, 11457 funcName 11458 } = _ref; 11459 var numer = args[0]; 11460 var denom = args[1]; 11461 var hasBarLine; 11462 var leftDelim = null; 11463 var rightDelim = null; 11464 var size = "auto"; 11465 11466 switch (funcName) { 11467 case "\\dfrac": 11468 case "\\frac": 11469 case "\\tfrac": 11470 hasBarLine = true; 11471 break; 11472 11473 case "\\\\atopfrac": 11474 hasBarLine = false; 11475 break; 11476 11477 case "\\dbinom": 11478 case "\\binom": 11479 case "\\tbinom": 11480 hasBarLine = false; 11481 leftDelim = "("; 11482 rightDelim = ")"; 11483 break; 11484 11485 case "\\\\bracefrac": 11486 hasBarLine = false; 11487 leftDelim = "\\{"; 11488 rightDelim = "\\}"; 11489 break; 11490 11491 case "\\\\brackfrac": 11492 hasBarLine = false; 11493 leftDelim = "["; 11494 rightDelim = "]"; 11495 break; 11496 11497 default: 11498 throw new Error("Unrecognized genfrac command"); 11499 } 11500 11501 switch (funcName) { 11502 case "\\dfrac": 11503 case "\\dbinom": 11504 size = "display"; 11505 break; 11506 11507 case "\\tfrac": 11508 case "\\tbinom": 11509 size = "text"; 11510 break; 11511 } 11512 11513 return { 11514 type: "genfrac", 11515 mode: parser.mode, 11516 continued: false, 11517 numer, 11518 denom, 11519 hasBarLine, 11520 leftDelim, 11521 rightDelim, 11522 size, 11523 barSize: null 11524 }; 11525 }, 11526 htmlBuilder: htmlBuilder$6, 11527 mathmlBuilder: mathmlBuilder$6 11528 }); 11529 defineFunction({ 11530 type: "genfrac", 11531 names: ["\\cfrac"], 11532 props: { 11533 numArgs: 2 11534 }, 11535 handler: (_ref2, args) => { 11536 var { 11537 parser, 11538 funcName 11539 } = _ref2; 11540 var numer = args[0]; 11541 var denom = args[1]; 11542 return { 11543 type: "genfrac", 11544 mode: parser.mode, 11545 continued: true, 11546 numer, 11547 denom, 11548 hasBarLine: true, 11549 leftDelim: null, 11550 rightDelim: null, 11551 size: "display", 11552 barSize: null 11553 }; 11554 } 11555 }); // Infix generalized fractions -- these are not rendered directly, but replaced 11556 // immediately by one of the variants above. 11557 11558 defineFunction({ 11559 type: "infix", 11560 names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], 11561 props: { 11562 numArgs: 0, 11563 infix: true 11564 }, 11565 11566 handler(_ref3) { 11567 var { 11568 parser, 11569 funcName, 11570 token 11571 } = _ref3; 11572 var replaceWith; 11573 11574 switch (funcName) { 11575 case "\\over": 11576 replaceWith = "\\frac"; 11577 break; 11578 11579 case "\\choose": 11580 replaceWith = "\\binom"; 11581 break; 11582 11583 case "\\atop": 11584 replaceWith = "\\\\atopfrac"; 11585 break; 11586 11587 case "\\brace": 11588 replaceWith = "\\\\bracefrac"; 11589 break; 11590 11591 case "\\brack": 11592 replaceWith = "\\\\brackfrac"; 11593 break; 11594 11595 default: 11596 throw new Error("Unrecognized infix genfrac command"); 11597 } 11598 11599 return { 11600 type: "infix", 11601 mode: parser.mode, 11602 replaceWith, 11603 token 11604 }; 11605 } 11606 11607 }); 11608 var stylArray = ["display", "text", "script", "scriptscript"]; 11609 11610 var delimFromValue = function delimFromValue(delimString) { 11611 var delim = null; 11612 11613 if (delimString.length > 0) { 11614 delim = delimString; 11615 delim = delim === "." ? null : delim; 11616 } 11617 11618 return delim; 11619 }; 11620 11621 defineFunction({ 11622 type: "genfrac", 11623 names: ["\\genfrac"], 11624 props: { 11625 numArgs: 6, 11626 allowedInArgument: true, 11627 argTypes: ["math", "math", "size", "text", "math", "math"] 11628 }, 11629 11630 handler(_ref4, args) { 11631 var { 11632 parser 11633 } = _ref4; 11634 var numer = args[4]; 11635 var denom = args[5]; // Look into the parse nodes to get the desired delimiters. 11636 11637 var leftNode = normalizeArgument(args[0]); 11638 var leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null; 11639 var rightNode = normalizeArgument(args[1]); 11640 var rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null; 11641 var barNode = assertNodeType(args[2], "size"); 11642 var hasBarLine; 11643 var barSize = null; 11644 11645 if (barNode.isBlank) { 11646 // \genfrac acts differently than \above. 11647 // \genfrac treats an empty size group as a signal to use a 11648 // standard bar size. \above would see size = 0 and omit the bar. 11649 hasBarLine = true; 11650 } else { 11651 barSize = barNode.value; 11652 hasBarLine = barSize.number > 0; 11653 } // Find out if we want displaystyle, textstyle, etc. 11654 11655 11656 var size = "auto"; 11657 var styl = args[3]; 11658 11659 if (styl.type === "ordgroup") { 11660 if (styl.body.length > 0) { 11661 var textOrd = assertNodeType(styl.body[0], "textord"); 11662 size = stylArray[Number(textOrd.text)]; 11663 } 11664 } else { 11665 styl = assertNodeType(styl, "textord"); 11666 size = stylArray[Number(styl.text)]; 11667 } 11668 11669 return { 11670 type: "genfrac", 11671 mode: parser.mode, 11672 numer, 11673 denom, 11674 continued: false, 11675 hasBarLine, 11676 barSize, 11677 leftDelim, 11678 rightDelim, 11679 size 11680 }; 11681 }, 11682 11683 htmlBuilder: htmlBuilder$6, 11684 mathmlBuilder: mathmlBuilder$6 11685 }); // \above is an infix fraction that also defines a fraction bar size. 11686 11687 defineFunction({ 11688 type: "infix", 11689 names: ["\\above"], 11690 props: { 11691 numArgs: 1, 11692 argTypes: ["size"], 11693 infix: true 11694 }, 11695 11696 handler(_ref5, args) { 11697 var { 11698 parser, 11699 funcName, 11700 token 11701 } = _ref5; 11702 return { 11703 type: "infix", 11704 mode: parser.mode, 11705 replaceWith: "\\\\abovefrac", 11706 size: assertNodeType(args[0], "size").value, 11707 token 11708 }; 11709 } 11710 11711 }); 11712 defineFunction({ 11713 type: "genfrac", 11714 names: ["\\\\abovefrac"], 11715 props: { 11716 numArgs: 3, 11717 argTypes: ["math", "size", "math"] 11718 }, 11719 handler: (_ref6, args) => { 11720 var { 11721 parser, 11722 funcName 11723 } = _ref6; 11724 var numer = args[0]; 11725 var barSize = assert(assertNodeType(args[1], "infix").size); 11726 var denom = args[2]; 11727 var hasBarLine = barSize.number > 0; 11728 return { 11729 type: "genfrac", 11730 mode: parser.mode, 11731 numer, 11732 denom, 11733 continued: false, 11734 hasBarLine, 11735 barSize, 11736 leftDelim: null, 11737 rightDelim: null, 11738 size: "auto" 11739 }; 11740 }, 11741 htmlBuilder: htmlBuilder$6, 11742 mathmlBuilder: mathmlBuilder$6 11743 }); 11744 11745 // NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but 11746 // also "supsub" since an over/underbrace can affect super/subscripting. 11747 var htmlBuilder$7 = (grp, options) => { 11748 var style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node. 11749 11750 var supSubGroup; 11751 var group; 11752 11753 if (grp.type === "supsub") { 11754 // Ref: LaTeX source2e: }}}}\limits} 11755 // i.e. LaTeX treats the brace similar to an op and passes it 11756 // with \limits, so we need to assign supsub style. 11757 supSubGroup = grp.sup ? buildGroup(grp.sup, options.havingStyle(style.sup()), options) : buildGroup(grp.sub, options.havingStyle(style.sub()), options); 11758 group = assertNodeType(grp.base, "horizBrace"); 11759 } else { 11760 group = assertNodeType(grp, "horizBrace"); 11761 } // Build the base group 11762 11763 11764 var body = buildGroup(group.base, options.havingBaseStyle(Style$1.DISPLAY)); // Create the stretchy element 11765 11766 var braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns ┏━━━━━━━━┓ 11767 // This first vlist contains the content and the brace: equation 11768 11769 var vlist; 11770 11771 if (group.isOver) { 11772 vlist = buildCommon.makeVList({ 11773 positionType: "firstBaseline", 11774 children: [{ 11775 type: "elem", 11776 elem: body 11777 }, { 11778 type: "kern", 11779 size: 0.1 11780 }, { 11781 type: "elem", 11782 elem: braceBody 11783 }] 11784 }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList. 11785 11786 vlist.children[0].children[0].children[1].classes.push("svg-align"); 11787 } else { 11788 vlist = buildCommon.makeVList({ 11789 positionType: "bottom", 11790 positionData: body.depth + 0.1 + braceBody.height, 11791 children: [{ 11792 type: "elem", 11793 elem: braceBody 11794 }, { 11795 type: "kern", 11796 size: 0.1 11797 }, { 11798 type: "elem", 11799 elem: body 11800 }] 11801 }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList. 11802 11803 vlist.children[0].children[0].children[0].classes.push("svg-align"); 11804 } 11805 11806 if (supSubGroup) { 11807 // To write the supsub, wrap the first vlist in another vlist: 11808 // They can't all go in the same vlist, because the note might be 11809 // wider than the equation. We want the equation to control the 11810 // brace width. 11811 // note long note long note 11812 // ┏━━━━━━━━┓ or ┏━━━┓ not ┏━━━━━━━━━┓ 11813 // equation eqn eqn 11814 var vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options); 11815 11816 if (group.isOver) { 11817 vlist = buildCommon.makeVList({ 11818 positionType: "firstBaseline", 11819 children: [{ 11820 type: "elem", 11821 elem: vSpan 11822 }, { 11823 type: "kern", 11824 size: 0.2 11825 }, { 11826 type: "elem", 11827 elem: supSubGroup 11828 }] 11829 }, options); 11830 } else { 11831 vlist = buildCommon.makeVList({ 11832 positionType: "bottom", 11833 positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth, 11834 children: [{ 11835 type: "elem", 11836 elem: supSubGroup 11837 }, { 11838 type: "kern", 11839 size: 0.2 11840 }, { 11841 type: "elem", 11842 elem: vSpan 11843 }] 11844 }, options); 11845 } 11846 } 11847 11848 return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options); 11849 }; 11850 11851 var mathmlBuilder$7 = (group, options) => { 11852 var accentNode = stretchy.mathMLnode(group.label); 11853 return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildGroup$1(group.base, options), accentNode]); 11854 }; // Horizontal stretchy braces 11855 11856 11857 defineFunction({ 11858 type: "horizBrace", 11859 names: ["\\overbrace", "\\underbrace"], 11860 props: { 11861 numArgs: 1 11862 }, 11863 11864 handler(_ref, args) { 11865 var { 11866 parser, 11867 funcName 11868 } = _ref; 11869 return { 11870 type: "horizBrace", 11871 mode: parser.mode, 11872 label: funcName, 11873 isOver: /^\\over/.test(funcName), 11874 base: args[0] 11875 }; 11876 }, 11877 11878 htmlBuilder: htmlBuilder$7, 11879 mathmlBuilder: mathmlBuilder$7 11880 }); 11881 11882 defineFunction({ 11883 type: "href", 11884 names: ["\\href"], 11885 props: { 11886 numArgs: 2, 11887 argTypes: ["url", "original"], 11888 allowedInText: true 11889 }, 11890 handler: (_ref, args) => { 11891 var { 11892 parser 11893 } = _ref; 11894 var body = args[1]; 11895 var href = assertNodeType(args[0], "url").url; 11896 11897 if (!parser.settings.isTrusted({ 11898 command: "\\href", 11899 url: href 11900 })) { 11901 return parser.formatUnsupportedCmd("\\href"); 11902 } 11903 11904 return { 11905 type: "href", 11906 mode: parser.mode, 11907 href, 11908 body: ordargument(body) 11909 }; 11910 }, 11911 htmlBuilder: (group, options) => { 11912 var elements = buildExpression(group.body, options, false); 11913 return buildCommon.makeAnchor(group.href, [], elements, options); 11914 }, 11915 mathmlBuilder: (group, options) => { 11916 var math = buildExpressionRow(group.body, options); 11917 11918 if (!(math instanceof MathNode)) { 11919 math = new MathNode("mrow", [math]); 11920 } 11921 11922 math.setAttribute("href", group.href); 11923 return math; 11924 } 11925 }); 11926 defineFunction({ 11927 type: "href", 11928 names: ["\\url"], 11929 props: { 11930 numArgs: 1, 11931 argTypes: ["url"], 11932 allowedInText: true 11933 }, 11934 handler: (_ref2, args) => { 11935 var { 11936 parser 11937 } = _ref2; 11938 var href = assertNodeType(args[0], "url").url; 11939 11940 if (!parser.settings.isTrusted({ 11941 command: "\\url", 11942 url: href 11943 })) { 11944 return parser.formatUnsupportedCmd("\\url"); 11945 } 11946 11947 var chars = []; 11948 11949 for (var i = 0; i < href.length; i++) { 11950 var c = href[i]; 11951 11952 if (c === "~") { 11953 c = "\\textasciitilde"; 11954 } 11955 11956 chars.push({ 11957 type: "textord", 11958 mode: "text", 11959 text: c 11960 }); 11961 } 11962 11963 var body = { 11964 type: "text", 11965 mode: parser.mode, 11966 font: "\\texttt", 11967 body: chars 11968 }; 11969 return { 11970 type: "href", 11971 mode: parser.mode, 11972 href, 11973 body: ordargument(body) 11974 }; 11975 } 11976 }); 11977 11978 // In LaTeX, \vcenter can act only on a box, as in 11979 // \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}} 11980 // This function by itself doesn't do anything but prevent a soft line break. 11981 11982 defineFunction({ 11983 type: "hbox", 11984 names: ["\\hbox"], 11985 props: { 11986 numArgs: 1, 11987 argTypes: ["text"], 11988 allowedInText: true, 11989 primitive: true 11990 }, 11991 11992 handler(_ref, args) { 11993 var { 11994 parser 11995 } = _ref; 11996 return { 11997 type: "hbox", 11998 mode: parser.mode, 11999 body: ordargument(args[0]) 12000 }; 12001 }, 12002 12003 htmlBuilder(group, options) { 12004 var elements = buildExpression(group.body, options, false); 12005 return buildCommon.makeFragment(elements); 12006 }, 12007 12008 mathmlBuilder(group, options) { 12009 return new mathMLTree.MathNode("mrow", buildExpression$1(group.body, options)); 12010 } 12011 12012 }); 12013 12014 defineFunction({ 12015 type: "html", 12016 names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"], 12017 props: { 12018 numArgs: 2, 12019 argTypes: ["raw", "original"], 12020 allowedInText: true 12021 }, 12022 handler: (_ref, args) => { 12023 var { 12024 parser, 12025 funcName, 12026 token 12027 } = _ref; 12028 var value = assertNodeType(args[0], "raw").string; 12029 var body = args[1]; 12030 12031 if (parser.settings.strict) { 12032 parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode"); 12033 } 12034 12035 var trustContext; 12036 var attributes = {}; 12037 12038 switch (funcName) { 12039 case "\\htmlClass": 12040 attributes.class = value; 12041 trustContext = { 12042 command: "\\htmlClass", 12043 class: value 12044 }; 12045 break; 12046 12047 case "\\htmlId": 12048 attributes.id = value; 12049 trustContext = { 12050 command: "\\htmlId", 12051 id: value 12052 }; 12053 break; 12054 12055 case "\\htmlStyle": 12056 attributes.style = value; 12057 trustContext = { 12058 command: "\\htmlStyle", 12059 style: value 12060 }; 12061 break; 12062 12063 case "\\htmlData": 12064 { 12065 var data = value.split(","); 12066 12067 for (var i = 0; i < data.length; i++) { 12068 var keyVal = data[i].split("="); 12069 12070 if (keyVal.length !== 2) { 12071 throw new ParseError("Error parsing key-value for \\htmlData"); 12072 } 12073 12074 attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); 12075 } 12076 12077 trustContext = { 12078 command: "\\htmlData", 12079 attributes 12080 }; 12081 break; 12082 } 12083 12084 default: 12085 throw new Error("Unrecognized html command"); 12086 } 12087 12088 if (!parser.settings.isTrusted(trustContext)) { 12089 return parser.formatUnsupportedCmd(funcName); 12090 } 12091 12092 return { 12093 type: "html", 12094 mode: parser.mode, 12095 attributes, 12096 body: ordargument(body) 12097 }; 12098 }, 12099 htmlBuilder: (group, options) => { 12100 var elements = buildExpression(group.body, options, false); 12101 var classes = ["enclosing"]; 12102 12103 if (group.attributes.class) { 12104 classes.push(...group.attributes.class.trim().split(/\s+/)); 12105 } 12106 12107 var span = buildCommon.makeSpan(classes, elements, options); 12108 12109 for (var attr in group.attributes) { 12110 if (attr !== "class" && group.attributes.hasOwnProperty(attr)) { 12111 span.setAttribute(attr, group.attributes[attr]); 12112 } 12113 } 12114 12115 return span; 12116 }, 12117 mathmlBuilder: (group, options) => { 12118 return buildExpressionRow(group.body, options); 12119 } 12120 }); 12121 12122 defineFunction({ 12123 type: "htmlmathml", 12124 names: ["\\html@mathml"], 12125 props: { 12126 numArgs: 2, 12127 allowedInText: true 12128 }, 12129 handler: (_ref, args) => { 12130 var { 12131 parser 12132 } = _ref; 12133 return { 12134 type: "htmlmathml", 12135 mode: parser.mode, 12136 html: ordargument(args[0]), 12137 mathml: ordargument(args[1]) 12138 }; 12139 }, 12140 htmlBuilder: (group, options) => { 12141 var elements = buildExpression(group.html, options, false); 12142 return buildCommon.makeFragment(elements); 12143 }, 12144 mathmlBuilder: (group, options) => { 12145 return buildExpressionRow(group.mathml, options); 12146 } 12147 }); 12148 12149 var sizeData = function sizeData(str) { 12150 if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { 12151 // str is a number with no unit specified. 12152 // default unit is bp, per graphix package. 12153 return { 12154 number: +str, 12155 unit: "bp" 12156 }; 12157 } else { 12158 var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); 12159 12160 if (!match) { 12161 throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); 12162 } 12163 12164 var data = { 12165 number: +(match[1] + match[2]), 12166 // sign + magnitude, cast to number 12167 unit: match[3] 12168 }; 12169 12170 if (!validUnit(data)) { 12171 throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); 12172 } 12173 12174 return data; 12175 } 12176 }; 12177 12178 defineFunction({ 12179 type: "includegraphics", 12180 names: ["\\includegraphics"], 12181 props: { 12182 numArgs: 1, 12183 numOptionalArgs: 1, 12184 argTypes: ["raw", "url"], 12185 allowedInText: false 12186 }, 12187 handler: (_ref, args, optArgs) => { 12188 var { 12189 parser 12190 } = _ref; 12191 var width = { 12192 number: 0, 12193 unit: "em" 12194 }; 12195 var height = { 12196 number: 0.9, 12197 unit: "em" 12198 }; // sorta character sized. 12199 12200 var totalheight = { 12201 number: 0, 12202 unit: "em" 12203 }; 12204 var alt = ""; 12205 12206 if (optArgs[0]) { 12207 var attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string. 12208 12209 var attributes = attributeStr.split(","); 12210 12211 for (var i = 0; i < attributes.length; i++) { 12212 var keyVal = attributes[i].split("="); 12213 12214 if (keyVal.length === 2) { 12215 var str = keyVal[1].trim(); 12216 12217 switch (keyVal[0].trim()) { 12218 case "alt": 12219 alt = str; 12220 break; 12221 12222 case "width": 12223 width = sizeData(str); 12224 break; 12225 12226 case "height": 12227 height = sizeData(str); 12228 break; 12229 12230 case "totalheight": 12231 totalheight = sizeData(str); 12232 break; 12233 12234 default: 12235 throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics."); 12236 } 12237 } 12238 } 12239 } 12240 12241 var src = assertNodeType(args[0], "url").url; 12242 12243 if (alt === "") { 12244 // No alt given. Use the file name. Strip away the path. 12245 alt = src; 12246 alt = alt.replace(/^.*[\\/]/, ''); 12247 alt = alt.substring(0, alt.lastIndexOf('.')); 12248 } 12249 12250 if (!parser.settings.isTrusted({ 12251 command: "\\includegraphics", 12252 url: src 12253 })) { 12254 return parser.formatUnsupportedCmd("\\includegraphics"); 12255 } 12256 12257 return { 12258 type: "includegraphics", 12259 mode: parser.mode, 12260 alt: alt, 12261 width: width, 12262 height: height, 12263 totalheight: totalheight, 12264 src: src 12265 }; 12266 }, 12267 htmlBuilder: (group, options) => { 12268 var height = calculateSize(group.height, options); 12269 var depth = 0; 12270 12271 if (group.totalheight.number > 0) { 12272 depth = calculateSize(group.totalheight, options) - height; 12273 depth = Number(depth.toFixed(2)); 12274 } 12275 12276 var width = 0; 12277 12278 if (group.width.number > 0) { 12279 width = calculateSize(group.width, options); 12280 } 12281 12282 var style = { 12283 height: height + depth + "em" 12284 }; 12285 12286 if (width > 0) { 12287 style.width = width + "em"; 12288 } 12289 12290 if (depth > 0) { 12291 style.verticalAlign = -depth + "em"; 12292 } 12293 12294 var node = new Img(group.src, group.alt, style); 12295 node.height = height; 12296 node.depth = depth; 12297 return node; 12298 }, 12299 mathmlBuilder: (group, options) => { 12300 var node = new mathMLTree.MathNode("mglyph", []); 12301 node.setAttribute("alt", group.alt); 12302 var height = calculateSize(group.height, options); 12303 var depth = 0; 12304 12305 if (group.totalheight.number > 0) { 12306 depth = calculateSize(group.totalheight, options) - height; 12307 depth = depth.toFixed(2); 12308 node.setAttribute("valign", "-" + depth + "em"); 12309 } 12310 12311 node.setAttribute("height", height + depth + "em"); 12312 12313 if (group.width.number > 0) { 12314 var width = calculateSize(group.width, options); 12315 node.setAttribute("width", width + "em"); 12316 } 12317 12318 node.setAttribute("src", group.src); 12319 return node; 12320 } 12321 }); 12322 12323 // Horizontal spacing commands 12324 12325 defineFunction({ 12326 type: "kern", 12327 names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], 12328 props: { 12329 numArgs: 1, 12330 argTypes: ["size"], 12331 primitive: true, 12332 allowedInText: true 12333 }, 12334 12335 handler(_ref, args) { 12336 var { 12337 parser, 12338 funcName 12339 } = _ref; 12340 var size = assertNodeType(args[0], "size"); 12341 12342 if (parser.settings.strict) { 12343 var mathFunction = funcName[1] === 'm'; // \mkern, \mskip 12344 12345 var muUnit = size.value.unit === 'mu'; 12346 12347 if (mathFunction) { 12348 if (!muUnit) { 12349 parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units")); 12350 } 12351 12352 if (parser.mode !== "math") { 12353 parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode"); 12354 } 12355 } else { 12356 // !mathFunction 12357 if (muUnit) { 12358 parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units"); 12359 } 12360 } 12361 } 12362 12363 return { 12364 type: "kern", 12365 mode: parser.mode, 12366 dimension: size.value 12367 }; 12368 }, 12369 12370 htmlBuilder(group, options) { 12371 return buildCommon.makeGlue(group.dimension, options); 12372 }, 12373 12374 mathmlBuilder(group, options) { 12375 var dimension = calculateSize(group.dimension, options); 12376 return new mathMLTree.SpaceNode(dimension); 12377 } 12378 12379 }); 12380 12381 // Horizontal overlap functions 12382 defineFunction({ 12383 type: "lap", 12384 names: ["\\mathllap", "\\mathrlap", "\\mathclap"], 12385 props: { 12386 numArgs: 1, 12387 allowedInText: true 12388 }, 12389 handler: (_ref, args) => { 12390 var { 12391 parser, 12392 funcName 12393 } = _ref; 12394 var body = args[0]; 12395 return { 12396 type: "lap", 12397 mode: parser.mode, 12398 alignment: funcName.slice(5), 12399 body 12400 }; 12401 }, 12402 htmlBuilder: (group, options) => { 12403 // mathllap, mathrlap, mathclap 12404 var inner; 12405 12406 if (group.alignment === "clap") { 12407 // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/ 12408 inner = buildCommon.makeSpan([], [buildGroup(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span 12409 12410 inner = buildCommon.makeSpan(["inner"], [inner], options); 12411 } else { 12412 inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options)]); 12413 } 12414 12415 var fix = buildCommon.makeSpan(["fix"], []); 12416 var node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the 12417 // two items involved in the lap. 12418 // Next, use a strut to set the height of the HTML bounding box. 12419 // Otherwise, a tall argument may be misplaced. 12420 // This code resolved issue #1153 12421 12422 var strut = buildCommon.makeSpan(["strut"]); 12423 strut.style.height = node.height + node.depth + "em"; 12424 strut.style.verticalAlign = -node.depth + "em"; 12425 node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall. 12426 // This code resolves issue #1234 12427 12428 node = buildCommon.makeSpan(["thinbox"], [node], options); 12429 return buildCommon.makeSpan(["mord", "vbox"], [node], options); 12430 }, 12431 mathmlBuilder: (group, options) => { 12432 // mathllap, mathrlap, mathclap 12433 var node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]); 12434 12435 if (group.alignment !== "rlap") { 12436 var offset = group.alignment === "llap" ? "-1" : "-0.5"; 12437 node.setAttribute("lspace", offset + "width"); 12438 } 12439 12440 node.setAttribute("width", "0px"); 12441 return node; 12442 } 12443 }); 12444 12445 defineFunction({ 12446 type: "styling", 12447 names: ["\\(", "$"], 12448 props: { 12449 numArgs: 0, 12450 allowedInText: true, 12451 allowedInMath: false 12452 }, 12453 12454 handler(_ref, args) { 12455 var { 12456 funcName, 12457 parser 12458 } = _ref; 12459 var outerMode = parser.mode; 12460 parser.switchMode("math"); 12461 var close = funcName === "\\(" ? "\\)" : "$"; 12462 var body = parser.parseExpression(false, close); 12463 parser.expect(close); 12464 parser.switchMode(outerMode); 12465 return { 12466 type: "styling", 12467 mode: parser.mode, 12468 style: "text", 12469 body 12470 }; 12471 } 12472 12473 }); // Check for extra closing math delimiters 12474 12475 defineFunction({ 12476 type: "text", 12477 // Doesn't matter what this is. 12478 names: ["\\)", "\\]"], 12479 props: { 12480 numArgs: 0, 12481 allowedInText: true, 12482 allowedInMath: false 12483 }, 12484 12485 handler(context, args) { 12486 throw new ParseError("Mismatched " + context.funcName); 12487 } 12488 12489 }); 12490 12491 var chooseMathStyle = (group, options) => { 12492 switch (options.style.size) { 12493 case Style$1.DISPLAY.size: 12494 return group.display; 12495 12496 case Style$1.TEXT.size: 12497 return group.text; 12498 12499 case Style$1.SCRIPT.size: 12500 return group.script; 12501 12502 case Style$1.SCRIPTSCRIPT.size: 12503 return group.scriptscript; 12504 12505 default: 12506 return group.text; 12507 } 12508 }; 12509 12510 defineFunction({ 12511 type: "mathchoice", 12512 names: ["\\mathchoice"], 12513 props: { 12514 numArgs: 4, 12515 primitive: true 12516 }, 12517 handler: (_ref, args) => { 12518 var { 12519 parser 12520 } = _ref; 12521 return { 12522 type: "mathchoice", 12523 mode: parser.mode, 12524 display: ordargument(args[0]), 12525 text: ordargument(args[1]), 12526 script: ordargument(args[2]), 12527 scriptscript: ordargument(args[3]) 12528 }; 12529 }, 12530 htmlBuilder: (group, options) => { 12531 var body = chooseMathStyle(group, options); 12532 var elements = buildExpression(body, options, false); 12533 return buildCommon.makeFragment(elements); 12534 }, 12535 mathmlBuilder: (group, options) => { 12536 var body = chooseMathStyle(group, options); 12537 return buildExpressionRow(body, options); 12538 } 12539 }); 12540 12541 // For an operator with limits, assemble the base, sup, and sub into a span. 12542 var assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => { 12543 base = buildCommon.makeSpan([], [base]); 12544 var sub; 12545 var sup; // We manually have to handle the superscripts and subscripts. This, 12546 // aside from the kern calculations, is copied from supsub. 12547 12548 if (supGroup) { 12549 var elem = buildGroup(supGroup, options.havingStyle(style.sup()), options); 12550 sup = { 12551 elem, 12552 kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth) 12553 }; 12554 } 12555 12556 if (subGroup) { 12557 var _elem = buildGroup(subGroup, options.havingStyle(style.sub()), options); 12558 12559 sub = { 12560 elem: _elem, 12561 kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - _elem.height) 12562 }; 12563 } // Build the final group as a vlist of the possible subscript, base, 12564 // and possible superscript. 12565 12566 12567 var finalGroup; 12568 12569 if (sup && sub) { 12570 var bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift; 12571 finalGroup = buildCommon.makeVList({ 12572 positionType: "bottom", 12573 positionData: bottom, 12574 children: [{ 12575 type: "kern", 12576 size: options.fontMetrics().bigOpSpacing5 12577 }, { 12578 type: "elem", 12579 elem: sub.elem, 12580 marginLeft: -slant + "em" 12581 }, { 12582 type: "kern", 12583 size: sub.kern 12584 }, { 12585 type: "elem", 12586 elem: base 12587 }, { 12588 type: "kern", 12589 size: sup.kern 12590 }, { 12591 type: "elem", 12592 elem: sup.elem, 12593 marginLeft: slant + "em" 12594 }, { 12595 type: "kern", 12596 size: options.fontMetrics().bigOpSpacing5 12597 }] 12598 }, options); 12599 } else if (sub) { 12600 var top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note 12601 // that we are supposed to shift the limits by 1/2 of the slant, 12602 // but since we are centering the limits adding a full slant of 12603 // margin will shift by 1/2 that. 12604 12605 finalGroup = buildCommon.makeVList({ 12606 positionType: "top", 12607 positionData: top, 12608 children: [{ 12609 type: "kern", 12610 size: options.fontMetrics().bigOpSpacing5 12611 }, { 12612 type: "elem", 12613 elem: sub.elem, 12614 marginLeft: -slant + "em" 12615 }, { 12616 type: "kern", 12617 size: sub.kern 12618 }, { 12619 type: "elem", 12620 elem: base 12621 }] 12622 }, options); 12623 } else if (sup) { 12624 var _bottom = base.depth + baseShift; 12625 12626 finalGroup = buildCommon.makeVList({ 12627 positionType: "bottom", 12628 positionData: _bottom, 12629 children: [{ 12630 type: "elem", 12631 elem: base 12632 }, { 12633 type: "kern", 12634 size: sup.kern 12635 }, { 12636 type: "elem", 12637 elem: sup.elem, 12638 marginLeft: slant + "em" 12639 }, { 12640 type: "kern", 12641 size: options.fontMetrics().bigOpSpacing5 12642 }] 12643 }, options); 12644 } else { 12645 // This case probably shouldn't occur (this would mean the 12646 // supsub was sending us a group with no superscript or 12647 // subscript) but be safe. 12648 return base; 12649 } 12650 12651 return buildCommon.makeSpan(["mop", "op-limits"], [finalGroup], options); 12652 }; 12653 12654 // Limits, symbols 12655 // Most operators have a large successor symbol, but these don't. 12656 var noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also 12657 // "supsub" since some of them (like \int) can affect super/subscripting. 12658 12659 var htmlBuilder$8 = (grp, options) => { 12660 // Operators are handled in the TeXbook pg. 443-444, rule 13(a). 12661 var supGroup; 12662 var subGroup; 12663 var hasLimits = false; 12664 var group; 12665 12666 if (grp.type === "supsub") { 12667 // If we have limits, supsub will pass us its group to handle. Pull 12668 // out the superscript and subscript and set the group to the op in 12669 // its base. 12670 supGroup = grp.sup; 12671 subGroup = grp.sub; 12672 group = assertNodeType(grp.base, "op"); 12673 hasLimits = true; 12674 } else { 12675 group = assertNodeType(grp, "op"); 12676 } 12677 12678 var style = options.style; 12679 var large = false; 12680 12681 if (style.size === Style$1.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) { 12682 // Most symbol operators get larger in displaystyle (rule 13) 12683 large = true; 12684 } 12685 12686 var base; 12687 12688 if (group.symbol) { 12689 // If this is a symbol, create the symbol. 12690 var fontName = large ? "Size2-Regular" : "Size1-Regular"; 12691 var stash = ""; 12692 12693 if (group.name === "\\oiint" || group.name === "\\oiiint") { 12694 // No font glyphs yet, so use a glyph w/o the oval. 12695 // TODO: When font glyphs are available, delete this code. 12696 stash = group.name.substr(1); 12697 group.name = stash === "oiint" ? "\\iint" : "\\iiint"; 12698 } 12699 12700 base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]); 12701 12702 if (stash.length > 0) { 12703 // We're in \oiint or \oiiint. Overlay the oval. 12704 // TODO: When font glyphs are available, delete this code. 12705 var italic = base.italic; 12706 var oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options); 12707 base = buildCommon.makeVList({ 12708 positionType: "individualShift", 12709 children: [{ 12710 type: "elem", 12711 elem: base, 12712 shift: 0 12713 }, { 12714 type: "elem", 12715 elem: oval, 12716 shift: large ? 0.08 : 0 12717 }] 12718 }, options); 12719 group.name = "\\" + stash; 12720 base.classes.unshift("mop"); // $FlowFixMe 12721 12722 base.italic = italic; 12723 } 12724 } else if (group.body) { 12725 // If this is a list, compose that list. 12726 var inner = buildExpression(group.body, options, true); 12727 12728 if (inner.length === 1 && inner[0] instanceof SymbolNode) { 12729 base = inner[0]; 12730 base.classes[0] = "mop"; // replace old mclass 12731 } else { 12732 base = buildCommon.makeSpan(["mop"], inner, options); 12733 } 12734 } else { 12735 // Otherwise, this is a text operator. Build the text from the 12736 // operator's name. 12737 var output = []; 12738 12739 for (var i = 1; i < group.name.length; i++) { 12740 output.push(buildCommon.mathsym(group.name[i], group.mode, options)); 12741 } 12742 12743 base = buildCommon.makeSpan(["mop"], output, options); 12744 } // If content of op is a single symbol, shift it vertically. 12745 12746 12747 var baseShift = 0; 12748 var slant = 0; 12749 12750 if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) { 12751 // We suppress the shift of the base of \overset and \underset. Otherwise, 12752 // shift the symbol so its center lies on the axis (rule 13). It 12753 // appears that our fonts have the centers of the symbols already 12754 // almost on the axis, so these numbers are very small. Note we 12755 // don't actually apply this here, but instead it is used either in 12756 // the vlist creation or separately when there are no limits. 12757 baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction. 12758 // $FlowFixMe 12759 12760 slant = base.italic; 12761 } 12762 12763 if (hasLimits) { 12764 return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift); 12765 } else { 12766 if (baseShift) { 12767 base.style.position = "relative"; 12768 base.style.top = baseShift + "em"; 12769 } 12770 12771 return base; 12772 } 12773 }; 12774 12775 var mathmlBuilder$8 = (group, options) => { 12776 var node; 12777 12778 if (group.symbol) { 12779 // This is a symbol. Just add the symbol. 12780 node = new MathNode("mo", [makeText(group.name, group.mode)]); 12781 12782 if (utils.contains(noSuccessor, group.name)) { 12783 node.setAttribute("largeop", "false"); 12784 } 12785 } else if (group.body) { 12786 // This is an operator with children. Add them. 12787 node = new MathNode("mo", buildExpression$1(group.body, options)); 12788 } else { 12789 // This is a text operator. Add all of the characters from the 12790 // operator's name. 12791 node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an <mo>⁡</mo>. 12792 // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 12793 12794 var operator = new MathNode("mo", [makeText("\u2061", "text")]); 12795 12796 if (group.parentIsSupSub) { 12797 node = new MathNode("mrow", [node, operator]); 12798 } else { 12799 node = newDocumentFragment([node, operator]); 12800 } 12801 } 12802 12803 return node; 12804 }; 12805 12806 var singleCharBigOps = { 12807 "\u220F": "\\prod", 12808 "\u2210": "\\coprod", 12809 "\u2211": "\\sum", 12810 "\u22c0": "\\bigwedge", 12811 "\u22c1": "\\bigvee", 12812 "\u22c2": "\\bigcap", 12813 "\u22c3": "\\bigcup", 12814 "\u2a00": "\\bigodot", 12815 "\u2a01": "\\bigoplus", 12816 "\u2a02": "\\bigotimes", 12817 "\u2a04": "\\biguplus", 12818 "\u2a06": "\\bigsqcup" 12819 }; 12820 defineFunction({ 12821 type: "op", 12822 names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"], 12823 props: { 12824 numArgs: 0 12825 }, 12826 handler: (_ref, args) => { 12827 var { 12828 parser, 12829 funcName 12830 } = _ref; 12831 var fName = funcName; 12832 12833 if (fName.length === 1) { 12834 fName = singleCharBigOps[fName]; 12835 } 12836 12837 return { 12838 type: "op", 12839 mode: parser.mode, 12840 limits: true, 12841 parentIsSupSub: false, 12842 symbol: true, 12843 name: fName 12844 }; 12845 }, 12846 htmlBuilder: htmlBuilder$8, 12847 mathmlBuilder: mathmlBuilder$8 12848 }); // Note: calling defineFunction with a type that's already been defined only 12849 // works because the same htmlBuilder and mathmlBuilder are being used. 12850 12851 defineFunction({ 12852 type: "op", 12853 names: ["\\mathop"], 12854 props: { 12855 numArgs: 1, 12856 primitive: true 12857 }, 12858 handler: (_ref2, args) => { 12859 var { 12860 parser 12861 } = _ref2; 12862 var body = args[0]; 12863 return { 12864 type: "op", 12865 mode: parser.mode, 12866 limits: false, 12867 parentIsSupSub: false, 12868 symbol: false, 12869 body: ordargument(body) 12870 }; 12871 }, 12872 htmlBuilder: htmlBuilder$8, 12873 mathmlBuilder: mathmlBuilder$8 12874 }); // There are 2 flags for operators; whether they produce limits in 12875 // displaystyle, and whether they are symbols and should grow in 12876 // displaystyle. These four groups cover the four possible choices. 12877 12878 var singleCharIntegrals = { 12879 "\u222b": "\\int", 12880 "\u222c": "\\iint", 12881 "\u222d": "\\iiint", 12882 "\u222e": "\\oint", 12883 "\u222f": "\\oiint", 12884 "\u2230": "\\oiiint" 12885 }; // No limits, not symbols 12886 12887 defineFunction({ 12888 type: "op", 12889 names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"], 12890 props: { 12891 numArgs: 0 12892 }, 12893 12894 handler(_ref3) { 12895 var { 12896 parser, 12897 funcName 12898 } = _ref3; 12899 return { 12900 type: "op", 12901 mode: parser.mode, 12902 limits: false, 12903 parentIsSupSub: false, 12904 symbol: false, 12905 name: funcName 12906 }; 12907 }, 12908 12909 htmlBuilder: htmlBuilder$8, 12910 mathmlBuilder: mathmlBuilder$8 12911 }); // Limits, not symbols 12912 12913 defineFunction({ 12914 type: "op", 12915 names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], 12916 props: { 12917 numArgs: 0 12918 }, 12919 12920 handler(_ref4) { 12921 var { 12922 parser, 12923 funcName 12924 } = _ref4; 12925 return { 12926 type: "op", 12927 mode: parser.mode, 12928 limits: true, 12929 parentIsSupSub: false, 12930 symbol: false, 12931 name: funcName 12932 }; 12933 }, 12934 12935 htmlBuilder: htmlBuilder$8, 12936 mathmlBuilder: mathmlBuilder$8 12937 }); // No limits, symbols 12938 12939 defineFunction({ 12940 type: "op", 12941 names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"], 12942 props: { 12943 numArgs: 0 12944 }, 12945 12946 handler(_ref5) { 12947 var { 12948 parser, 12949 funcName 12950 } = _ref5; 12951 var fName = funcName; 12952 12953 if (fName.length === 1) { 12954 fName = singleCharIntegrals[fName]; 12955 } 12956 12957 return { 12958 type: "op", 12959 mode: parser.mode, 12960 limits: false, 12961 parentIsSupSub: false, 12962 symbol: true, 12963 name: fName 12964 }; 12965 }, 12966 12967 htmlBuilder: htmlBuilder$8, 12968 mathmlBuilder: mathmlBuilder$8 12969 }); 12970 12971 // NOTE: Unlike most `htmlBuilder`s, this one handles not only 12972 // "operatorname", but also "supsub" since \operatorname* can 12973 // affect super/subscripting. 12974 var htmlBuilder$9 = (grp, options) => { 12975 // Operators are handled in the TeXbook pg. 443-444, rule 13(a). 12976 var supGroup; 12977 var subGroup; 12978 var hasLimits = false; 12979 var group; 12980 12981 if (grp.type === "supsub") { 12982 // If we have limits, supsub will pass us its group to handle. Pull 12983 // out the superscript and subscript and set the group to the op in 12984 // its base. 12985 supGroup = grp.sup; 12986 subGroup = grp.sub; 12987 group = assertNodeType(grp.base, "operatorname"); 12988 hasLimits = true; 12989 } else { 12990 group = assertNodeType(grp, "operatorname"); 12991 } 12992 12993 var base; 12994 12995 if (group.body.length > 0) { 12996 var body = group.body.map(child => { 12997 // $FlowFixMe: Check if the node has a string `text` property. 12998 var childText = child.text; 12999 13000 if (typeof childText === "string") { 13001 return { 13002 type: "textord", 13003 mode: child.mode, 13004 text: childText 13005 }; 13006 } else { 13007 return child; 13008 } 13009 }); // Consolidate function names into symbol characters. 13010 13011 var expression = buildExpression(body, options.withFont("mathrm"), true); 13012 13013 for (var i = 0; i < expression.length; i++) { 13014 var child = expression[i]; 13015 13016 if (child instanceof SymbolNode) { 13017 // Per amsopn package, 13018 // change minus to hyphen and \ast to asterisk 13019 child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); 13020 } 13021 } 13022 13023 base = buildCommon.makeSpan(["mop"], expression, options); 13024 } else { 13025 base = buildCommon.makeSpan(["mop"], [], options); 13026 } 13027 13028 if (hasLimits) { 13029 return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0); 13030 } else { 13031 return base; 13032 } 13033 }; 13034 13035 var mathmlBuilder$9 = (group, options) => { 13036 // The steps taken here are similar to the html version. 13037 var expression = buildExpression$1(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction? 13038 13039 var isAllString = true; // default 13040 13041 for (var i = 0; i < expression.length; i++) { 13042 var node = expression[i]; 13043 13044 if (node instanceof mathMLTree.SpaceNode) ; else if (node instanceof mathMLTree.MathNode) { 13045 switch (node.type) { 13046 case "mi": 13047 case "mn": 13048 case "ms": 13049 case "mspace": 13050 case "mtext": 13051 break; 13052 // Do nothing yet. 13053 13054 case "mo": 13055 { 13056 var child = node.children[0]; 13057 13058 if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { 13059 child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); 13060 } else { 13061 isAllString = false; 13062 } 13063 13064 break; 13065 } 13066 13067 default: 13068 isAllString = false; 13069 } 13070 } else { 13071 isAllString = false; 13072 } 13073 } 13074 13075 if (isAllString) { 13076 // Write a single TextNode instead of multiple nested tags. 13077 var word = expression.map(node => node.toText()).join(""); 13078 expression = [new mathMLTree.TextNode(word)]; 13079 } 13080 13081 var identifier = new mathMLTree.MathNode("mi", expression); 13082 identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as ⁡ 13083 // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp 13084 13085 var operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); 13086 13087 if (group.parentIsSupSub) { 13088 return new mathMLTree.MathNode("mrow", [identifier, operator]); 13089 } else { 13090 return mathMLTree.newDocumentFragment([identifier, operator]); 13091 } 13092 }; // \operatorname 13093 // amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ 13094 13095 13096 defineFunction({ 13097 type: "operatorname", 13098 names: ["\\operatorname", "\\operatorname*"], 13099 props: { 13100 numArgs: 1 13101 }, 13102 handler: (_ref, args) => { 13103 var { 13104 parser, 13105 funcName 13106 } = _ref; 13107 var body = args[0]; 13108 return { 13109 type: "operatorname", 13110 mode: parser.mode, 13111 body: ordargument(body), 13112 alwaysHandleSupSub: funcName === "\\operatorname*", 13113 limits: false, 13114 parentIsSupSub: false 13115 }; 13116 }, 13117 htmlBuilder: htmlBuilder$9, 13118 mathmlBuilder: mathmlBuilder$9 13119 }); 13120 13121 defineFunctionBuilders({ 13122 type: "ordgroup", 13123 13124 htmlBuilder(group, options) { 13125 if (group.semisimple) { 13126 return buildCommon.makeFragment(buildExpression(group.body, options, false)); 13127 } 13128 13129 return buildCommon.makeSpan(["mord"], buildExpression(group.body, options, true), options); 13130 }, 13131 13132 mathmlBuilder(group, options) { 13133 return buildExpressionRow(group.body, options, true); 13134 } 13135 13136 }); 13137 13138 defineFunction({ 13139 type: "overline", 13140 names: ["\\overline"], 13141 props: { 13142 numArgs: 1 13143 }, 13144 13145 handler(_ref, args) { 13146 var { 13147 parser 13148 } = _ref; 13149 var body = args[0]; 13150 return { 13151 type: "overline", 13152 mode: parser.mode, 13153 body 13154 }; 13155 }, 13156 13157 htmlBuilder(group, options) { 13158 // Overlines are handled in the TeXbook pg 443, Rule 9. 13159 // Build the inner group in the cramped style. 13160 var innerGroup = buildGroup(group.body, options.havingCrampedStyle()); // Create the line above the body 13161 13162 var line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns 13163 13164 var defaultRuleThickness = options.fontMetrics().defaultRuleThickness; 13165 var vlist = buildCommon.makeVList({ 13166 positionType: "firstBaseline", 13167 children: [{ 13168 type: "elem", 13169 elem: innerGroup 13170 }, { 13171 type: "kern", 13172 size: 3 * defaultRuleThickness 13173 }, { 13174 type: "elem", 13175 elem: line 13176 }, { 13177 type: "kern", 13178 size: defaultRuleThickness 13179 }] 13180 }, options); 13181 return buildCommon.makeSpan(["mord", "overline"], [vlist], options); 13182 }, 13183 13184 mathmlBuilder(group, options) { 13185 var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]); 13186 operator.setAttribute("stretchy", "true"); 13187 var node = new mathMLTree.MathNode("mover", [buildGroup$1(group.body, options), operator]); 13188 node.setAttribute("accent", "true"); 13189 return node; 13190 } 13191 13192 }); 13193 13194 defineFunction({ 13195 type: "phantom", 13196 names: ["\\phantom"], 13197 props: { 13198 numArgs: 1, 13199 allowedInText: true 13200 }, 13201 handler: (_ref, args) => { 13202 var { 13203 parser 13204 } = _ref; 13205 var body = args[0]; 13206 return { 13207 type: "phantom", 13208 mode: parser.mode, 13209 body: ordargument(body) 13210 }; 13211 }, 13212 htmlBuilder: (group, options) => { 13213 var elements = buildExpression(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains. 13214 // See "color" for more details. 13215 13216 return buildCommon.makeFragment(elements); 13217 }, 13218 mathmlBuilder: (group, options) => { 13219 var inner = buildExpression$1(group.body, options); 13220 return new mathMLTree.MathNode("mphantom", inner); 13221 } 13222 }); 13223 defineFunction({ 13224 type: "hphantom", 13225 names: ["\\hphantom"], 13226 props: { 13227 numArgs: 1, 13228 allowedInText: true 13229 }, 13230 handler: (_ref2, args) => { 13231 var { 13232 parser 13233 } = _ref2; 13234 var body = args[0]; 13235 return { 13236 type: "hphantom", 13237 mode: parser.mode, 13238 body 13239 }; 13240 }, 13241 htmlBuilder: (group, options) => { 13242 var node = buildCommon.makeSpan([], [buildGroup(group.body, options.withPhantom())]); 13243 node.height = 0; 13244 node.depth = 0; 13245 13246 if (node.children) { 13247 for (var i = 0; i < node.children.length; i++) { 13248 node.children[i].height = 0; 13249 node.children[i].depth = 0; 13250 } 13251 } // See smash for comment re: use of makeVList 13252 13253 13254 node = buildCommon.makeVList({ 13255 positionType: "firstBaseline", 13256 children: [{ 13257 type: "elem", 13258 elem: node 13259 }] 13260 }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord). 13261 13262 return buildCommon.makeSpan(["mord"], [node], options); 13263 }, 13264 mathmlBuilder: (group, options) => { 13265 var inner = buildExpression$1(ordargument(group.body), options); 13266 var phantom = new mathMLTree.MathNode("mphantom", inner); 13267 var node = new mathMLTree.MathNode("mpadded", [phantom]); 13268 node.setAttribute("height", "0px"); 13269 node.setAttribute("depth", "0px"); 13270 return node; 13271 } 13272 }); 13273 defineFunction({ 13274 type: "vphantom", 13275 names: ["\\vphantom"], 13276 props: { 13277 numArgs: 1, 13278 allowedInText: true 13279 }, 13280 handler: (_ref3, args) => { 13281 var { 13282 parser 13283 } = _ref3; 13284 var body = args[0]; 13285 return { 13286 type: "vphantom", 13287 mode: parser.mode, 13288 body 13289 }; 13290 }, 13291 htmlBuilder: (group, options) => { 13292 var inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options.withPhantom())]); 13293 var fix = buildCommon.makeSpan(["fix"], []); 13294 return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options); 13295 }, 13296 mathmlBuilder: (group, options) => { 13297 var inner = buildExpression$1(ordargument(group.body), options); 13298 var phantom = new mathMLTree.MathNode("mphantom", inner); 13299 var node = new mathMLTree.MathNode("mpadded", [phantom]); 13300 node.setAttribute("width", "0px"); 13301 return node; 13302 } 13303 }); 13304 13305 defineFunction({ 13306 type: "raisebox", 13307 names: ["\\raisebox"], 13308 props: { 13309 numArgs: 2, 13310 argTypes: ["size", "hbox"], 13311 allowedInText: true 13312 }, 13313 13314 handler(_ref, args) { 13315 var { 13316 parser 13317 } = _ref; 13318 var amount = assertNodeType(args[0], "size").value; 13319 var body = args[1]; 13320 return { 13321 type: "raisebox", 13322 mode: parser.mode, 13323 dy: amount, 13324 body 13325 }; 13326 }, 13327 13328 htmlBuilder(group, options) { 13329 var body = buildGroup(group.body, options); 13330 var dy = calculateSize(group.dy, options); 13331 return buildCommon.makeVList({ 13332 positionType: "shift", 13333 positionData: -dy, 13334 children: [{ 13335 type: "elem", 13336 elem: body 13337 }] 13338 }, options); 13339 }, 13340 13341 mathmlBuilder(group, options) { 13342 var node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]); 13343 var dy = group.dy.number + group.dy.unit; 13344 node.setAttribute("voffset", dy); 13345 return node; 13346 } 13347 13348 }); 13349 13350 defineFunction({ 13351 type: "rule", 13352 names: ["\\rule"], 13353 props: { 13354 numArgs: 2, 13355 numOptionalArgs: 1, 13356 argTypes: ["size", "size", "size"] 13357 }, 13358 13359 handler(_ref, args, optArgs) { 13360 var { 13361 parser 13362 } = _ref; 13363 var shift = optArgs[0]; 13364 var width = assertNodeType(args[0], "size"); 13365 var height = assertNodeType(args[1], "size"); 13366 return { 13367 type: "rule", 13368 mode: parser.mode, 13369 shift: shift && assertNodeType(shift, "size").value, 13370 width: width.value, 13371 height: height.value 13372 }; 13373 }, 13374 13375 htmlBuilder(group, options) { 13376 // Make an empty span for the rule 13377 var rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units 13378 13379 var width = calculateSize(group.width, options); 13380 var height = calculateSize(group.height, options); 13381 var shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size 13382 13383 rule.style.borderRightWidth = width + "em"; 13384 rule.style.borderTopWidth = height + "em"; 13385 rule.style.bottom = shift + "em"; // Record the height and width 13386 13387 rule.width = width; 13388 rule.height = height + shift; 13389 rule.depth = -shift; // Font size is the number large enough that the browser will 13390 // reserve at least `absHeight` space above the baseline. 13391 // The 1.125 factor was empirically determined 13392 13393 rule.maxFontSize = height * 1.125 * options.sizeMultiplier; 13394 return rule; 13395 }, 13396 13397 mathmlBuilder(group, options) { 13398 var width = calculateSize(group.width, options); 13399 var height = calculateSize(group.height, options); 13400 var shift = group.shift ? calculateSize(group.shift, options) : 0; 13401 var color = options.color && options.getColor() || "black"; 13402 var rule = new mathMLTree.MathNode("mspace"); 13403 rule.setAttribute("mathbackground", color); 13404 rule.setAttribute("width", width + "em"); 13405 rule.setAttribute("height", height + "em"); 13406 var wrapper = new mathMLTree.MathNode("mpadded", [rule]); 13407 13408 if (shift >= 0) { 13409 wrapper.setAttribute("height", "+" + shift + "em"); 13410 } else { 13411 wrapper.setAttribute("height", shift + "em"); 13412 wrapper.setAttribute("depth", "+" + -shift + "em"); 13413 } 13414 13415 wrapper.setAttribute("voffset", shift + "em"); 13416 return wrapper; 13417 } 13418 13419 }); 13420 13421 function sizingGroup(value, options, baseOptions) { 13422 var inner = buildExpression(value, options, false); 13423 var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize 13424 // manually. Handle nested size changes. 13425 13426 for (var i = 0; i < inner.length; i++) { 13427 var pos = inner[i].classes.indexOf("sizing"); 13428 13429 if (pos < 0) { 13430 Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions)); 13431 } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) { 13432 // This is a nested size change: e.g., inner[i] is the "b" in 13433 // `\Huge a \small b`. Override the old size (the `reset-` class) 13434 // but not the new size. 13435 inner[i].classes[pos + 1] = "reset-size" + baseOptions.size; 13436 } 13437 13438 inner[i].height *= multiplier; 13439 inner[i].depth *= multiplier; 13440 } 13441 13442 return buildCommon.makeFragment(inner); 13443 } 13444 var sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"]; 13445 var htmlBuilder$a = (group, options) => { 13446 // Handle sizing operators like \Huge. Real TeX doesn't actually allow 13447 // these functions inside of math expressions, so we do some special 13448 // handling. 13449 var newOptions = options.havingSize(group.size); 13450 return sizingGroup(group.body, newOptions, options); 13451 }; 13452 defineFunction({ 13453 type: "sizing", 13454 names: sizeFuncs, 13455 props: { 13456 numArgs: 0, 13457 allowedInText: true 13458 }, 13459 handler: (_ref, args) => { 13460 var { 13461 breakOnTokenText, 13462 funcName, 13463 parser 13464 } = _ref; 13465 var body = parser.parseExpression(false, breakOnTokenText); 13466 return { 13467 type: "sizing", 13468 mode: parser.mode, 13469 // Figure out what size to use based on the list of functions above 13470 size: sizeFuncs.indexOf(funcName) + 1, 13471 body 13472 }; 13473 }, 13474 htmlBuilder: htmlBuilder$a, 13475 mathmlBuilder: (group, options) => { 13476 var newOptions = options.havingSize(group.size); 13477 var inner = buildExpression$1(group.body, newOptions); 13478 var node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size 13479 // changes, because we don't keep state of what style we're currently 13480 // in, so we can't reset the size to normal before changing it. Now 13481 // that we're passing an options parameter we should be able to fix 13482 // this. 13483 13484 node.setAttribute("mathsize", newOptions.sizeMultiplier + "em"); 13485 return node; 13486 } 13487 }); 13488 13489 // smash, with optional [tb], as in AMS 13490 defineFunction({ 13491 type: "smash", 13492 names: ["\\smash"], 13493 props: { 13494 numArgs: 1, 13495 numOptionalArgs: 1, 13496 allowedInText: true 13497 }, 13498 handler: (_ref, args, optArgs) => { 13499 var { 13500 parser 13501 } = _ref; 13502 var smashHeight = false; 13503 var smashDepth = false; 13504 var tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); 13505 13506 if (tbArg) { 13507 // Optional [tb] argument is engaged. 13508 // ref: amsmath: \renewcommand{\smash}[1][tb]{% 13509 // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% 13510 var letter = ""; 13511 13512 for (var i = 0; i < tbArg.body.length; ++i) { 13513 var node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property. 13514 13515 letter = node.text; 13516 13517 if (letter === "t") { 13518 smashHeight = true; 13519 } else if (letter === "b") { 13520 smashDepth = true; 13521 } else { 13522 smashHeight = false; 13523 smashDepth = false; 13524 break; 13525 } 13526 } 13527 } else { 13528 smashHeight = true; 13529 smashDepth = true; 13530 } 13531 13532 var body = args[0]; 13533 return { 13534 type: "smash", 13535 mode: parser.mode, 13536 body, 13537 smashHeight, 13538 smashDepth 13539 }; 13540 }, 13541 htmlBuilder: (group, options) => { 13542 var node = buildCommon.makeSpan([], [buildGroup(group.body, options)]); 13543 13544 if (!group.smashHeight && !group.smashDepth) { 13545 return node; 13546 } 13547 13548 if (group.smashHeight) { 13549 node.height = 0; // In order to influence makeVList, we have to reset the children. 13550 13551 if (node.children) { 13552 for (var i = 0; i < node.children.length; i++) { 13553 node.children[i].height = 0; 13554 } 13555 } 13556 } 13557 13558 if (group.smashDepth) { 13559 node.depth = 0; 13560 13561 if (node.children) { 13562 for (var _i = 0; _i < node.children.length; _i++) { 13563 node.children[_i].depth = 0; 13564 } 13565 } 13566 } // At this point, we've reset the TeX-like height and depth values. 13567 // But the span still has an HTML line height. 13568 // makeVList applies "display: table-cell", which prevents the browser 13569 // from acting on that line height. So we'll call makeVList now. 13570 13571 13572 var smashedNode = buildCommon.makeVList({ 13573 positionType: "firstBaseline", 13574 children: [{ 13575 type: "elem", 13576 elem: node 13577 }] 13578 }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord). 13579 13580 return buildCommon.makeSpan(["mord"], [smashedNode], options); 13581 }, 13582 mathmlBuilder: (group, options) => { 13583 var node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]); 13584 13585 if (group.smashHeight) { 13586 node.setAttribute("height", "0px"); 13587 } 13588 13589 if (group.smashDepth) { 13590 node.setAttribute("depth", "0px"); 13591 } 13592 13593 return node; 13594 } 13595 }); 13596 13597 defineFunction({ 13598 type: "sqrt", 13599 names: ["\\sqrt"], 13600 props: { 13601 numArgs: 1, 13602 numOptionalArgs: 1 13603 }, 13604 13605 handler(_ref, args, optArgs) { 13606 var { 13607 parser 13608 } = _ref; 13609 var index = optArgs[0]; 13610 var body = args[0]; 13611 return { 13612 type: "sqrt", 13613 mode: parser.mode, 13614 body, 13615 index 13616 }; 13617 }, 13618 13619 htmlBuilder(group, options) { 13620 // Square roots are handled in the TeXbook pg. 443, Rule 11. 13621 // First, we do the same steps as in overline to build the inner group 13622 // and line 13623 var inner = buildGroup(group.body, options.havingCrampedStyle()); 13624 13625 if (inner.height === 0) { 13626 // Render a small surd. 13627 inner.height = options.fontMetrics().xHeight; 13628 } // Some groups can return document fragments. Handle those by wrapping 13629 // them in a span. 13630 13631 13632 inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter 13633 13634 var metrics = options.fontMetrics(); 13635 var theta = metrics.defaultRuleThickness; 13636 var phi = theta; 13637 13638 if (options.style.id < Style$1.TEXT.id) { 13639 phi = options.fontMetrics().xHeight; 13640 } // Calculate the clearance between the body and line 13641 13642 13643 var lineClearance = theta + phi / 4; 13644 var minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size 13645 13646 var { 13647 span: img, 13648 ruleWidth, 13649 advanceWidth 13650 } = delimiter.sqrtImage(minDelimiterHeight, options); 13651 var delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size 13652 13653 if (delimDepth > inner.height + inner.depth + lineClearance) { 13654 lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2; 13655 } // Shift the sqrt image 13656 13657 13658 var imgShift = img.height - inner.height - lineClearance - ruleWidth; 13659 inner.style.paddingLeft = advanceWidth + "em"; // Overlay the image and the argument. 13660 13661 var body = buildCommon.makeVList({ 13662 positionType: "firstBaseline", 13663 children: [{ 13664 type: "elem", 13665 elem: inner, 13666 wrapperClasses: ["svg-align"] 13667 }, { 13668 type: "kern", 13669 size: -(inner.height + imgShift) 13670 }, { 13671 type: "elem", 13672 elem: img 13673 }, { 13674 type: "kern", 13675 size: ruleWidth 13676 }] 13677 }, options); 13678 13679 if (!group.index) { 13680 return buildCommon.makeSpan(["mord", "sqrt"], [body], options); 13681 } else { 13682 // Handle the optional root index 13683 // The index is always in scriptscript style 13684 var newOptions = options.havingStyle(Style$1.SCRIPTSCRIPT); 13685 var rootm = buildGroup(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX 13686 // source, in the definition of `\r@@t`. 13687 13688 var toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly 13689 13690 var rootVList = buildCommon.makeVList({ 13691 positionType: "shift", 13692 positionData: -toShift, 13693 children: [{ 13694 type: "elem", 13695 elem: rootm 13696 }] 13697 }, options); // Add a class surrounding it so we can add on the appropriate 13698 // kerning 13699 13700 var rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]); 13701 return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options); 13702 } 13703 }, 13704 13705 mathmlBuilder(group, options) { 13706 var { 13707 body, 13708 index 13709 } = group; 13710 return index ? new mathMLTree.MathNode("mroot", [buildGroup$1(body, options), buildGroup$1(index, options)]) : new mathMLTree.MathNode("msqrt", [buildGroup$1(body, options)]); 13711 } 13712 13713 }); 13714 13715 var styleMap$1 = { 13716 "display": Style$1.DISPLAY, 13717 "text": Style$1.TEXT, 13718 "script": Style$1.SCRIPT, 13719 "scriptscript": Style$1.SCRIPTSCRIPT 13720 }; 13721 defineFunction({ 13722 type: "styling", 13723 names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], 13724 props: { 13725 numArgs: 0, 13726 allowedInText: true, 13727 primitive: true 13728 }, 13729 13730 handler(_ref, args) { 13731 var { 13732 breakOnTokenText, 13733 funcName, 13734 parser 13735 } = _ref; 13736 // parse out the implicit body 13737 var body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g. 13738 // here and in buildHTML and de-dupe the enumeration of all the styles). 13739 // $FlowFixMe: The names above exactly match the styles. 13740 13741 var style = funcName.slice(1, funcName.length - 5); 13742 return { 13743 type: "styling", 13744 mode: parser.mode, 13745 // Figure out what style to use by pulling out the style from 13746 // the function name 13747 style, 13748 body 13749 }; 13750 }, 13751 13752 htmlBuilder(group, options) { 13753 // Style changes are handled in the TeXbook on pg. 442, Rule 3. 13754 var newStyle = styleMap$1[group.style]; 13755 var newOptions = options.havingStyle(newStyle).withFont(''); 13756 return sizingGroup(group.body, newOptions, options); 13757 }, 13758 13759 mathmlBuilder(group, options) { 13760 // Figure out what style we're changing to. 13761 var newStyle = styleMap$1[group.style]; 13762 var newOptions = options.havingStyle(newStyle); 13763 var inner = buildExpression$1(group.body, newOptions); 13764 var node = new mathMLTree.MathNode("mstyle", inner); 13765 var styleAttributes = { 13766 "display": ["0", "true"], 13767 "text": ["0", "false"], 13768 "script": ["1", "false"], 13769 "scriptscript": ["2", "false"] 13770 }; 13771 var attr = styleAttributes[group.style]; 13772 node.setAttribute("scriptlevel", attr[0]); 13773 node.setAttribute("displaystyle", attr[1]); 13774 return node; 13775 } 13776 13777 }); 13778 13779 /** 13780 * Sometimes, groups perform special rules when they have superscripts or 13781 * subscripts attached to them. This function lets the `supsub` group know that 13782 * Sometimes, groups perform special rules when they have superscripts or 13783 * its inner element should handle the superscripts and subscripts instead of 13784 * handling them itself. 13785 */ 13786 var htmlBuilderDelegate = function htmlBuilderDelegate(group, options) { 13787 var base = group.base; 13788 13789 if (!base) { 13790 return null; 13791 } else if (base.type === "op") { 13792 // Operators handle supsubs differently when they have limits 13793 // (e.g. `\displaystyle\sum_2^3`) 13794 var delegate = base.limits && (options.style.size === Style$1.DISPLAY.size || base.alwaysHandleSupSub); 13795 return delegate ? htmlBuilder$8 : null; 13796 } else if (base.type === "operatorname") { 13797 var _delegate = base.alwaysHandleSupSub && (options.style.size === Style$1.DISPLAY.size || base.limits); 13798 13799 return _delegate ? htmlBuilder$9 : null; 13800 } else if (base.type === "accent") { 13801 return utils.isCharacterBox(base.base) ? htmlBuilder : null; 13802 } else if (base.type === "horizBrace") { 13803 var isSup = !group.sub; 13804 return isSup === base.isOver ? htmlBuilder$7 : null; 13805 } else { 13806 return null; 13807 } 13808 }; // Super scripts and subscripts, whose precise placement can depend on other 13809 // functions that precede them. 13810 13811 13812 defineFunctionBuilders({ 13813 type: "supsub", 13814 13815 htmlBuilder(group, options) { 13816 // Superscript and subscripts are handled in the TeXbook on page 13817 // 445-446, rules 18(a-f). 13818 // Here is where we defer to the inner group if it should handle 13819 // superscripts and subscripts itself. 13820 var builderDelegate = htmlBuilderDelegate(group, options); 13821 13822 if (builderDelegate) { 13823 return builderDelegate(group, options); 13824 } 13825 13826 var { 13827 base: valueBase, 13828 sup: valueSup, 13829 sub: valueSub 13830 } = group; 13831 var base = buildGroup(valueBase, options); 13832 var supm; 13833 var subm; 13834 var metrics = options.fontMetrics(); // Rule 18a 13835 13836 var supShift = 0; 13837 var subShift = 0; 13838 var isCharacterBox = valueBase && utils.isCharacterBox(valueBase); 13839 13840 if (valueSup) { 13841 var newOptions = options.havingStyle(options.style.sup()); 13842 supm = buildGroup(valueSup, newOptions, options); 13843 13844 if (!isCharacterBox) { 13845 supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier; 13846 } 13847 } 13848 13849 if (valueSub) { 13850 var _newOptions = options.havingStyle(options.style.sub()); 13851 13852 subm = buildGroup(valueSub, _newOptions, options); 13853 13854 if (!isCharacterBox) { 13855 subShift = base.depth + _newOptions.fontMetrics().subDrop * _newOptions.sizeMultiplier / options.sizeMultiplier; 13856 } 13857 } // Rule 18c 13858 13859 13860 var minSupShift; 13861 13862 if (options.style === Style$1.DISPLAY) { 13863 minSupShift = metrics.sup1; 13864 } else if (options.style.cramped) { 13865 minSupShift = metrics.sup3; 13866 } else { 13867 minSupShift = metrics.sup2; 13868 } // scriptspace is a font-size-independent size, so scale it 13869 // appropriately for use as the marginRight. 13870 13871 13872 var multiplier = options.sizeMultiplier; 13873 var marginRight = 0.5 / metrics.ptPerEm / multiplier + "em"; 13874 var marginLeft = null; 13875 13876 if (subm) { 13877 // Subscripts shouldn't be shifted by the base's italic correction. 13878 // Account for that by shifting the subscript back the appropriate 13879 // amount. Note we only do this when the base is a single symbol. 13880 var isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint"); 13881 13882 if (base instanceof SymbolNode || isOiint) { 13883 // $FlowFixMe 13884 marginLeft = -base.italic + "em"; 13885 } 13886 } 13887 13888 var supsub; 13889 13890 if (supm && subm) { 13891 supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight); 13892 subShift = Math.max(subShift, metrics.sub2); 13893 var ruleWidth = metrics.defaultRuleThickness; // Rule 18e 13894 13895 var maxWidth = 4 * ruleWidth; 13896 13897 if (supShift - supm.depth - (subm.height - subShift) < maxWidth) { 13898 subShift = maxWidth - (supShift - supm.depth) + subm.height; 13899 var psi = 0.8 * metrics.xHeight - (supShift - supm.depth); 13900 13901 if (psi > 0) { 13902 supShift += psi; 13903 subShift -= psi; 13904 } 13905 } 13906 13907 var vlistElem = [{ 13908 type: "elem", 13909 elem: subm, 13910 shift: subShift, 13911 marginRight, 13912 marginLeft 13913 }, { 13914 type: "elem", 13915 elem: supm, 13916 shift: -supShift, 13917 marginRight 13918 }]; 13919 supsub = buildCommon.makeVList({ 13920 positionType: "individualShift", 13921 children: vlistElem 13922 }, options); 13923 } else if (subm) { 13924 // Rule 18b 13925 subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight); 13926 var _vlistElem = [{ 13927 type: "elem", 13928 elem: subm, 13929 marginLeft, 13930 marginRight 13931 }]; 13932 supsub = buildCommon.makeVList({ 13933 positionType: "shift", 13934 positionData: subShift, 13935 children: _vlistElem 13936 }, options); 13937 } else if (supm) { 13938 // Rule 18c, d 13939 supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight); 13940 supsub = buildCommon.makeVList({ 13941 positionType: "shift", 13942 positionData: -supShift, 13943 children: [{ 13944 type: "elem", 13945 elem: supm, 13946 marginRight 13947 }] 13948 }, options); 13949 } else { 13950 throw new Error("supsub must have either sup or sub."); 13951 } // Wrap the supsub vlist in a span.msupsub to reset text-align. 13952 13953 13954 var mclass = getTypeOfDomTree(base, "right") || "mord"; 13955 return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options); 13956 }, 13957 13958 mathmlBuilder(group, options) { 13959 // Is the inner group a relevant horizonal brace? 13960 var isBrace = false; 13961 var isOver; 13962 var isSup; 13963 13964 if (group.base && group.base.type === "horizBrace") { 13965 isSup = !!group.sup; 13966 13967 if (isSup === group.base.isOver) { 13968 isBrace = true; 13969 isOver = group.base.isOver; 13970 } 13971 } 13972 13973 if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) { 13974 group.base.parentIsSupSub = true; 13975 } 13976 13977 var children = [buildGroup$1(group.base, options)]; 13978 13979 if (group.sub) { 13980 children.push(buildGroup$1(group.sub, options)); 13981 } 13982 13983 if (group.sup) { 13984 children.push(buildGroup$1(group.sup, options)); 13985 } 13986 13987 var nodeType; 13988 13989 if (isBrace) { 13990 nodeType = isOver ? "mover" : "munder"; 13991 } else if (!group.sub) { 13992 var base = group.base; 13993 13994 if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) { 13995 nodeType = "mover"; 13996 } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) { 13997 nodeType = "mover"; 13998 } else { 13999 nodeType = "msup"; 14000 } 14001 } else if (!group.sup) { 14002 var _base = group.base; 14003 14004 if (_base && _base.type === "op" && _base.limits && (options.style === Style$1.DISPLAY || _base.alwaysHandleSupSub)) { 14005 nodeType = "munder"; 14006 } else if (_base && _base.type === "operatorname" && _base.alwaysHandleSupSub && (_base.limits || options.style === Style$1.DISPLAY)) { 14007 nodeType = "munder"; 14008 } else { 14009 nodeType = "msub"; 14010 } 14011 } else { 14012 var _base2 = group.base; 14013 14014 if (_base2 && _base2.type === "op" && _base2.limits && options.style === Style$1.DISPLAY) { 14015 nodeType = "munderover"; 14016 } else if (_base2 && _base2.type === "operatorname" && _base2.alwaysHandleSupSub && (options.style === Style$1.DISPLAY || _base2.limits)) { 14017 nodeType = "munderover"; 14018 } else { 14019 nodeType = "msubsup"; 14020 } 14021 } 14022 14023 return new mathMLTree.MathNode(nodeType, children); 14024 } 14025 14026 }); 14027 14028 defineFunctionBuilders({ 14029 type: "atom", 14030 14031 htmlBuilder(group, options) { 14032 return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]); 14033 }, 14034 14035 mathmlBuilder(group, options) { 14036 var node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); 14037 14038 if (group.family === "bin") { 14039 var variant = getVariant(group, options); 14040 14041 if (variant === "bold-italic") { 14042 node.setAttribute("mathvariant", variant); 14043 } 14044 } else if (group.family === "punct") { 14045 node.setAttribute("separator", "true"); 14046 } else if (group.family === "open" || group.family === "close") { 14047 // Delims built here should not stretch vertically. 14048 // See delimsizing.js for stretchy delims. 14049 node.setAttribute("stretchy", "false"); 14050 } 14051 14052 return node; 14053 } 14054 14055 }); 14056 14057 // "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in 14058 // src/symbols.js. 14059 var defaultVariant = { 14060 "mi": "italic", 14061 "mn": "normal", 14062 "mtext": "normal" 14063 }; 14064 defineFunctionBuilders({ 14065 type: "mathord", 14066 14067 htmlBuilder(group, options) { 14068 return buildCommon.makeOrd(group, options, "mathord"); 14069 }, 14070 14071 mathmlBuilder(group, options) { 14072 var node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]); 14073 var variant = getVariant(group, options) || "italic"; 14074 14075 if (variant !== defaultVariant[node.type]) { 14076 node.setAttribute("mathvariant", variant); 14077 } 14078 14079 return node; 14080 } 14081 14082 }); 14083 defineFunctionBuilders({ 14084 type: "textord", 14085 14086 htmlBuilder(group, options) { 14087 return buildCommon.makeOrd(group, options, "textord"); 14088 }, 14089 14090 mathmlBuilder(group, options) { 14091 var text = makeText(group.text, group.mode, options); 14092 var variant = getVariant(group, options) || "normal"; 14093 var node; 14094 14095 if (group.mode === 'text') { 14096 node = new mathMLTree.MathNode("mtext", [text]); 14097 } else if (/[0-9]/.test(group.text)) { 14098 node = new mathMLTree.MathNode("mn", [text]); 14099 } else if (group.text === "\\prime") { 14100 node = new mathMLTree.MathNode("mo", [text]); 14101 } else { 14102 node = new mathMLTree.MathNode("mi", [text]); 14103 } 14104 14105 if (variant !== defaultVariant[node.type]) { 14106 node.setAttribute("mathvariant", variant); 14107 } 14108 14109 return node; 14110 } 14111 14112 }); 14113 14114 var cssSpace = { 14115 "\\nobreak": "nobreak", 14116 "\\allowbreak": "allowbreak" 14117 }; // A lookup table to determine whether a spacing function/symbol should be 14118 // treated like a regular space character. If a symbol or command is a key 14119 // in this table, then it should be a regular space character. Furthermore, 14120 // the associated value may have a `className` specifying an extra CSS class 14121 // to add to the created `span`. 14122 14123 var regularSpace = { 14124 " ": {}, 14125 "\\ ": {}, 14126 "~": { 14127 className: "nobreak" 14128 }, 14129 "\\space": {}, 14130 "\\nobreakspace": { 14131 className: "nobreak" 14132 } 14133 }; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in 14134 // src/symbols.js. 14135 14136 defineFunctionBuilders({ 14137 type: "spacing", 14138 14139 htmlBuilder(group, options) { 14140 if (regularSpace.hasOwnProperty(group.text)) { 14141 var className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these 14142 // things has an entry in the symbols table, so these will be turned 14143 // into appropriate outputs. 14144 14145 if (group.mode === "text") { 14146 var ord = buildCommon.makeOrd(group, options, "textord"); 14147 ord.classes.push(className); 14148 return ord; 14149 } else { 14150 return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options); 14151 } 14152 } else if (cssSpace.hasOwnProperty(group.text)) { 14153 // Spaces based on just a CSS class. 14154 return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options); 14155 } else { 14156 throw new ParseError("Unknown type of space \"" + group.text + "\""); 14157 } 14158 }, 14159 14160 mathmlBuilder(group, options) { 14161 var node; 14162 14163 if (regularSpace.hasOwnProperty(group.text)) { 14164 node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); 14165 } else if (cssSpace.hasOwnProperty(group.text)) { 14166 // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored 14167 return new mathMLTree.MathNode("mspace"); 14168 } else { 14169 throw new ParseError("Unknown type of space \"" + group.text + "\""); 14170 } 14171 14172 return node; 14173 } 14174 14175 }); 14176 14177 var pad = () => { 14178 var padNode = new mathMLTree.MathNode("mtd", []); 14179 padNode.setAttribute("width", "50%"); 14180 return padNode; 14181 }; 14182 14183 defineFunctionBuilders({ 14184 type: "tag", 14185 14186 mathmlBuilder(group, options) { 14187 var table = new mathMLTree.MathNode("mtable", [new mathMLTree.MathNode("mtr", [pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.body, options)]), pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.tag, options)])])]); 14188 table.setAttribute("width", "100%"); 14189 return table; // TODO: Left-aligned tags. 14190 // Currently, the group and options passed here do not contain 14191 // enough info to set tag alignment. `leqno` is in Settings but it is 14192 // not passed to Options. On the HTML side, leqno is 14193 // set by a CSS class applied in buildTree.js. That would have worked 14194 // in MathML if browsers supported <mlabeledtr>. Since they don't, we 14195 // need to rewrite the way this function is called. 14196 } 14197 14198 }); 14199 14200 var textFontFamilies = { 14201 "\\text": undefined, 14202 "\\textrm": "textrm", 14203 "\\textsf": "textsf", 14204 "\\texttt": "texttt", 14205 "\\textnormal": "textrm" 14206 }; 14207 var textFontWeights = { 14208 "\\textbf": "textbf", 14209 "\\textmd": "textmd" 14210 }; 14211 var textFontShapes = { 14212 "\\textit": "textit", 14213 "\\textup": "textup" 14214 }; 14215 14216 var optionsWithFont = (group, options) => { 14217 var font = group.font; // Checks if the argument is a font family or a font style. 14218 14219 if (!font) { 14220 return options; 14221 } else if (textFontFamilies[font]) { 14222 return options.withTextFontFamily(textFontFamilies[font]); 14223 } else if (textFontWeights[font]) { 14224 return options.withTextFontWeight(textFontWeights[font]); 14225 } else { 14226 return options.withTextFontShape(textFontShapes[font]); 14227 } 14228 }; 14229 14230 defineFunction({ 14231 type: "text", 14232 names: [// Font families 14233 "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights 14234 "\\textbf", "\\textmd", // Font Shapes 14235 "\\textit", "\\textup"], 14236 props: { 14237 numArgs: 1, 14238 argTypes: ["text"], 14239 allowedInArgument: true, 14240 allowedInText: true 14241 }, 14242 14243 handler(_ref, args) { 14244 var { 14245 parser, 14246 funcName 14247 } = _ref; 14248 var body = args[0]; 14249 return { 14250 type: "text", 14251 mode: parser.mode, 14252 body: ordargument(body), 14253 font: funcName 14254 }; 14255 }, 14256 14257 htmlBuilder(group, options) { 14258 var newOptions = optionsWithFont(group, options); 14259 var inner = buildExpression(group.body, newOptions, true); 14260 return buildCommon.makeSpan(["mord", "text"], inner, newOptions); 14261 }, 14262 14263 mathmlBuilder(group, options) { 14264 var newOptions = optionsWithFont(group, options); 14265 return buildExpressionRow(group.body, newOptions); 14266 } 14267 14268 }); 14269 14270 defineFunction({ 14271 type: "underline", 14272 names: ["\\underline"], 14273 props: { 14274 numArgs: 1, 14275 allowedInText: true 14276 }, 14277 14278 handler(_ref, args) { 14279 var { 14280 parser 14281 } = _ref; 14282 return { 14283 type: "underline", 14284 mode: parser.mode, 14285 body: args[0] 14286 }; 14287 }, 14288 14289 htmlBuilder(group, options) { 14290 // Underlines are handled in the TeXbook pg 443, Rule 10. 14291 // Build the inner group. 14292 var innerGroup = buildGroup(group.body, options); // Create the line to go below the body 14293 14294 var line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns 14295 14296 var defaultRuleThickness = options.fontMetrics().defaultRuleThickness; 14297 var vlist = buildCommon.makeVList({ 14298 positionType: "top", 14299 positionData: innerGroup.height, 14300 children: [{ 14301 type: "kern", 14302 size: defaultRuleThickness 14303 }, { 14304 type: "elem", 14305 elem: line 14306 }, { 14307 type: "kern", 14308 size: 3 * defaultRuleThickness 14309 }, { 14310 type: "elem", 14311 elem: innerGroup 14312 }] 14313 }, options); 14314 return buildCommon.makeSpan(["mord", "underline"], [vlist], options); 14315 }, 14316 14317 mathmlBuilder(group, options) { 14318 var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]); 14319 operator.setAttribute("stretchy", "true"); 14320 var node = new mathMLTree.MathNode("munder", [buildGroup$1(group.body, options), operator]); 14321 node.setAttribute("accentunder", "true"); 14322 return node; 14323 } 14324 14325 }); 14326 14327 defineFunction({ 14328 type: "vcenter", 14329 names: ["\\vcenter"], 14330 props: { 14331 numArgs: 1, 14332 argTypes: ["original"], 14333 // In LaTeX, \vcenter can act only on a box. 14334 allowedInText: false 14335 }, 14336 14337 handler(_ref, args) { 14338 var { 14339 parser 14340 } = _ref; 14341 return { 14342 type: "vcenter", 14343 mode: parser.mode, 14344 body: args[0] 14345 }; 14346 }, 14347 14348 htmlBuilder(group, options) { 14349 var body = buildGroup(group.body, options); 14350 var axisHeight = options.fontMetrics().axisHeight; 14351 var dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight)); 14352 return buildCommon.makeVList({ 14353 positionType: "shift", 14354 positionData: dy, 14355 children: [{ 14356 type: "elem", 14357 elem: body 14358 }] 14359 }, options); 14360 }, 14361 14362 mathmlBuilder(group, options) { 14363 // There is no way to do this in MathML. 14364 // Write a class as a breadcrumb in case some post-processor wants 14365 // to perform a vcenter adjustment. 14366 return new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)], ["vcenter"]); 14367 } 14368 14369 }); 14370 14371 defineFunction({ 14372 type: "verb", 14373 names: ["\\verb"], 14374 props: { 14375 numArgs: 0, 14376 allowedInText: true 14377 }, 14378 14379 handler(context, args, optArgs) { 14380 // \verb and \verb* are dealt with directly in Parser.js. 14381 // If we end up here, it's because of a failure to match the two delimiters 14382 // in the regex in Lexer.js. LaTeX raises the following error when \verb is 14383 // terminated by end of line (or file). 14384 throw new ParseError("\\verb ended by end of line instead of matching delimiter"); 14385 }, 14386 14387 htmlBuilder(group, options) { 14388 var text = makeVerb(group); 14389 var body = []; // \verb enters text mode and therefore is sized like \textstyle 14390 14391 var newOptions = options.havingStyle(options.style.text()); 14392 14393 for (var i = 0; i < text.length; i++) { 14394 var c = text[i]; 14395 14396 if (c === '~') { 14397 c = '\\textasciitilde'; 14398 } 14399 14400 body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"])); 14401 } 14402 14403 return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions); 14404 }, 14405 14406 mathmlBuilder(group, options) { 14407 var text = new mathMLTree.TextNode(makeVerb(group)); 14408 var node = new mathMLTree.MathNode("mtext", [text]); 14409 node.setAttribute("mathvariant", "monospace"); 14410 return node; 14411 } 14412 14413 }); 14414 /** 14415 * Converts verb group into body string. 14416 * 14417 * \verb* replaces each space with an open box \u2423 14418 * \verb replaces each space with a no-break space \xA0 14419 */ 14420 14421 var makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0'); 14422 14423 /** Include this to ensure that all functions are defined. */ 14424 var functions = _functions; 14425 14426 /** 14427 * The Lexer class handles tokenizing the input in various ways. Since our 14428 * parser expects us to be able to backtrack, the lexer allows lexing from any 14429 * given starting point. 14430 * 14431 * Its main exposed function is the `lex` function, which takes a position to 14432 * lex from and a type of token to lex. It defers to the appropriate `_innerLex` 14433 * function. 14434 * 14435 * The various `_innerLex` functions perform the actual lexing of different 14436 * kinds. 14437 */ 14438 14439 /* The following tokenRegex 14440 * - matches typical whitespace (but not NBSP etc.) using its first group 14441 * - does not match any control character \x00-\x1f except whitespace 14442 * - does not match a bare backslash 14443 * - matches any ASCII character except those just mentioned 14444 * - does not match the BMP private use area \uE000-\uF8FF 14445 * - does not match bare surrogate code units 14446 * - matches any BMP character except for those just described 14447 * - matches any valid Unicode surrogate pair 14448 * - matches a backslash followed by one or more letters 14449 * - matches a backslash followed by any BMP character, including newline 14450 * Just because the Lexer matches something doesn't mean it's valid input: 14451 * If there is no matching function or symbol definition, the Parser will 14452 * still reject the input. 14453 */ 14454 var spaceRegexString = "[ \r\n\t]"; 14455 var controlWordRegexString = "\\\\[a-zA-Z@]+"; 14456 var controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; 14457 var controlWordWhitespaceRegexString = "" + controlWordRegexString + spaceRegexString + "*"; 14458 var controlWordWhitespaceRegex = new RegExp("^(" + controlWordRegexString + ")" + spaceRegexString + "*$"); 14459 var combiningDiacriticalMarkString = "[\u0300-\u036f]"; 14460 var combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$"); 14461 var tokenRegexString = "(" + spaceRegexString + "+)|" + // whitespace 14462 "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + ( // single codepoint 14463 combiningDiacriticalMarkString + "*") + // ...plus accents 14464 "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + ( // surrogate pair 14465 combiningDiacriticalMarkString + "*") + // ...plus accents 14466 "|\\\\verb\\*([^]).*?\\3" + // \verb* 14467 "|\\\\verb([^*a-zA-Z]).*?\\4" + // \verb unstarred 14468 "|\\\\operatorname\\*" + ( // \operatorname* 14469 "|" + controlWordWhitespaceRegexString) + ( // \macroName + spaces 14470 "|" + controlSymbolRegexString + ")"); // \\, \', etc. 14471 14472 /** Main Lexer class */ 14473 14474 class Lexer { 14475 // category codes, only supports comment characters (14) for now 14476 constructor(input, settings) { 14477 this.input = void 0; 14478 this.settings = void 0; 14479 this.tokenRegex = void 0; 14480 this.catcodes = void 0; 14481 // Separate accents from characters 14482 this.input = input; 14483 this.settings = settings; 14484 this.tokenRegex = new RegExp(tokenRegexString, 'g'); 14485 this.catcodes = { 14486 "%": 14 // comment character 14487 14488 }; 14489 } 14490 14491 setCatcode(char, code) { 14492 this.catcodes[char] = code; 14493 } 14494 /** 14495 * This function lexes a single token. 14496 */ 14497 14498 14499 lex() { 14500 var input = this.input; 14501 var pos = this.tokenRegex.lastIndex; 14502 14503 if (pos === input.length) { 14504 return new Token("EOF", new SourceLocation(this, pos, pos)); 14505 } 14506 14507 var match = this.tokenRegex.exec(input); 14508 14509 if (match === null || match.index !== pos) { 14510 throw new ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1))); 14511 } 14512 14513 var text = match[2] || " "; 14514 14515 if (this.catcodes[text] === 14) { 14516 // comment character 14517 var nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex); 14518 14519 if (nlIndex === -1) { 14520 this.tokenRegex.lastIndex = input.length; // EOF 14521 14522 this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)"); 14523 } else { 14524 this.tokenRegex.lastIndex = nlIndex + 1; 14525 } 14526 14527 return this.lex(); 14528 } // Trim any trailing whitespace from control word match 14529 14530 14531 var controlMatch = text.match(controlWordWhitespaceRegex); 14532 14533 if (controlMatch) { 14534 text = controlMatch[1]; 14535 } 14536 14537 return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); 14538 } 14539 14540 } 14541 14542 /** 14543 * A `Namespace` refers to a space of nameable things like macros or lengths, 14544 * which can be `set` either globally or local to a nested group, using an 14545 * undo stack similar to how TeX implements this functionality. 14546 * Performance-wise, `get` and local `set` take constant time, while global 14547 * `set` takes time proportional to the depth of group nesting. 14548 */ 14549 class Namespace { 14550 /** 14551 * Both arguments are optional. The first argument is an object of 14552 * built-in mappings which never change. The second argument is an object 14553 * of initial (global-level) mappings, which will constantly change 14554 * according to any global/top-level `set`s done. 14555 */ 14556 constructor(builtins, globalMacros) { 14557 if (builtins === void 0) { 14558 builtins = {}; 14559 } 14560 14561 if (globalMacros === void 0) { 14562 globalMacros = {}; 14563 } 14564 14565 this.current = void 0; 14566 this.builtins = void 0; 14567 this.undefStack = void 0; 14568 this.current = globalMacros; 14569 this.builtins = builtins; 14570 this.undefStack = []; 14571 } 14572 /** 14573 * Start a new nested group, affecting future local `set`s. 14574 */ 14575 14576 14577 beginGroup() { 14578 this.undefStack.push({}); 14579 } 14580 /** 14581 * End current nested group, restoring values before the group began. 14582 */ 14583 14584 14585 endGroup() { 14586 if (this.undefStack.length === 0) { 14587 throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug"); 14588 } 14589 14590 var undefs = this.undefStack.pop(); 14591 14592 for (var undef in undefs) { 14593 if (undefs.hasOwnProperty(undef)) { 14594 if (undefs[undef] === undefined) { 14595 delete this.current[undef]; 14596 } else { 14597 this.current[undef] = undefs[undef]; 14598 } 14599 } 14600 } 14601 } 14602 /** 14603 * Detect whether `name` has a definition. Equivalent to 14604 * `get(name) != null`. 14605 */ 14606 14607 14608 has(name) { 14609 return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name); 14610 } 14611 /** 14612 * Get the current value of a name, or `undefined` if there is no value. 14613 * 14614 * Note: Do not use `if (namespace.get(...))` to detect whether a macro 14615 * is defined, as the definition may be the empty string which evaluates 14616 * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or 14617 * `if (namespace.has(...))`. 14618 */ 14619 14620 14621 get(name) { 14622 if (this.current.hasOwnProperty(name)) { 14623 return this.current[name]; 14624 } else { 14625 return this.builtins[name]; 14626 } 14627 } 14628 /** 14629 * Set the current value of a name, and optionally set it globally too. 14630 * Local set() sets the current value and (when appropriate) adds an undo 14631 * operation to the undo stack. Global set() may change the undo 14632 * operation at every level, so takes time linear in their number. 14633 */ 14634 14635 14636 set(name, value, global) { 14637 if (global === void 0) { 14638 global = false; 14639 } 14640 14641 if (global) { 14642 // Global set is equivalent to setting in all groups. Simulate this 14643 // by destroying any undos currently scheduled for this name, 14644 // and adding an undo with the *new* value (in case it later gets 14645 // locally reset within this environment). 14646 for (var i = 0; i < this.undefStack.length; i++) { 14647 delete this.undefStack[i][name]; 14648 } 14649 14650 if (this.undefStack.length > 0) { 14651 this.undefStack[this.undefStack.length - 1][name] = value; 14652 } 14653 } else { 14654 // Undo this set at end of this group (possibly to `undefined`), 14655 // unless an undo is already in place, in which case that older 14656 // value is the correct one. 14657 var top = this.undefStack[this.undefStack.length - 1]; 14658 14659 if (top && !top.hasOwnProperty(name)) { 14660 top[name] = this.current[name]; 14661 } 14662 } 14663 14664 this.current[name] = value; 14665 } 14666 14667 } 14668 14669 /** 14670 * Predefined macros for KaTeX. 14671 * This can be used to define some commands in terms of others. 14672 */ 14673 var builtinMacros = {}; 14674 14675 function defineMacro(name, body) { 14676 builtinMacros[name] = body; 14677 } ////////////////////////////////////////////////////////////////////// 14678 // macro tools 14679 14680 defineMacro("\\noexpand", function (context) { 14681 // The expansion is the token itself; but that token is interpreted 14682 // as if its meaning were ‘\relax’ if it is a control sequence that 14683 // would ordinarily be expanded by TeX’s expansion rules. 14684 var t = context.popToken(); 14685 14686 if (context.isExpandable(t.text)) { 14687 t.noexpand = true; 14688 t.treatAsRelax = true; 14689 } 14690 14691 return { 14692 tokens: [t], 14693 numArgs: 0 14694 }; 14695 }); 14696 defineMacro("\\expandafter", function (context) { 14697 // TeX first reads the token that comes immediately after \expandafter, 14698 // without expanding it; let’s call this token t. Then TeX reads the 14699 // token that comes after t (and possibly more tokens, if that token 14700 // has an argument), replacing it by its expansion. Finally TeX puts 14701 // t back in front of that expansion. 14702 var t = context.popToken(); 14703 context.expandOnce(true); // expand only an expandable token 14704 14705 return { 14706 tokens: [t], 14707 numArgs: 0 14708 }; 14709 }); // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 14710 // TeX source: \long\def\@firstoftwo#1#2{#1} 14711 14712 defineMacro("\\@firstoftwo", function (context) { 14713 var args = context.consumeArgs(2); 14714 return { 14715 tokens: args[0], 14716 numArgs: 0 14717 }; 14718 }); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 14719 // TeX source: \long\def\@secondoftwo#1#2{#2} 14720 14721 defineMacro("\\@secondoftwo", function (context) { 14722 var args = context.consumeArgs(2); 14723 return { 14724 tokens: args[1], 14725 numArgs: 0 14726 }; 14727 }); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) 14728 // symbol that isn't a space, consuming any spaces but not consuming the 14729 // first nonspace character. If that nonspace character matches #1, then 14730 // the macro expands to #2; otherwise, it expands to #3. 14731 14732 defineMacro("\\@ifnextchar", function (context) { 14733 var args = context.consumeArgs(3); // symbol, if, else 14734 14735 context.consumeSpaces(); 14736 var nextToken = context.future(); 14737 14738 if (args[0].length === 1 && args[0][0].text === nextToken.text) { 14739 return { 14740 tokens: args[1], 14741 numArgs: 0 14742 }; 14743 } else { 14744 return { 14745 tokens: args[2], 14746 numArgs: 0 14747 }; 14748 } 14749 }); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. 14750 // If it is `*`, then it consumes the symbol, and the macro expands to #1; 14751 // otherwise, the macro expands to #2 (without consuming the symbol). 14752 // TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} 14753 14754 defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode 14755 14756 defineMacro("\\TextOrMath", function (context) { 14757 var args = context.consumeArgs(2); 14758 14759 if (context.mode === 'text') { 14760 return { 14761 tokens: args[0], 14762 numArgs: 0 14763 }; 14764 } else { 14765 return { 14766 tokens: args[1], 14767 numArgs: 0 14768 }; 14769 } 14770 }); // Lookup table for parsing numbers in base 8 through 16 14771 14772 var digitToNumber = { 14773 "0": 0, 14774 "1": 1, 14775 "2": 2, 14776 "3": 3, 14777 "4": 4, 14778 "5": 5, 14779 "6": 6, 14780 "7": 7, 14781 "8": 8, 14782 "9": 9, 14783 "a": 10, 14784 "A": 10, 14785 "b": 11, 14786 "B": 11, 14787 "c": 12, 14788 "C": 12, 14789 "d": 13, 14790 "D": 13, 14791 "e": 14, 14792 "E": 14, 14793 "f": 15, 14794 "F": 15 14795 }; // TeX \char makes a literal character (catcode 12) using the following forms: 14796 // (see The TeXBook, p. 43) 14797 // \char123 -- decimal 14798 // \char'123 -- octal 14799 // \char"123 -- hex 14800 // \char`x -- character that can be written (i.e. isn't active) 14801 // \char`\x -- character that cannot be written (e.g. %) 14802 // These all refer to characters from the font, so we turn them into special 14803 // calls to a function \@char dealt with in the Parser. 14804 14805 defineMacro("\\char", function (context) { 14806 var token = context.popToken(); 14807 var base; 14808 var number = ''; 14809 14810 if (token.text === "'") { 14811 base = 8; 14812 token = context.popToken(); 14813 } else if (token.text === '"') { 14814 base = 16; 14815 token = context.popToken(); 14816 } else if (token.text === "`") { 14817 token = context.popToken(); 14818 14819 if (token.text[0] === "\\") { 14820 number = token.text.charCodeAt(1); 14821 } else if (token.text === "EOF") { 14822 throw new ParseError("\\char` missing argument"); 14823 } else { 14824 number = token.text.charCodeAt(0); 14825 } 14826 } else { 14827 base = 10; 14828 } 14829 14830 if (base) { 14831 // Parse a number in the given base, starting with first `token`. 14832 number = digitToNumber[token.text]; 14833 14834 if (number == null || number >= base) { 14835 throw new ParseError("Invalid base-" + base + " digit " + token.text); 14836 } 14837 14838 var digit; 14839 14840 while ((digit = digitToNumber[context.future().text]) != null && digit < base) { 14841 number *= base; 14842 number += digit; 14843 context.popToken(); 14844 } 14845 } 14846 14847 return "\\@char{" + number + "}"; 14848 }); // \newcommand{\macro}[args]{definition} 14849 // \renewcommand{\macro}[args]{definition} 14850 // TODO: Optional arguments: \newcommand{\macro}[args][default]{definition} 14851 14852 var newcommand = (context, existsOK, nonexistsOK) => { 14853 var arg = context.consumeArg().tokens; 14854 14855 if (arg.length !== 1) { 14856 throw new ParseError("\\newcommand's first argument must be a macro name"); 14857 } 14858 14859 var name = arg[0].text; 14860 var exists = context.isDefined(name); 14861 14862 if (exists && !existsOK) { 14863 throw new ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand")); 14864 } 14865 14866 if (!exists && !nonexistsOK) { 14867 throw new ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand"); 14868 } 14869 14870 var numArgs = 0; 14871 arg = context.consumeArg().tokens; 14872 14873 if (arg.length === 1 && arg[0].text === "[") { 14874 var argText = ''; 14875 var token = context.expandNextToken(); 14876 14877 while (token.text !== "]" && token.text !== "EOF") { 14878 // TODO: Should properly expand arg, e.g., ignore {}s 14879 argText += token.text; 14880 token = context.expandNextToken(); 14881 } 14882 14883 if (!argText.match(/^\s*[0-9]+\s*$/)) { 14884 throw new ParseError("Invalid number of arguments: " + argText); 14885 } 14886 14887 numArgs = parseInt(argText); 14888 arg = context.consumeArg().tokens; 14889 } // Final arg is the expansion of the macro 14890 14891 14892 context.macros.set(name, { 14893 tokens: arg, 14894 numArgs 14895 }); 14896 return ''; 14897 }; 14898 14899 defineMacro("\\newcommand", context => newcommand(context, false, true)); 14900 defineMacro("\\renewcommand", context => newcommand(context, true, false)); 14901 defineMacro("\\providecommand", context => newcommand(context, true, true)); // terminal (console) tools 14902 14903 defineMacro("\\message", context => { 14904 var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console 14905 14906 console.log(arg.reverse().map(token => token.text).join("")); 14907 return ''; 14908 }); 14909 defineMacro("\\errmessage", context => { 14910 var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console 14911 14912 console.error(arg.reverse().map(token => token.text).join("")); 14913 return ''; 14914 }); 14915 defineMacro("\\show", context => { 14916 var tok = context.popToken(); 14917 var name = tok.text; // eslint-disable-next-line no-console 14918 14919 console.log(tok, context.macros.get(name), functions[name], symbols.math[name], symbols.text[name]); 14920 return ''; 14921 }); ////////////////////////////////////////////////////////////////////// 14922 // Grouping 14923 // \let\bgroup={ \let\egroup=} 14924 14925 defineMacro("\\bgroup", "{"); 14926 defineMacro("\\egroup", "}"); // Symbols from latex.ltx: 14927 // \def\lq{`} 14928 // \def\rq{'} 14929 // \def \aa {\r a} 14930 // \def \AA {\r A} 14931 14932 defineMacro("\\lq", "`"); 14933 defineMacro("\\rq", "'"); 14934 defineMacro("\\aa", "\\r a"); 14935 defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML. 14936 // \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}} 14937 // \DeclareTextCommandDefault{\textregistered}{\textcircled{% 14938 // \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}} 14939 // \DeclareRobustCommand{\copyright}{% 14940 // \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi} 14941 14942 defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}"); 14943 defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"); 14944 defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF 14945 14946 defineMacro("\u212C", "\\mathscr{B}"); // script 14947 14948 defineMacro("\u2130", "\\mathscr{E}"); 14949 defineMacro("\u2131", "\\mathscr{F}"); 14950 defineMacro("\u210B", "\\mathscr{H}"); 14951 defineMacro("\u2110", "\\mathscr{I}"); 14952 defineMacro("\u2112", "\\mathscr{L}"); 14953 defineMacro("\u2133", "\\mathscr{M}"); 14954 defineMacro("\u211B", "\\mathscr{R}"); 14955 defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur 14956 14957 defineMacro("\u210C", "\\mathfrak{H}"); 14958 defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML. 14959 14960 defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot 14961 // The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays 14962 // the dot at U+22C5 and gives it punct spacing. 14963 14964 defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode 14965 14966 defineMacro("\\llap", "\\mathllap{\\textrm{#1}}"); 14967 defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}"); 14968 defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \mathstrut from the TeXbook, p 360 14969 14970 defineMacro("\\mathstrut", "\\vphantom{(}"); // \underbar from TeXbook p 353 14971 14972 defineMacro("\\underbar", "\\underline{\\text{#1}}"); // \not is defined by base/fontmath.ltx via 14973 // \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36} 14974 // It's thus treated like a \mathrel, but defined by a symbol that has zero 14975 // width but extends to the right. We use \rlap to get that spacing. 14976 // For MathML we write U+0338 here. buildMathML.js will then do the overlay. 14977 14978 defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx: 14979 // \def\neq{\not=} \let\ne=\neq 14980 // \DeclareRobustCommand 14981 // \notin{\mathrel{\m@th\mathpalette\c@ncel\in}} 14982 // \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}} 14983 14984 defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}"); 14985 defineMacro("\\ne", "\\neq"); 14986 defineMacro("\u2260", "\\neq"); 14987 defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}"); 14988 defineMacro("\u2209", "\\notin"); // Unicode stacked relations 14989 14990 defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}"); 14991 defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"); 14992 defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}"); 14993 defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}"); 14994 defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}"); 14995 defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}"); 14996 defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode 14997 14998 defineMacro("\u27C2", "\\perp"); 14999 defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}"); 15000 defineMacro("\u220C", "\\notni"); 15001 defineMacro("\u231C", "\\ulcorner"); 15002 defineMacro("\u231D", "\\urcorner"); 15003 defineMacro("\u231E", "\\llcorner"); 15004 defineMacro("\u231F", "\\lrcorner"); 15005 defineMacro("\u00A9", "\\copyright"); 15006 defineMacro("\u00AE", "\\textregistered"); 15007 defineMacro("\uFE0F", "\\textregistered"); // The KaTeX fonts have corners at codepoints that don't match Unicode. 15008 // For MathML purposes, use the Unicode code point. 15009 15010 defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}"); 15011 defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}"); 15012 defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}"); 15013 defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}"); ////////////////////////////////////////////////////////////////////// 15014 // LaTeX_2ε 15015 // \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ 15016 // \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} 15017 // We'll call \varvdots, which gets a glyph from symbols.js. 15018 // The zero-width rule gets us an equivalent to the vertical 6pt kern. 15019 15020 defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); 15021 defineMacro("\u22ee", "\\vdots"); ////////////////////////////////////////////////////////////////////// 15022 // amsmath.sty 15023 // http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf 15024 // Italic Greek capital letters. AMS defines these with \DeclareMathSymbol, 15025 // but they are equivalent to \mathit{\Letter}. 15026 15027 defineMacro("\\varGamma", "\\mathit{\\Gamma}"); 15028 defineMacro("\\varDelta", "\\mathit{\\Delta}"); 15029 defineMacro("\\varTheta", "\\mathit{\\Theta}"); 15030 defineMacro("\\varLambda", "\\mathit{\\Lambda}"); 15031 defineMacro("\\varXi", "\\mathit{\\Xi}"); 15032 defineMacro("\\varPi", "\\mathit{\\Pi}"); 15033 defineMacro("\\varSigma", "\\mathit{\\Sigma}"); 15034 defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}"); 15035 defineMacro("\\varPhi", "\\mathit{\\Phi}"); 15036 defineMacro("\\varPsi", "\\mathit{\\Psi}"); 15037 defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} 15038 15039 defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript 15040 // \mkern-\thinmuskip{:}\mskip6muplus1mu\relax} 15041 15042 defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} 15043 15044 defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;} 15045 // \def\implies{\DOTSB\;\Longrightarrow\;} 15046 // \def\impliedby{\DOTSB\;\Longleftarrow\;} 15047 15048 defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); 15049 defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); 15050 defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // AMSMath's automatic \dots, based on \mdots@@ macro. 15051 15052 var dotsByToken = { 15053 ',': '\\dotsc', 15054 '\\not': '\\dotsb', 15055 // \keybin@ checks for the following: 15056 '+': '\\dotsb', 15057 '=': '\\dotsb', 15058 '<': '\\dotsb', 15059 '>': '\\dotsb', 15060 '-': '\\dotsb', 15061 '*': '\\dotsb', 15062 ':': '\\dotsb', 15063 // Symbols whose definition starts with \DOTSB: 15064 '\\DOTSB': '\\dotsb', 15065 '\\coprod': '\\dotsb', 15066 '\\bigvee': '\\dotsb', 15067 '\\bigwedge': '\\dotsb', 15068 '\\biguplus': '\\dotsb', 15069 '\\bigcap': '\\dotsb', 15070 '\\bigcup': '\\dotsb', 15071 '\\prod': '\\dotsb', 15072 '\\sum': '\\dotsb', 15073 '\\bigotimes': '\\dotsb', 15074 '\\bigoplus': '\\dotsb', 15075 '\\bigodot': '\\dotsb', 15076 '\\bigsqcup': '\\dotsb', 15077 '\\And': '\\dotsb', 15078 '\\longrightarrow': '\\dotsb', 15079 '\\Longrightarrow': '\\dotsb', 15080 '\\longleftarrow': '\\dotsb', 15081 '\\Longleftarrow': '\\dotsb', 15082 '\\longleftrightarrow': '\\dotsb', 15083 '\\Longleftrightarrow': '\\dotsb', 15084 '\\mapsto': '\\dotsb', 15085 '\\longmapsto': '\\dotsb', 15086 '\\hookrightarrow': '\\dotsb', 15087 '\\doteq': '\\dotsb', 15088 // Symbols whose definition starts with \mathbin: 15089 '\\mathbin': '\\dotsb', 15090 // Symbols whose definition starts with \mathrel: 15091 '\\mathrel': '\\dotsb', 15092 '\\relbar': '\\dotsb', 15093 '\\Relbar': '\\dotsb', 15094 '\\xrightarrow': '\\dotsb', 15095 '\\xleftarrow': '\\dotsb', 15096 // Symbols whose definition starts with \DOTSI: 15097 '\\DOTSI': '\\dotsi', 15098 '\\int': '\\dotsi', 15099 '\\oint': '\\dotsi', 15100 '\\iint': '\\dotsi', 15101 '\\iiint': '\\dotsi', 15102 '\\iiiint': '\\dotsi', 15103 '\\idotsint': '\\dotsi', 15104 // Symbols whose definition starts with \DOTSX: 15105 '\\DOTSX': '\\dotsx' 15106 }; 15107 defineMacro("\\dots", function (context) { 15108 // TODO: If used in text mode, should expand to \textellipsis. 15109 // However, in KaTeX, \textellipsis and \ldots behave the same 15110 // (in text mode), and it's unlikely we'd see any of the math commands 15111 // that affect the behavior of \dots when in text mode. So fine for now 15112 // (until we support \ifmmode ... \else ... \fi). 15113 var thedots = '\\dotso'; 15114 var next = context.expandAfterFuture().text; 15115 15116 if (next in dotsByToken) { 15117 thedots = dotsByToken[next]; 15118 } else if (next.substr(0, 4) === '\\not') { 15119 thedots = '\\dotsb'; 15120 } else if (next in symbols.math) { 15121 if (utils.contains(['bin', 'rel'], symbols.math[next].group)) { 15122 thedots = '\\dotsb'; 15123 } 15124 } 15125 15126 return thedots; 15127 }); 15128 var spaceAfterDots = { 15129 // \rightdelim@ checks for the following: 15130 ')': true, 15131 ']': true, 15132 '\\rbrack': true, 15133 '\\}': true, 15134 '\\rbrace': true, 15135 '\\rangle': true, 15136 '\\rceil': true, 15137 '\\rfloor': true, 15138 '\\rgroup': true, 15139 '\\rmoustache': true, 15140 '\\right': true, 15141 '\\bigr': true, 15142 '\\biggr': true, 15143 '\\Bigr': true, 15144 '\\Biggr': true, 15145 // \extra@ also tests for the following: 15146 '$': true, 15147 // \extrap@ checks for the following: 15148 ';': true, 15149 '.': true, 15150 ',': true 15151 }; 15152 defineMacro("\\dotso", function (context) { 15153 var next = context.future().text; 15154 15155 if (next in spaceAfterDots) { 15156 return "\\ldots\\,"; 15157 } else { 15158 return "\\ldots"; 15159 } 15160 }); 15161 defineMacro("\\dotsc", function (context) { 15162 var next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for 15163 // ';' and '.', but doesn't check for ','. 15164 15165 if (next in spaceAfterDots && next !== ',') { 15166 return "\\ldots\\,"; 15167 } else { 15168 return "\\ldots"; 15169 } 15170 }); 15171 defineMacro("\\cdots", function (context) { 15172 var next = context.future().text; 15173 15174 if (next in spaceAfterDots) { 15175 return "\\@cdots\\,"; 15176 } else { 15177 return "\\@cdots"; 15178 } 15179 }); 15180 defineMacro("\\dotsb", "\\cdots"); 15181 defineMacro("\\dotsm", "\\cdots"); 15182 defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro 15183 // starting with \DOTSX implies \dotso, and then \extra@ detects this case 15184 // and forces the added `\,`. 15185 15186 defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax 15187 // \let\DOTSB\relax 15188 // \let\DOTSX\relax 15189 15190 defineMacro("\\DOTSI", "\\relax"); 15191 defineMacro("\\DOTSB", "\\relax"); 15192 defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults 15193 // \DeclareRobustCommand{\tmspace}[3]{% 15194 // \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} 15195 15196 defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} 15197 // TODO: math mode should use \thinmuskip 15198 15199 defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\, 15200 15201 defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip} 15202 // \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} 15203 // TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu 15204 15205 defineMacro("\\>", "\\mskip{4mu}"); 15206 defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\: 15207 15208 defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} 15209 // TODO: math mode should use \thickmuskip = 5mu plus 5mu 15210 15211 defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\; 15212 15213 defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} 15214 // TODO: math mode should use \thinmuskip 15215 15216 defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\! 15217 15218 defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} 15219 // TODO: math mode should use \medmuskip 15220 15221 defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} 15222 // TODO: math mode should use \thickmuskip 15223 15224 defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em } 15225 15226 defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax} 15227 15228 defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax} 15229 15230 defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax} 15231 15232 defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag 15233 15234 defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); 15235 defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); 15236 defineMacro("\\tag@literal", context => { 15237 if (context.macros.get("\\df@tag")) { 15238 throw new ParseError("Multiple \\tag"); 15239 } 15240 15241 return "\\gdef\\df@tag{\\text{#1}}"; 15242 }); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin 15243 // {\operator@font mod}\penalty900 15244 // \mkern5mu\nonscript\mskip-\medmuskip} 15245 // \newcommand{\pod}[1]{\allowbreak 15246 // \if@display\mkern18mu\else\mkern8mu\fi(#1)} 15247 // \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} 15248 // \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu 15249 // \else\mkern12mu\fi{\operator@font mod}\,\,#1} 15250 // TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu 15251 15252 defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"); 15253 defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"); 15254 defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); 15255 defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); // \pmb -- A simulation of bold. 15256 // The version in ambsy.sty works by typesetting three copies of the argument 15257 // with small offsets. We use two copies. We omit the vertical offset because 15258 // of rendering problems that makeVList encounters in Safari. 15259 15260 defineMacro("\\pmb", "\\html@mathml{" + "\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" + "{\\mathbf{#1}}"); ////////////////////////////////////////////////////////////////////// 15261 // LaTeX source2e 15262 // \expandafter\let\expandafter\@normalcr 15263 // \csname\expandafter\@gobble\string\\ \endcsname 15264 // \DeclareRobustCommand\newline{\@normalcr\relax} 15265 15266 defineMacro("\\newline", "\\\\\\relax"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} 15267 // TODO: Doesn't normally work in math mode because \@ fails. KaTeX doesn't 15268 // support \@ yet, so that's omitted, and we add \text so that the result 15269 // doesn't look funny in math mode. 15270 15271 defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em% 15272 // {\sbox\z@ T% 15273 // \vbox to\ht\z@{\hbox{\check@mathfonts 15274 // \fontsize\sf@size\z@ 15275 // \math@fontsfalse\selectfont 15276 // A}% 15277 // \vss}% 15278 // }% 15279 // \kern-.15em% 15280 // \TeX} 15281 // This code aligns the top of the A with the T (from the perspective of TeX's 15282 // boxes, though visually the A appears to extend above slightly). 15283 // We compute the corresponding \raisebox when A is rendered in \normalsize 15284 // \scriptstyle, which has a scale factor of 0.7 (see Options.js). 15285 15286 var latexRaiseA = fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1] + "em"; 15287 defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo 15288 15289 defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} 15290 // \def\@hspace#1{\hskip #1\relax} 15291 // \def\@hspacer#1{\vrule \@width\z@\nobreak 15292 // \hskip #1\hskip \z@skip} 15293 15294 defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); 15295 defineMacro("\\@hspace", "\\hskip #1\\relax"); 15296 defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); ////////////////////////////////////////////////////////////////////// 15297 // mathtools.sty 15298 //\providecommand\ordinarycolon{:} 15299 15300 defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}} 15301 //TODO(edemaine): Not yet centered. Fix via \raisebox or #726 15302 15303 defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon} 15304 15305 defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=} 15306 15307 defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔ 15308 // \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=} 15309 15310 defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} 15311 15312 defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} 15313 15314 defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon} 15315 15316 defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕ 15317 // \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} 15318 15319 defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon} 15320 15321 defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} 15322 15323 defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} 15324 15325 defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} 15326 15327 defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} 15328 15329 defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} 15330 15331 defineMacro("\\Colonsim", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"2237\\char\"223c}}"); // Some Unicode characters are implemented with macros to mathtools functions. 15332 15333 defineMacro("\u2237", "\\dblcolon"); // :: 15334 15335 defineMacro("\u2239", "\\eqcolon"); // -: 15336 15337 defineMacro("\u2254", "\\coloneqq"); // := 15338 15339 defineMacro("\u2255", "\\eqqcolon"); // =: 15340 15341 defineMacro("\u2A74", "\\Coloneqq"); // ::= 15342 ////////////////////////////////////////////////////////////////////// 15343 // colonequals.sty 15344 // Alternate names for mathtools's macros: 15345 15346 defineMacro("\\ratio", "\\vcentcolon"); 15347 defineMacro("\\coloncolon", "\\dblcolon"); 15348 defineMacro("\\colonequals", "\\coloneqq"); 15349 defineMacro("\\coloncolonequals", "\\Coloneqq"); 15350 defineMacro("\\equalscolon", "\\eqqcolon"); 15351 defineMacro("\\equalscoloncolon", "\\Eqqcolon"); 15352 defineMacro("\\colonminus", "\\coloneq"); 15353 defineMacro("\\coloncolonminus", "\\Coloneq"); 15354 defineMacro("\\minuscolon", "\\eqcolon"); 15355 defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals. 15356 15357 defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals. 15358 15359 defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions: 15360 15361 defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"); 15362 defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"); 15363 defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"); 15364 defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts 15365 15366 defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}"); 15367 defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); 15368 defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); ////////////////////////////////////////////////////////////////////// 15369 // From amsopn.sty 15370 15371 defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); 15372 defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); 15373 defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}"); 15374 defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}"); 15375 defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}"); 15376 defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"); ////////////////////////////////////////////////////////////////////// 15377 // MathML alternates for KaTeX glyphs in the Unicode private area 15378 15379 defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}"); 15380 defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}"); 15381 defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}"); 15382 defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}"); 15383 defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}"); 15384 defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}"); 15385 defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}"); 15386 defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}"); 15387 defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}"); 15388 defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}"); 15389 defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}"); 15390 defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}"); 15391 defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}"); 15392 defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}"); 15393 defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}"); 15394 defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"); ////////////////////////////////////////////////////////////////////// 15395 // stmaryrd and semantic 15396 // The stmaryrd and semantic packages render the next four items by calling a 15397 // glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros. 15398 15399 defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}"); 15400 defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}"); 15401 defineMacro("\u27e6", "\\llbracket"); // blackboard bold [ 15402 15403 defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ] 15404 15405 defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}"); 15406 defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}"); 15407 defineMacro("\u2983", "\\lBrace"); // blackboard bold { 15408 15409 defineMacro("\u2984", "\\rBrace"); // blackboard bold } 15410 // TODO: Create variable sized versions of the last two items. I believe that 15411 // will require new font glyphs. 15412 // The stmaryrd function `\minuso` provides a "Plimsoll" symbol that 15413 // superimposes the characters \circ and \mathminus. Used in chemistry. 15414 15415 defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}"); 15416 defineMacro("⦵", "\\minuso"); ////////////////////////////////////////////////////////////////////// 15417 // texvc.sty 15418 // The texvc package contains macros available in mediawiki pages. 15419 // We omit the functions deprecated at 15420 // https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax 15421 // We also omit texvc's \O, which conflicts with \text{\O} 15422 15423 defineMacro("\\darr", "\\downarrow"); 15424 defineMacro("\\dArr", "\\Downarrow"); 15425 defineMacro("\\Darr", "\\Downarrow"); 15426 defineMacro("\\lang", "\\langle"); 15427 defineMacro("\\rang", "\\rangle"); 15428 defineMacro("\\uarr", "\\uparrow"); 15429 defineMacro("\\uArr", "\\Uparrow"); 15430 defineMacro("\\Uarr", "\\Uparrow"); 15431 defineMacro("\\N", "\\mathbb{N}"); 15432 defineMacro("\\R", "\\mathbb{R}"); 15433 defineMacro("\\Z", "\\mathbb{Z}"); 15434 defineMacro("\\alef", "\\aleph"); 15435 defineMacro("\\alefsym", "\\aleph"); 15436 defineMacro("\\Alpha", "\\mathrm{A}"); 15437 defineMacro("\\Beta", "\\mathrm{B}"); 15438 defineMacro("\\bull", "\\bullet"); 15439 defineMacro("\\Chi", "\\mathrm{X}"); 15440 defineMacro("\\clubs", "\\clubsuit"); 15441 defineMacro("\\cnums", "\\mathbb{C}"); 15442 defineMacro("\\Complex", "\\mathbb{C}"); 15443 defineMacro("\\Dagger", "\\ddagger"); 15444 defineMacro("\\diamonds", "\\diamondsuit"); 15445 defineMacro("\\empty", "\\emptyset"); 15446 defineMacro("\\Epsilon", "\\mathrm{E}"); 15447 defineMacro("\\Eta", "\\mathrm{H}"); 15448 defineMacro("\\exist", "\\exists"); 15449 defineMacro("\\harr", "\\leftrightarrow"); 15450 defineMacro("\\hArr", "\\Leftrightarrow"); 15451 defineMacro("\\Harr", "\\Leftrightarrow"); 15452 defineMacro("\\hearts", "\\heartsuit"); 15453 defineMacro("\\image", "\\Im"); 15454 defineMacro("\\infin", "\\infty"); 15455 defineMacro("\\Iota", "\\mathrm{I}"); 15456 defineMacro("\\isin", "\\in"); 15457 defineMacro("\\Kappa", "\\mathrm{K}"); 15458 defineMacro("\\larr", "\\leftarrow"); 15459 defineMacro("\\lArr", "\\Leftarrow"); 15460 defineMacro("\\Larr", "\\Leftarrow"); 15461 defineMacro("\\lrarr", "\\leftrightarrow"); 15462 defineMacro("\\lrArr", "\\Leftrightarrow"); 15463 defineMacro("\\Lrarr", "\\Leftrightarrow"); 15464 defineMacro("\\Mu", "\\mathrm{M}"); 15465 defineMacro("\\natnums", "\\mathbb{N}"); 15466 defineMacro("\\Nu", "\\mathrm{N}"); 15467 defineMacro("\\Omicron", "\\mathrm{O}"); 15468 defineMacro("\\plusmn", "\\pm"); 15469 defineMacro("\\rarr", "\\rightarrow"); 15470 defineMacro("\\rArr", "\\Rightarrow"); 15471 defineMacro("\\Rarr", "\\Rightarrow"); 15472 defineMacro("\\real", "\\Re"); 15473 defineMacro("\\reals", "\\mathbb{R}"); 15474 defineMacro("\\Reals", "\\mathbb{R}"); 15475 defineMacro("\\Rho", "\\mathrm{P}"); 15476 defineMacro("\\sdot", "\\cdot"); 15477 defineMacro("\\sect", "\\S"); 15478 defineMacro("\\spades", "\\spadesuit"); 15479 defineMacro("\\sub", "\\subset"); 15480 defineMacro("\\sube", "\\subseteq"); 15481 defineMacro("\\supe", "\\supseteq"); 15482 defineMacro("\\Tau", "\\mathrm{T}"); 15483 defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}"); 15484 15485 defineMacro("\\weierp", "\\wp"); 15486 defineMacro("\\Zeta", "\\mathrm{Z}"); ////////////////////////////////////////////////////////////////////// 15487 // statmath.sty 15488 // https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf 15489 15490 defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); 15491 defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); 15492 defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); ////////////////////////////////////////////////////////////////////// 15493 // braket.sty 15494 // http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf 15495 15496 defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); 15497 defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); 15498 defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); 15499 defineMacro("\\Bra", "\\left\\langle#1\\right|"); 15500 defineMacro("\\Ket", "\\left|#1\\right\\rangle"); ////////////////////////////////////////////////////////////////////// 15501 // actuarialangle.dtx 15502 15503 defineMacro("\\angln", "{\\angl n}"); // Custom Khan Academy colors, should be moved to an optional package 15504 15505 defineMacro("\\blue", "\\textcolor{##6495ed}{#1}"); 15506 defineMacro("\\orange", "\\textcolor{##ffa500}{#1}"); 15507 defineMacro("\\pink", "\\textcolor{##ff00af}{#1}"); 15508 defineMacro("\\red", "\\textcolor{##df0030}{#1}"); 15509 defineMacro("\\green", "\\textcolor{##28ae7b}{#1}"); 15510 defineMacro("\\gray", "\\textcolor{gray}{#1}"); 15511 defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}"); 15512 defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}"); 15513 defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}"); 15514 defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}"); 15515 defineMacro("\\blueD", "\\textcolor{##11accd}{#1}"); 15516 defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}"); 15517 defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}"); 15518 defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}"); 15519 defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}"); 15520 defineMacro("\\tealD", "\\textcolor{##01a995}{#1}"); 15521 defineMacro("\\tealE", "\\textcolor{##208170}{#1}"); 15522 defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}"); 15523 defineMacro("\\greenB", "\\textcolor{##8af281}{#1}"); 15524 defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}"); 15525 defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}"); 15526 defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}"); 15527 defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}"); 15528 defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}"); 15529 defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}"); 15530 defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}"); 15531 defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}"); 15532 defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}"); 15533 defineMacro("\\redB", "\\textcolor{##ff8482}{#1}"); 15534 defineMacro("\\redC", "\\textcolor{##f9685d}{#1}"); 15535 defineMacro("\\redD", "\\textcolor{##e84d39}{#1}"); 15536 defineMacro("\\redE", "\\textcolor{##bc2612}{#1}"); 15537 defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}"); 15538 defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}"); 15539 defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}"); 15540 defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}"); 15541 defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}"); 15542 defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}"); 15543 defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}"); 15544 defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}"); 15545 defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}"); 15546 defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}"); 15547 defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}"); 15548 defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}"); 15549 defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}"); 15550 defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}"); 15551 defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}"); 15552 defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}"); 15553 defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}"); 15554 defineMacro("\\grayE", "\\textcolor{##babec2}{#1}"); 15555 defineMacro("\\grayF", "\\textcolor{##888d93}{#1}"); 15556 defineMacro("\\grayG", "\\textcolor{##626569}{#1}"); 15557 defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}"); 15558 defineMacro("\\grayI", "\\textcolor{##21242c}{#1}"); 15559 defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}"); 15560 defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}"); 15561 15562 /** 15563 * This file contains the “gullet” where macros are expanded 15564 * until only non-macro tokens remain. 15565 */ 15566 // List of commands that act like macros but aren't defined as a macro, 15567 // function, or symbol. Used in `isDefined`. 15568 var implicitCommands = { 15569 "\\relax": true, 15570 // MacroExpander.js 15571 "^": true, 15572 // Parser.js 15573 "_": true, 15574 // Parser.js 15575 "\\limits": true, 15576 // Parser.js 15577 "\\nolimits": true // Parser.js 15578 15579 }; 15580 class MacroExpander { 15581 constructor(input, settings, mode) { 15582 this.settings = void 0; 15583 this.expansionCount = void 0; 15584 this.lexer = void 0; 15585 this.macros = void 0; 15586 this.stack = void 0; 15587 this.mode = void 0; 15588 this.settings = settings; 15589 this.expansionCount = 0; 15590 this.feed(input); // Make new global namespace 15591 15592 this.macros = new Namespace(builtinMacros, settings.macros); 15593 this.mode = mode; 15594 this.stack = []; // contains tokens in REVERSE order 15595 } 15596 /** 15597 * Feed a new input string to the same MacroExpander 15598 * (with existing macros etc.). 15599 */ 15600 15601 15602 feed(input) { 15603 this.lexer = new Lexer(input, this.settings); 15604 } 15605 /** 15606 * Switches between "text" and "math" modes. 15607 */ 15608 15609 15610 switchMode(newMode) { 15611 this.mode = newMode; 15612 } 15613 /** 15614 * Start a new group nesting within all namespaces. 15615 */ 15616 15617 15618 beginGroup() { 15619 this.macros.beginGroup(); 15620 } 15621 /** 15622 * End current group nesting within all namespaces. 15623 */ 15624 15625 15626 endGroup() { 15627 this.macros.endGroup(); 15628 } 15629 /** 15630 * Returns the topmost token on the stack, without expanding it. 15631 * Similar in behavior to TeX's `\futurelet`. 15632 */ 15633 15634 15635 future() { 15636 if (this.stack.length === 0) { 15637 this.pushToken(this.lexer.lex()); 15638 } 15639 15640 return this.stack[this.stack.length - 1]; 15641 } 15642 /** 15643 * Remove and return the next unexpanded token. 15644 */ 15645 15646 15647 popToken() { 15648 this.future(); // ensure non-empty stack 15649 15650 return this.stack.pop(); 15651 } 15652 /** 15653 * Add a given token to the token stack. In particular, this get be used 15654 * to put back a token returned from one of the other methods. 15655 */ 15656 15657 15658 pushToken(token) { 15659 this.stack.push(token); 15660 } 15661 /** 15662 * Append an array of tokens to the token stack. 15663 */ 15664 15665 15666 pushTokens(tokens) { 15667 this.stack.push(...tokens); 15668 } 15669 /** 15670 * Find an macro argument without expanding tokens and append the array of 15671 * tokens to the token stack. Uses Token as a container for the result. 15672 */ 15673 15674 15675 scanArgument(isOptional) { 15676 var start; 15677 var end; 15678 var tokens; 15679 15680 if (isOptional) { 15681 this.consumeSpaces(); // \@ifnextchar gobbles any space following it 15682 15683 if (this.future().text !== "[") { 15684 return null; 15685 } 15686 15687 start = this.popToken(); // don't include [ in tokens 15688 15689 ({ 15690 tokens, 15691 end 15692 } = this.consumeArg(["]"])); 15693 } else { 15694 ({ 15695 tokens, 15696 start, 15697 end 15698 } = this.consumeArg()); 15699 } // indicate the end of an argument 15700 15701 15702 this.pushToken(new Token("EOF", end.loc)); 15703 this.pushTokens(tokens); 15704 return start.range(end, ""); 15705 } 15706 /** 15707 * Consume all following space tokens, without expansion. 15708 */ 15709 15710 15711 consumeSpaces() { 15712 for (;;) { 15713 var token = this.future(); 15714 15715 if (token.text === " ") { 15716 this.stack.pop(); 15717 } else { 15718 break; 15719 } 15720 } 15721 } 15722 /** 15723 * Consume an argument from the token stream, and return the resulting array 15724 * of tokens and start/end token. 15725 */ 15726 15727 15728 consumeArg(delims) { 15729 // The argument for a delimited parameter is the shortest (possibly 15730 // empty) sequence of tokens with properly nested {...} groups that is 15731 // followed ... by this particular list of non-parameter tokens. 15732 // The argument for an undelimited parameter is the next nonblank 15733 // token, unless that token is ‘{’, when the argument will be the 15734 // entire {...} group that follows. 15735 var tokens = []; 15736 var isDelimited = delims && delims.length > 0; 15737 15738 if (!isDelimited) { 15739 // Ignore spaces between arguments. As the TeXbook says: 15740 // "After you have said ‘\def\row#1#2{...}’, you are allowed to 15741 // put spaces between the arguments (e.g., ‘\row x n’), because 15742 // TeX doesn’t use single spaces as undelimited arguments." 15743 this.consumeSpaces(); 15744 } 15745 15746 var start = this.future(); 15747 var tok; 15748 var depth = 0; 15749 var match = 0; 15750 15751 do { 15752 tok = this.popToken(); 15753 tokens.push(tok); 15754 15755 if (tok.text === "{") { 15756 ++depth; 15757 } else if (tok.text === "}") { 15758 --depth; 15759 15760 if (depth === -1) { 15761 throw new ParseError("Extra }", tok); 15762 } 15763 } else if (tok.text === "EOF") { 15764 throw new ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok); 15765 } 15766 15767 if (delims && isDelimited) { 15768 if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) { 15769 ++match; 15770 15771 if (match === delims.length) { 15772 // don't include delims in tokens 15773 tokens.splice(-match, match); 15774 break; 15775 } 15776 } else { 15777 match = 0; 15778 } 15779 } 15780 } while (depth !== 0 || isDelimited); // If the argument found ... has the form ‘{<nested tokens>}’, 15781 // ... the outermost braces enclosing the argument are removed 15782 15783 15784 if (start.text === "{" && tokens[tokens.length - 1].text === "}") { 15785 tokens.pop(); 15786 tokens.shift(); 15787 } 15788 15789 tokens.reverse(); // to fit in with stack order 15790 15791 return { 15792 tokens, 15793 start, 15794 end: tok 15795 }; 15796 } 15797 /** 15798 * Consume the specified number of (delimited) arguments from the token 15799 * stream and return the resulting array of arguments. 15800 */ 15801 15802 15803 consumeArgs(numArgs, delimiters) { 15804 if (delimiters) { 15805 if (delimiters.length !== numArgs + 1) { 15806 throw new ParseError("The length of delimiters doesn't match the number of args!"); 15807 } 15808 15809 var delims = delimiters[0]; 15810 15811 for (var i = 0; i < delims.length; i++) { 15812 var tok = this.popToken(); 15813 15814 if (delims[i] !== tok.text) { 15815 throw new ParseError("Use of the macro doesn't match its definition", tok); 15816 } 15817 } 15818 } 15819 15820 var args = []; 15821 15822 for (var _i = 0; _i < numArgs; _i++) { 15823 args.push(this.consumeArg(delimiters && delimiters[_i + 1]).tokens); 15824 } 15825 15826 return args; 15827 } 15828 /** 15829 * Expand the next token only once if possible. 15830 * 15831 * If the token is expanded, the resulting tokens will be pushed onto 15832 * the stack in reverse order and will be returned as an array, 15833 * also in reverse order. 15834 * 15835 * If not, the next token will be returned without removing it 15836 * from the stack. This case can be detected by a `Token` return value 15837 * instead of an `Array` return value. 15838 * 15839 * In either case, the next token will be on the top of the stack, 15840 * or the stack will be empty. 15841 * 15842 * Used to implement `expandAfterFuture` and `expandNextToken`. 15843 * 15844 * If expandableOnly, only expandable tokens are expanded and 15845 * an undefined control sequence results in an error. 15846 */ 15847 15848 15849 expandOnce(expandableOnly) { 15850 var topToken = this.popToken(); 15851 var name = topToken.text; 15852 var expansion = !topToken.noexpand ? this._getExpansion(name) : null; 15853 15854 if (expansion == null || expandableOnly && expansion.unexpandable) { 15855 if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { 15856 throw new ParseError("Undefined control sequence: " + name); 15857 } 15858 15859 this.pushToken(topToken); 15860 return topToken; 15861 } 15862 15863 this.expansionCount++; 15864 15865 if (this.expansionCount > this.settings.maxExpand) { 15866 throw new ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting"); 15867 } 15868 15869 var tokens = expansion.tokens; 15870 var args = this.consumeArgs(expansion.numArgs, expansion.delimiters); 15871 15872 if (expansion.numArgs) { 15873 // paste arguments in place of the placeholders 15874 tokens = tokens.slice(); // make a shallow copy 15875 15876 for (var i = tokens.length - 1; i >= 0; --i) { 15877 var tok = tokens[i]; 15878 15879 if (tok.text === "#") { 15880 if (i === 0) { 15881 throw new ParseError("Incomplete placeholder at end of macro body", tok); 15882 } 15883 15884 tok = tokens[--i]; // next token on stack 15885 15886 if (tok.text === "#") { 15887 // ## → # 15888 tokens.splice(i + 1, 1); // drop first # 15889 } else if (/^[1-9]$/.test(tok.text)) { 15890 // replace the placeholder with the indicated argument 15891 tokens.splice(i, 2, ...args[+tok.text - 1]); 15892 } else { 15893 throw new ParseError("Not a valid argument number", tok); 15894 } 15895 } 15896 } 15897 } // Concatenate expansion onto top of stack. 15898 15899 15900 this.pushTokens(tokens); 15901 return tokens; 15902 } 15903 /** 15904 * Expand the next token only once (if possible), and return the resulting 15905 * top token on the stack (without removing anything from the stack). 15906 * Similar in behavior to TeX's `\expandafter\futurelet`. 15907 * Equivalent to expandOnce() followed by future(). 15908 */ 15909 15910 15911 expandAfterFuture() { 15912 this.expandOnce(); 15913 return this.future(); 15914 } 15915 /** 15916 * Recursively expand first token, then return first non-expandable token. 15917 */ 15918 15919 15920 expandNextToken() { 15921 for (;;) { 15922 var expanded = this.expandOnce(); // expandOnce returns Token if and only if it's fully expanded. 15923 15924 if (expanded instanceof Token) { 15925 // \relax stops the expansion, but shouldn't get returned (a 15926 // null return value couldn't get implemented as a function). 15927 // the token after \noexpand is interpreted as if its meaning 15928 // were ‘\relax’ 15929 if (expanded.text === "\\relax" || expanded.treatAsRelax) { 15930 this.stack.pop(); 15931 } else { 15932 return this.stack.pop(); // === expanded 15933 } 15934 } 15935 } // Flow unable to figure out that this pathway is impossible. 15936 // https://github.com/facebook/flow/issues/4808 15937 15938 15939 throw new Error(); // eslint-disable-line no-unreachable 15940 } 15941 /** 15942 * Fully expand the given macro name and return the resulting list of 15943 * tokens, or return `undefined` if no such macro is defined. 15944 */ 15945 15946 15947 expandMacro(name) { 15948 return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; 15949 } 15950 /** 15951 * Fully expand the given token stream and return the resulting list of tokens 15952 */ 15953 15954 15955 expandTokens(tokens) { 15956 var output = []; 15957 var oldStackLength = this.stack.length; 15958 this.pushTokens(tokens); 15959 15960 while (this.stack.length > oldStackLength) { 15961 var expanded = this.expandOnce(true); // expand only expandable tokens 15962 // expandOnce returns Token if and only if it's fully expanded. 15963 15964 if (expanded instanceof Token) { 15965 if (expanded.treatAsRelax) { 15966 // the expansion of \noexpand is the token itself 15967 expanded.noexpand = false; 15968 expanded.treatAsRelax = false; 15969 } 15970 15971 output.push(this.stack.pop()); 15972 } 15973 } 15974 15975 return output; 15976 } 15977 /** 15978 * Fully expand the given macro name and return the result as a string, 15979 * or return `undefined` if no such macro is defined. 15980 */ 15981 15982 15983 expandMacroAsText(name) { 15984 var tokens = this.expandMacro(name); 15985 15986 if (tokens) { 15987 return tokens.map(token => token.text).join(""); 15988 } else { 15989 return tokens; 15990 } 15991 } 15992 /** 15993 * Returns the expanded macro as a reversed array of tokens and a macro 15994 * argument count. Or returns `null` if no such macro. 15995 */ 15996 15997 15998 _getExpansion(name) { 15999 var definition = this.macros.get(name); 16000 16001 if (definition == null) { 16002 // mainly checking for undefined here 16003 return definition; 16004 } 16005 16006 var expansion = typeof definition === "function" ? definition(this) : definition; 16007 16008 if (typeof expansion === "string") { 16009 var numArgs = 0; 16010 16011 if (expansion.indexOf("#") !== -1) { 16012 var stripped = expansion.replace(/##/g, ""); 16013 16014 while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { 16015 ++numArgs; 16016 } 16017 } 16018 16019 var bodyLexer = new Lexer(expansion, this.settings); 16020 var tokens = []; 16021 var tok = bodyLexer.lex(); 16022 16023 while (tok.text !== "EOF") { 16024 tokens.push(tok); 16025 tok = bodyLexer.lex(); 16026 } 16027 16028 tokens.reverse(); // to fit in with stack using push and pop 16029 16030 var expanded = { 16031 tokens, 16032 numArgs 16033 }; 16034 return expanded; 16035 } 16036 16037 return expansion; 16038 } 16039 /** 16040 * Determine whether a command is currently "defined" (has some 16041 * functionality), meaning that it's a macro (in the current group), 16042 * a function, a symbol, or one of the special commands listed in 16043 * `implicitCommands`. 16044 */ 16045 16046 16047 isDefined(name) { 16048 return this.macros.has(name) || functions.hasOwnProperty(name) || symbols.math.hasOwnProperty(name) || symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name); 16049 } 16050 /** 16051 * Determine whether a command is expandable. 16052 */ 16053 16054 16055 isExpandable(name) { 16056 var macro = this.macros.get(name); 16057 return macro != null ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable : functions.hasOwnProperty(name) && !functions[name].primitive; 16058 } 16059 16060 } 16061 16062 /* eslint no-constant-condition:0 */ 16063 16064 var unicodeAccents = { 16065 "́": { 16066 "text": "\\'", 16067 "math": "\\acute" 16068 }, 16069 "̀": { 16070 "text": "\\`", 16071 "math": "\\grave" 16072 }, 16073 "̈": { 16074 "text": "\\\"", 16075 "math": "\\ddot" 16076 }, 16077 "̃": { 16078 "text": "\\~", 16079 "math": "\\tilde" 16080 }, 16081 "̄": { 16082 "text": "\\=", 16083 "math": "\\bar" 16084 }, 16085 "̆": { 16086 "text": "\\u", 16087 "math": "\\breve" 16088 }, 16089 "̌": { 16090 "text": "\\v", 16091 "math": "\\check" 16092 }, 16093 "̂": { 16094 "text": "\\^", 16095 "math": "\\hat" 16096 }, 16097 "̇": { 16098 "text": "\\.", 16099 "math": "\\dot" 16100 }, 16101 "̊": { 16102 "text": "\\r", 16103 "math": "\\mathring" 16104 }, 16105 "̋": { 16106 "text": "\\H" 16107 } 16108 }; 16109 var unicodeSymbols = { 16110 "á": "á", 16111 "à": "à", 16112 "ä": "ä", 16113 "ǟ": "ǟ", 16114 "ã": "ã", 16115 "ā": "ā", 16116 "ă": "ă", 16117 "ắ": "ắ", 16118 "ằ": "ằ", 16119 "ẵ": "ẵ", 16120 "ǎ": "ǎ", 16121 "â": "â", 16122 "ấ": "ấ", 16123 "ầ": "ầ", 16124 "ẫ": "ẫ", 16125 "ȧ": "ȧ", 16126 "ǡ": "ǡ", 16127 "å": "å", 16128 "ǻ": "ǻ", 16129 "ḃ": "ḃ", 16130 "ć": "ć", 16131 "č": "č", 16132 "ĉ": "ĉ", 16133 "ċ": "ċ", 16134 "ď": "ď", 16135 "ḋ": "ḋ", 16136 "é": "é", 16137 "è": "è", 16138 "ë": "ë", 16139 "ẽ": "ẽ", 16140 "ē": "ē", 16141 "ḗ": "ḗ", 16142 "ḕ": "ḕ", 16143 "ĕ": "ĕ", 16144 "ě": "ě", 16145 "ê": "ê", 16146 "ế": "ế", 16147 "ề": "ề", 16148 "ễ": "ễ", 16149 "ė": "ė", 16150 "ḟ": "ḟ", 16151 "ǵ": "ǵ", 16152 "ḡ": "ḡ", 16153 "ğ": "ğ", 16154 "ǧ": "ǧ", 16155 "ĝ": "ĝ", 16156 "ġ": "ġ", 16157 "ḧ": "ḧ", 16158 "ȟ": "ȟ", 16159 "ĥ": "ĥ", 16160 "ḣ": "ḣ", 16161 "í": "í", 16162 "ì": "ì", 16163 "ï": "ï", 16164 "ḯ": "ḯ", 16165 "ĩ": "ĩ", 16166 "ī": "ī", 16167 "ĭ": "ĭ", 16168 "ǐ": "ǐ", 16169 "î": "î", 16170 "ǰ": "ǰ", 16171 "ĵ": "ĵ", 16172 "ḱ": "ḱ", 16173 "ǩ": "ǩ", 16174 "ĺ": "ĺ", 16175 "ľ": "ľ", 16176 "ḿ": "ḿ", 16177 "ṁ": "ṁ", 16178 "ń": "ń", 16179 "ǹ": "ǹ", 16180 "ñ": "ñ", 16181 "ň": "ň", 16182 "ṅ": "ṅ", 16183 "ó": "ó", 16184 "ò": "ò", 16185 "ö": "ö", 16186 "ȫ": "ȫ", 16187 "õ": "õ", 16188 "ṍ": "ṍ", 16189 "ṏ": "ṏ", 16190 "ȭ": "ȭ", 16191 "ō": "ō", 16192 "ṓ": "ṓ", 16193 "ṑ": "ṑ", 16194 "ŏ": "ŏ", 16195 "ǒ": "ǒ", 16196 "ô": "ô", 16197 "ố": "ố", 16198 "ồ": "ồ", 16199 "ỗ": "ỗ", 16200 "ȯ": "ȯ", 16201 "ȱ": "ȱ", 16202 "ő": "ő", 16203 "ṕ": "ṕ", 16204 "ṗ": "ṗ", 16205 "ŕ": "ŕ", 16206 "ř": "ř", 16207 "ṙ": "ṙ", 16208 "ś": "ś", 16209 "ṥ": "ṥ", 16210 "š": "š", 16211 "ṧ": "ṧ", 16212 "ŝ": "ŝ", 16213 "ṡ": "ṡ", 16214 "ẗ": "ẗ", 16215 "ť": "ť", 16216 "ṫ": "ṫ", 16217 "ú": "ú", 16218 "ù": "ù", 16219 "ü": "ü", 16220 "ǘ": "ǘ", 16221 "ǜ": "ǜ", 16222 "ǖ": "ǖ", 16223 "ǚ": "ǚ", 16224 "ũ": "ũ", 16225 "ṹ": "ṹ", 16226 "ū": "ū", 16227 "ṻ": "ṻ", 16228 "ŭ": "ŭ", 16229 "ǔ": "ǔ", 16230 "û": "û", 16231 "ů": "ů", 16232 "ű": "ű", 16233 "ṽ": "ṽ", 16234 "ẃ": "ẃ", 16235 "ẁ": "ẁ", 16236 "ẅ": "ẅ", 16237 "ŵ": "ŵ", 16238 "ẇ": "ẇ", 16239 "ẘ": "ẘ", 16240 "ẍ": "ẍ", 16241 "ẋ": "ẋ", 16242 "ý": "ý", 16243 "ỳ": "ỳ", 16244 "ÿ": "ÿ", 16245 "ỹ": "ỹ", 16246 "ȳ": "ȳ", 16247 "ŷ": "ŷ", 16248 "ẏ": "ẏ", 16249 "ẙ": "ẙ", 16250 "ź": "ź", 16251 "ž": "ž", 16252 "ẑ": "ẑ", 16253 "ż": "ż", 16254 "Á": "Á", 16255 "À": "À", 16256 "Ä": "Ä", 16257 "Ǟ": "Ǟ", 16258 "Ã": "Ã", 16259 "Ā": "Ā", 16260 "Ă": "Ă", 16261 "Ắ": "Ắ", 16262 "Ằ": "Ằ", 16263 "Ẵ": "Ẵ", 16264 "Ǎ": "Ǎ", 16265 "Â": "Â", 16266 "Ấ": "Ấ", 16267 "Ầ": "Ầ", 16268 "Ẫ": "Ẫ", 16269 "Ȧ": "Ȧ", 16270 "Ǡ": "Ǡ", 16271 "Å": "Å", 16272 "Ǻ": "Ǻ", 16273 "Ḃ": "Ḃ", 16274 "Ć": "Ć", 16275 "Č": "Č", 16276 "Ĉ": "Ĉ", 16277 "Ċ": "Ċ", 16278 "Ď": "Ď", 16279 "Ḋ": "Ḋ", 16280 "É": "É", 16281 "È": "È", 16282 "Ë": "Ë", 16283 "Ẽ": "Ẽ", 16284 "Ē": "Ē", 16285 "Ḗ": "Ḗ", 16286 "Ḕ": "Ḕ", 16287 "Ĕ": "Ĕ", 16288 "Ě": "Ě", 16289 "Ê": "Ê", 16290 "Ế": "Ế", 16291 "Ề": "Ề", 16292 "Ễ": "Ễ", 16293 "Ė": "Ė", 16294 "Ḟ": "Ḟ", 16295 "Ǵ": "Ǵ", 16296 "Ḡ": "Ḡ", 16297 "Ğ": "Ğ", 16298 "Ǧ": "Ǧ", 16299 "Ĝ": "Ĝ", 16300 "Ġ": "Ġ", 16301 "Ḧ": "Ḧ", 16302 "Ȟ": "Ȟ", 16303 "Ĥ": "Ĥ", 16304 "Ḣ": "Ḣ", 16305 "Í": "Í", 16306 "Ì": "Ì", 16307 "Ï": "Ï", 16308 "Ḯ": "Ḯ", 16309 "Ĩ": "Ĩ", 16310 "Ī": "Ī", 16311 "Ĭ": "Ĭ", 16312 "Ǐ": "Ǐ", 16313 "Î": "Î", 16314 "İ": "İ", 16315 "Ĵ": "Ĵ", 16316 "Ḱ": "Ḱ", 16317 "Ǩ": "Ǩ", 16318 "Ĺ": "Ĺ", 16319 "Ľ": "Ľ", 16320 "Ḿ": "Ḿ", 16321 "Ṁ": "Ṁ", 16322 "Ń": "Ń", 16323 "Ǹ": "Ǹ", 16324 "Ñ": "Ñ", 16325 "Ň": "Ň", 16326 "Ṅ": "Ṅ", 16327 "Ó": "Ó", 16328 "Ò": "Ò", 16329 "Ö": "Ö", 16330 "Ȫ": "Ȫ", 16331 "Õ": "Õ", 16332 "Ṍ": "Ṍ", 16333 "Ṏ": "Ṏ", 16334 "Ȭ": "Ȭ", 16335 "Ō": "Ō", 16336 "Ṓ": "Ṓ", 16337 "Ṑ": "Ṑ", 16338 "Ŏ": "Ŏ", 16339 "Ǒ": "Ǒ", 16340 "Ô": "Ô", 16341 "Ố": "Ố", 16342 "Ồ": "Ồ", 16343 "Ỗ": "Ỗ", 16344 "Ȯ": "Ȯ", 16345 "Ȱ": "Ȱ", 16346 "Ő": "Ő", 16347 "Ṕ": "Ṕ", 16348 "Ṗ": "Ṗ", 16349 "Ŕ": "Ŕ", 16350 "Ř": "Ř", 16351 "Ṙ": "Ṙ", 16352 "Ś": "Ś", 16353 "Ṥ": "Ṥ", 16354 "Š": "Š", 16355 "Ṧ": "Ṧ", 16356 "Ŝ": "Ŝ", 16357 "Ṡ": "Ṡ", 16358 "Ť": "Ť", 16359 "Ṫ": "Ṫ", 16360 "Ú": "Ú", 16361 "Ù": "Ù", 16362 "Ü": "Ü", 16363 "Ǘ": "Ǘ", 16364 "Ǜ": "Ǜ", 16365 "Ǖ": "Ǖ", 16366 "Ǚ": "Ǚ", 16367 "Ũ": "Ũ", 16368 "Ṹ": "Ṹ", 16369 "Ū": "Ū", 16370 "Ṻ": "Ṻ", 16371 "Ŭ": "Ŭ", 16372 "Ǔ": "Ǔ", 16373 "Û": "Û", 16374 "Ů": "Ů", 16375 "Ű": "Ű", 16376 "Ṽ": "Ṽ", 16377 "Ẃ": "Ẃ", 16378 "Ẁ": "Ẁ", 16379 "Ẅ": "Ẅ", 16380 "Ŵ": "Ŵ", 16381 "Ẇ": "Ẇ", 16382 "Ẍ": "Ẍ", 16383 "Ẋ": "Ẋ", 16384 "Ý": "Ý", 16385 "Ỳ": "Ỳ", 16386 "Ÿ": "Ÿ", 16387 "Ỹ": "Ỹ", 16388 "Ȳ": "Ȳ", 16389 "Ŷ": "Ŷ", 16390 "Ẏ": "Ẏ", 16391 "Ź": "Ź", 16392 "Ž": "Ž", 16393 "Ẑ": "Ẑ", 16394 "Ż": "Ż", 16395 "ά": "ά", 16396 "ὰ": "ὰ", 16397 "ᾱ": "ᾱ", 16398 "ᾰ": "ᾰ", 16399 "έ": "έ", 16400 "ὲ": "ὲ", 16401 "ή": "ή", 16402 "ὴ": "ὴ", 16403 "ί": "ί", 16404 "ὶ": "ὶ", 16405 "ϊ": "ϊ", 16406 "ΐ": "ΐ", 16407 "ῒ": "ῒ", 16408 "ῑ": "ῑ", 16409 "ῐ": "ῐ", 16410 "ό": "ό", 16411 "ὸ": "ὸ", 16412 "ύ": "ύ", 16413 "ὺ": "ὺ", 16414 "ϋ": "ϋ", 16415 "ΰ": "ΰ", 16416 "ῢ": "ῢ", 16417 "ῡ": "ῡ", 16418 "ῠ": "ῠ", 16419 "ώ": "ώ", 16420 "ὼ": "ὼ", 16421 "Ύ": "Ύ", 16422 "Ὺ": "Ὺ", 16423 "Ϋ": "Ϋ", 16424 "Ῡ": "Ῡ", 16425 "Ῠ": "Ῠ", 16426 "Ώ": "Ώ", 16427 "Ὼ": "Ὼ" 16428 }; 16429 16430 /** 16431 * This file contains the parser used to parse out a TeX expression from the 16432 * input. Since TeX isn't context-free, standard parsers don't work particularly 16433 * well. 16434 * 16435 * The strategy of this parser is as such: 16436 * 16437 * The main functions (the `.parse...` ones) take a position in the current 16438 * parse string to parse tokens from. The lexer (found in Lexer.js, stored at 16439 * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When 16440 * individual tokens are needed at a position, the lexer is called to pull out a 16441 * token, which is then used. 16442 * 16443 * The parser has a property called "mode" indicating the mode that 16444 * the parser is currently in. Currently it has to be one of "math" or 16445 * "text", which denotes whether the current environment is a math-y 16446 * one or a text-y one (e.g. inside \text). Currently, this serves to 16447 * limit the functions which can be used in text mode. 16448 * 16449 * The main functions then return an object which contains the useful data that 16450 * was parsed at its given point, and a new position at the end of the parsed 16451 * data. The main functions can call each other and continue the parsing by 16452 * using the returned position as a new starting point. 16453 * 16454 * There are also extra `.handle...` functions, which pull out some reused 16455 * functionality into self-contained functions. 16456 * 16457 * The functions return ParseNodes. 16458 */ 16459 class Parser { 16460 constructor(input, settings) { 16461 this.mode = void 0; 16462 this.gullet = void 0; 16463 this.settings = void 0; 16464 this.leftrightDepth = void 0; 16465 this.nextToken = void 0; 16466 // Start in math mode 16467 this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a 16468 // new lexer (mouth) for this parser (stomach, in the language of TeX) 16469 16470 this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing 16471 16472 this.settings = settings; // Count leftright depth (for \middle errors) 16473 16474 this.leftrightDepth = 0; 16475 } 16476 /** 16477 * Checks a result to make sure it has the right type, and throws an 16478 * appropriate error otherwise. 16479 */ 16480 16481 16482 expect(text, consume) { 16483 if (consume === void 0) { 16484 consume = true; 16485 } 16486 16487 if (this.fetch().text !== text) { 16488 throw new ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch()); 16489 } 16490 16491 if (consume) { 16492 this.consume(); 16493 } 16494 } 16495 /** 16496 * Discards the current lookahead token, considering it consumed. 16497 */ 16498 16499 16500 consume() { 16501 this.nextToken = null; 16502 } 16503 /** 16504 * Return the current lookahead token, or if there isn't one (at the 16505 * beginning, or if the previous lookahead token was consume()d), 16506 * fetch the next token as the new lookahead token and return it. 16507 */ 16508 16509 16510 fetch() { 16511 if (this.nextToken == null) { 16512 this.nextToken = this.gullet.expandNextToken(); 16513 } 16514 16515 return this.nextToken; 16516 } 16517 /** 16518 * Switches between "text" and "math" modes. 16519 */ 16520 16521 16522 switchMode(newMode) { 16523 this.mode = newMode; 16524 this.gullet.switchMode(newMode); 16525 } 16526 /** 16527 * Main parsing function, which parses an entire input. 16528 */ 16529 16530 16531 parse() { 16532 if (!this.settings.globalGroup) { 16533 // Create a group namespace for the math expression. 16534 // (LaTeX creates a new group for every $...$, $$...$$, \[...\].) 16535 this.gullet.beginGroup(); 16536 } // Use old \color behavior (same as LaTeX's \textcolor) if requested. 16537 // We do this within the group for the math expression, so it doesn't 16538 // pollute settings.macros. 16539 16540 16541 if (this.settings.colorIsTextColor) { 16542 this.gullet.macros.set("\\color", "\\textcolor"); 16543 } // Try to parse the input 16544 16545 16546 var parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end 16547 16548 this.expect("EOF"); // End the group namespace for the expression 16549 16550 if (!this.settings.globalGroup) { 16551 this.gullet.endGroup(); 16552 } 16553 16554 return parse; 16555 } 16556 16557 /** 16558 * Parses an "expression", which is a list of atoms. 16559 * 16560 * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This 16561 * happens when functions have higher precendence han infix 16562 * nodes in implicit parses. 16563 * 16564 * `breakOnTokenText`: The text of the token that the expression should end 16565 * with, or `null` if something else should end the 16566 * expression. 16567 */ 16568 parseExpression(breakOnInfix, breakOnTokenText) { 16569 var body = []; // Keep adding atoms to the body until we can't parse any more atoms (either 16570 // we reached the end, a }, or a \right) 16571 16572 while (true) { 16573 // Ignore spaces in math mode 16574 if (this.mode === "math") { 16575 this.consumeSpaces(); 16576 } 16577 16578 var lex = this.fetch(); 16579 16580 if (Parser.endOfExpression.indexOf(lex.text) !== -1) { 16581 break; 16582 } 16583 16584 if (breakOnTokenText && lex.text === breakOnTokenText) { 16585 break; 16586 } 16587 16588 if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { 16589 break; 16590 } 16591 16592 var atom = this.parseAtom(breakOnTokenText); 16593 16594 if (!atom) { 16595 break; 16596 } else if (atom.type === "internal") { 16597 continue; 16598 } 16599 16600 body.push(atom); 16601 } 16602 16603 if (this.mode === "text") { 16604 this.formLigatures(body); 16605 } 16606 16607 return this.handleInfixNodes(body); 16608 } 16609 /** 16610 * Rewrites infix operators such as \over with corresponding commands such 16611 * as \frac. 16612 * 16613 * There can only be one infix operator per group. If there's more than one 16614 * then the expression is ambiguous. This can be resolved by adding {}. 16615 */ 16616 16617 16618 handleInfixNodes(body) { 16619 var overIndex = -1; 16620 var funcName; 16621 16622 for (var i = 0; i < body.length; i++) { 16623 if (body[i].type === "infix") { 16624 if (overIndex !== -1) { 16625 throw new ParseError("only one infix operator per group", body[i].token); 16626 } 16627 16628 overIndex = i; 16629 funcName = body[i].replaceWith; 16630 } 16631 } 16632 16633 if (overIndex !== -1 && funcName) { 16634 var numerNode; 16635 var denomNode; 16636 var numerBody = body.slice(0, overIndex); 16637 var denomBody = body.slice(overIndex + 1); 16638 16639 if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { 16640 numerNode = numerBody[0]; 16641 } else { 16642 numerNode = { 16643 type: "ordgroup", 16644 mode: this.mode, 16645 body: numerBody 16646 }; 16647 } 16648 16649 if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { 16650 denomNode = denomBody[0]; 16651 } else { 16652 denomNode = { 16653 type: "ordgroup", 16654 mode: this.mode, 16655 body: denomBody 16656 }; 16657 } 16658 16659 var node; 16660 16661 if (funcName === "\\\\abovefrac") { 16662 node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); 16663 } else { 16664 node = this.callFunction(funcName, [numerNode, denomNode], []); 16665 } 16666 16667 return [node]; 16668 } else { 16669 return body; 16670 } 16671 } 16672 /** 16673 * Handle a subscript or superscript with nice errors. 16674 */ 16675 16676 16677 handleSupSubscript(name) { 16678 var symbolToken = this.fetch(); 16679 var symbol = symbolToken.text; 16680 this.consume(); 16681 this.consumeSpaces(); // ignore spaces before sup/subscript argument 16682 16683 var group = this.parseGroup(name); 16684 16685 if (!group) { 16686 throw new ParseError("Expected group after '" + symbol + "'", symbolToken); 16687 } 16688 16689 return group; 16690 } 16691 /** 16692 * Converts the textual input of an unsupported command into a text node 16693 * contained within a color node whose color is determined by errorColor 16694 */ 16695 16696 16697 formatUnsupportedCmd(text) { 16698 var textordArray = []; 16699 16700 for (var i = 0; i < text.length; i++) { 16701 textordArray.push({ 16702 type: "textord", 16703 mode: "text", 16704 text: text[i] 16705 }); 16706 } 16707 16708 var textNode = { 16709 type: "text", 16710 mode: this.mode, 16711 body: textordArray 16712 }; 16713 var colorNode = { 16714 type: "color", 16715 mode: this.mode, 16716 color: this.settings.errorColor, 16717 body: [textNode] 16718 }; 16719 return colorNode; 16720 } 16721 /** 16722 * Parses a group with optional super/subscripts. 16723 */ 16724 16725 16726 parseAtom(breakOnTokenText) { 16727 // The body of an atom is an implicit group, so that things like 16728 // \left(x\right)^2 work correctly. 16729 var base = this.parseGroup("atom", breakOnTokenText); // In text mode, we don't have superscripts or subscripts 16730 16731 if (this.mode === "text") { 16732 return base; 16733 } // Note that base may be empty (i.e. null) at this point. 16734 16735 16736 var superscript; 16737 var subscript; 16738 16739 while (true) { 16740 // Guaranteed in math mode, so eat any spaces first. 16741 this.consumeSpaces(); // Lex the first token 16742 16743 var lex = this.fetch(); 16744 16745 if (lex.text === "\\limits" || lex.text === "\\nolimits") { 16746 // We got a limit control 16747 if (base && base.type === "op") { 16748 var limits = lex.text === "\\limits"; 16749 base.limits = limits; 16750 base.alwaysHandleSupSub = true; 16751 } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub) { 16752 var _limits = lex.text === "\\limits"; 16753 16754 base.limits = _limits; 16755 } else { 16756 throw new ParseError("Limit controls must follow a math operator", lex); 16757 } 16758 16759 this.consume(); 16760 } else if (lex.text === "^") { 16761 // We got a superscript start 16762 if (superscript) { 16763 throw new ParseError("Double superscript", lex); 16764 } 16765 16766 superscript = this.handleSupSubscript("superscript"); 16767 } else if (lex.text === "_") { 16768 // We got a subscript start 16769 if (subscript) { 16770 throw new ParseError("Double subscript", lex); 16771 } 16772 16773 subscript = this.handleSupSubscript("subscript"); 16774 } else if (lex.text === "'") { 16775 // We got a prime 16776 if (superscript) { 16777 throw new ParseError("Double superscript", lex); 16778 } 16779 16780 var prime = { 16781 type: "textord", 16782 mode: this.mode, 16783 text: "\\prime" 16784 }; // Many primes can be grouped together, so we handle this here 16785 16786 var primes = [prime]; 16787 this.consume(); // Keep lexing tokens until we get something that's not a prime 16788 16789 while (this.fetch().text === "'") { 16790 // For each one, add another prime to the list 16791 primes.push(prime); 16792 this.consume(); 16793 } // If there's a superscript following the primes, combine that 16794 // superscript in with the primes. 16795 16796 16797 if (this.fetch().text === "^") { 16798 primes.push(this.handleSupSubscript("superscript")); 16799 } // Put everything into an ordgroup as the superscript 16800 16801 16802 superscript = { 16803 type: "ordgroup", 16804 mode: this.mode, 16805 body: primes 16806 }; 16807 } else { 16808 // If it wasn't ^, _, or ', stop parsing super/subscripts 16809 break; 16810 } 16811 } // Base must be set if superscript or subscript are set per logic above, 16812 // but need to check here for type check to pass. 16813 16814 16815 if (superscript || subscript) { 16816 // If we got either a superscript or subscript, create a supsub 16817 return { 16818 type: "supsub", 16819 mode: this.mode, 16820 base: base, 16821 sup: superscript, 16822 sub: subscript 16823 }; 16824 } else { 16825 // Otherwise return the original body 16826 return base; 16827 } 16828 } 16829 /** 16830 * Parses an entire function, including its base and all of its arguments. 16831 */ 16832 16833 16834 parseFunction(breakOnTokenText, name) { 16835 var token = this.fetch(); 16836 var func = token.text; 16837 var funcData = functions[func]; 16838 16839 if (!funcData) { 16840 return null; 16841 } 16842 16843 this.consume(); // consume command token 16844 16845 if (name && name !== "atom" && !funcData.allowedInArgument) { 16846 throw new ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token); 16847 } else if (this.mode === "text" && !funcData.allowedInText) { 16848 throw new ParseError("Can't use function '" + func + "' in text mode", token); 16849 } else if (this.mode === "math" && funcData.allowedInMath === false) { 16850 throw new ParseError("Can't use function '" + func + "' in math mode", token); 16851 } 16852 16853 var { 16854 args, 16855 optArgs 16856 } = this.parseArguments(func, funcData); 16857 return this.callFunction(func, args, optArgs, token, breakOnTokenText); 16858 } 16859 /** 16860 * Call a function handler with a suitable context and arguments. 16861 */ 16862 16863 16864 callFunction(name, args, optArgs, token, breakOnTokenText) { 16865 var context = { 16866 funcName: name, 16867 parser: this, 16868 token, 16869 breakOnTokenText 16870 }; 16871 var func = functions[name]; 16872 16873 if (func && func.handler) { 16874 return func.handler(context, args, optArgs); 16875 } else { 16876 throw new ParseError("No function handler for " + name); 16877 } 16878 } 16879 /** 16880 * Parses the arguments of a function or environment 16881 */ 16882 16883 16884 parseArguments(func, // Should look like "\name" or "\begin{name}". 16885 funcData) { 16886 var totalArgs = funcData.numArgs + funcData.numOptionalArgs; 16887 16888 if (totalArgs === 0) { 16889 return { 16890 args: [], 16891 optArgs: [] 16892 }; 16893 } 16894 16895 var args = []; 16896 var optArgs = []; 16897 16898 for (var i = 0; i < totalArgs; i++) { 16899 var argType = funcData.argTypes && funcData.argTypes[i]; 16900 var isOptional = i < funcData.numOptionalArgs; 16901 16902 if (funcData.primitive && argType == null || // \sqrt expands into primitive if optional argument doesn't exist 16903 funcData.type === "sqrt" && i === 1 && optArgs[0] == null) { 16904 argType = "primitive"; 16905 } 16906 16907 var arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional); 16908 16909 if (isOptional) { 16910 optArgs.push(arg); 16911 } else if (arg != null) { 16912 args.push(arg); 16913 } else { 16914 // should be unreachable 16915 throw new ParseError("Null argument, please report this as a bug"); 16916 } 16917 } 16918 16919 return { 16920 args, 16921 optArgs 16922 }; 16923 } 16924 /** 16925 * Parses a group when the mode is changing. 16926 */ 16927 16928 16929 parseGroupOfType(name, type, optional) { 16930 switch (type) { 16931 case "color": 16932 return this.parseColorGroup(optional); 16933 16934 case "size": 16935 return this.parseSizeGroup(optional); 16936 16937 case "url": 16938 return this.parseUrlGroup(optional); 16939 16940 case "math": 16941 case "text": 16942 return this.parseArgumentGroup(optional, type); 16943 16944 case "hbox": 16945 { 16946 // hbox argument type wraps the argument in the equivalent of 16947 // \hbox, which is like \text but switching to \textstyle size. 16948 var group = this.parseArgumentGroup(optional, "text"); 16949 return group != null ? { 16950 type: "styling", 16951 mode: group.mode, 16952 body: [group], 16953 style: "text" // simulate \textstyle 16954 16955 } : null; 16956 } 16957 16958 case "raw": 16959 { 16960 var token = this.parseStringGroup("raw", optional); 16961 return token != null ? { 16962 type: "raw", 16963 mode: "text", 16964 string: token.text 16965 } : null; 16966 } 16967 16968 case "primitive": 16969 { 16970 if (optional) { 16971 throw new ParseError("A primitive argument cannot be optional"); 16972 } 16973 16974 var _group = this.parseGroup(name); 16975 16976 if (_group == null) { 16977 throw new ParseError("Expected group as " + name, this.fetch()); 16978 } 16979 16980 return _group; 16981 } 16982 16983 case "original": 16984 case null: 16985 case undefined: 16986 return this.parseArgumentGroup(optional); 16987 16988 default: 16989 throw new ParseError("Unknown group type as " + name, this.fetch()); 16990 } 16991 } 16992 /** 16993 * Discard any space tokens, fetching the next non-space token. 16994 */ 16995 16996 16997 consumeSpaces() { 16998 while (this.fetch().text === " ") { 16999 this.consume(); 17000 } 17001 } 17002 /** 17003 * Parses a group, essentially returning the string formed by the 17004 * brace-enclosed tokens plus some position information. 17005 */ 17006 17007 17008 parseStringGroup(modeName, // Used to describe the mode in error messages. 17009 optional) { 17010 var argToken = this.gullet.scanArgument(optional); 17011 17012 if (argToken == null) { 17013 return null; 17014 } 17015 17016 var str = ""; 17017 var nextToken; 17018 17019 while ((nextToken = this.fetch()).text !== "EOF") { 17020 str += nextToken.text; 17021 this.consume(); 17022 } 17023 17024 this.consume(); // consume the end of the argument 17025 17026 argToken.text = str; 17027 return argToken; 17028 } 17029 /** 17030 * Parses a regex-delimited group: the largest sequence of tokens 17031 * whose concatenated strings match `regex`. Returns the string 17032 * formed by the tokens plus some position information. 17033 */ 17034 17035 17036 parseRegexGroup(regex, modeName) { 17037 var firstToken = this.fetch(); 17038 var lastToken = firstToken; 17039 var str = ""; 17040 var nextToken; 17041 17042 while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { 17043 lastToken = nextToken; 17044 str += lastToken.text; 17045 this.consume(); 17046 } 17047 17048 if (str === "") { 17049 throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); 17050 } 17051 17052 return firstToken.range(lastToken, str); 17053 } 17054 /** 17055 * Parses a color description. 17056 */ 17057 17058 17059 parseColorGroup(optional) { 17060 var res = this.parseStringGroup("color", optional); 17061 17062 if (res == null) { 17063 return null; 17064 } 17065 17066 var match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text); 17067 17068 if (!match) { 17069 throw new ParseError("Invalid color: '" + res.text + "'", res); 17070 } 17071 17072 var color = match[0]; 17073 17074 if (/^[0-9a-f]{6}$/i.test(color)) { 17075 // We allow a 6-digit HTML color spec without a leading "#". 17076 // This follows the xcolor package's HTML color model. 17077 // Predefined color names are all missed by this RegEx pattern. 17078 color = "#" + color; 17079 } 17080 17081 return { 17082 type: "color-token", 17083 mode: this.mode, 17084 color 17085 }; 17086 } 17087 /** 17088 * Parses a size specification, consisting of magnitude and unit. 17089 */ 17090 17091 17092 parseSizeGroup(optional) { 17093 var res; 17094 var isBlank = false; // don't expand before parseStringGroup 17095 17096 this.gullet.consumeSpaces(); 17097 17098 if (!optional && this.gullet.future().text !== "{") { 17099 res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); 17100 } else { 17101 res = this.parseStringGroup("size", optional); 17102 } 17103 17104 if (!res) { 17105 return null; 17106 } 17107 17108 if (!optional && res.text.length === 0) { 17109 // Because we've tested for what is !optional, this block won't 17110 // affect \kern, \hspace, etc. It will capture the mandatory arguments 17111 // to \genfrac and \above. 17112 res.text = "0pt"; // Enable \above{} 17113 17114 isBlank = true; // This is here specifically for \genfrac 17115 } 17116 17117 var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); 17118 17119 if (!match) { 17120 throw new ParseError("Invalid size: '" + res.text + "'", res); 17121 } 17122 17123 var data = { 17124 number: +(match[1] + match[2]), 17125 // sign + magnitude, cast to number 17126 unit: match[3] 17127 }; 17128 17129 if (!validUnit(data)) { 17130 throw new ParseError("Invalid unit: '" + data.unit + "'", res); 17131 } 17132 17133 return { 17134 type: "size", 17135 mode: this.mode, 17136 value: data, 17137 isBlank 17138 }; 17139 } 17140 /** 17141 * Parses an URL, checking escaped letters and allowed protocols, 17142 * and setting the catcode of % as an active character (as in \hyperref). 17143 */ 17144 17145 17146 parseUrlGroup(optional) { 17147 this.gullet.lexer.setCatcode("%", 13); // active character 17148 17149 var res = this.parseStringGroup("url", optional); 17150 this.gullet.lexer.setCatcode("%", 14); // comment character 17151 17152 if (res == null) { 17153 return null; 17154 } // hyperref package allows backslashes alone in href, but doesn't 17155 // generate valid links in such cases; we interpret this as 17156 // "undefined" behaviour, and keep them as-is. Some browser will 17157 // replace backslashes with forward slashes. 17158 17159 17160 var url = res.text.replace(/\\([#$%&~_^{}])/g, '$1'); 17161 return { 17162 type: "url", 17163 mode: this.mode, 17164 url 17165 }; 17166 } 17167 /** 17168 * Parses an argument with the mode specified. 17169 */ 17170 17171 17172 parseArgumentGroup(optional, mode) { 17173 var argToken = this.gullet.scanArgument(optional); 17174 17175 if (argToken == null) { 17176 return null; 17177 } 17178 17179 var outerMode = this.mode; 17180 17181 if (mode) { 17182 // Switch to specified mode 17183 this.switchMode(mode); 17184 } 17185 17186 this.gullet.beginGroup(); 17187 var expression = this.parseExpression(false, "EOF"); // TODO: find an alternative way to denote the end 17188 17189 this.expect("EOF"); // expect the end of the argument 17190 17191 this.gullet.endGroup(); 17192 var result = { 17193 type: "ordgroup", 17194 mode: this.mode, 17195 loc: argToken.loc, 17196 body: expression 17197 }; 17198 17199 if (mode) { 17200 // Switch mode back 17201 this.switchMode(outerMode); 17202 } 17203 17204 return result; 17205 } 17206 /** 17207 * Parses an ordinary group, which is either a single nucleus (like "x") 17208 * or an expression in braces (like "{x+y}") or an implicit group, a group 17209 * that starts at the current position, and ends right before a higher explicit 17210 * group ends, or at EOF. 17211 */ 17212 17213 17214 parseGroup(name, // For error reporting. 17215 breakOnTokenText) { 17216 var firstToken = this.fetch(); 17217 var text = firstToken.text; 17218 var result; // Try to parse an open brace or \begingroup 17219 17220 if (text === "{" || text === "\\begingroup") { 17221 this.consume(); 17222 var groupEnd = text === "{" ? "}" : "\\endgroup"; 17223 this.gullet.beginGroup(); // If we get a brace, parse an expression 17224 17225 var expression = this.parseExpression(false, groupEnd); 17226 var lastToken = this.fetch(); 17227 this.expect(groupEnd); // Check that we got a matching closing brace 17228 17229 this.gullet.endGroup(); 17230 result = { 17231 type: "ordgroup", 17232 mode: this.mode, 17233 loc: SourceLocation.range(firstToken, lastToken), 17234 body: expression, 17235 // A group formed by \begingroup...\endgroup is a semi-simple group 17236 // which doesn't affect spacing in math mode, i.e., is transparent. 17237 // https://tex.stackexchange.com/questions/1930/when-should-one- 17238 // use-begingroup-instead-of-bgroup 17239 semisimple: text === "\\begingroup" || undefined 17240 }; 17241 } else { 17242 // If there exists a function with this name, parse the function. 17243 // Otherwise, just return a nucleus 17244 result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); 17245 17246 if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) { 17247 if (this.settings.throwOnError) { 17248 throw new ParseError("Undefined control sequence: " + text, firstToken); 17249 } 17250 17251 result = this.formatUnsupportedCmd(text); 17252 this.consume(); 17253 } 17254 } 17255 17256 return result; 17257 } 17258 /** 17259 * Form ligature-like combinations of characters for text mode. 17260 * This includes inputs like "--", "---", "``" and "''". 17261 * The result will simply replace multiple textord nodes with a single 17262 * character in each value by a single textord node having multiple 17263 * characters in its value. The representation is still ASCII source. 17264 * The group will be modified in place. 17265 */ 17266 17267 17268 formLigatures(group) { 17269 var n = group.length - 1; 17270 17271 for (var i = 0; i < n; ++i) { 17272 var a = group[i]; // $FlowFixMe: Not every node type has a `text` property. 17273 17274 var v = a.text; 17275 17276 if (v === "-" && group[i + 1].text === "-") { 17277 if (i + 1 < n && group[i + 2].text === "-") { 17278 group.splice(i, 3, { 17279 type: "textord", 17280 mode: "text", 17281 loc: SourceLocation.range(a, group[i + 2]), 17282 text: "---" 17283 }); 17284 n -= 2; 17285 } else { 17286 group.splice(i, 2, { 17287 type: "textord", 17288 mode: "text", 17289 loc: SourceLocation.range(a, group[i + 1]), 17290 text: "--" 17291 }); 17292 n -= 1; 17293 } 17294 } 17295 17296 if ((v === "'" || v === "`") && group[i + 1].text === v) { 17297 group.splice(i, 2, { 17298 type: "textord", 17299 mode: "text", 17300 loc: SourceLocation.range(a, group[i + 1]), 17301 text: v + v 17302 }); 17303 n -= 1; 17304 } 17305 } 17306 } 17307 /** 17308 * Parse a single symbol out of the string. Here, we handle single character 17309 * symbols and special functions like \verb. 17310 */ 17311 17312 17313 parseSymbol() { 17314 var nucleus = this.fetch(); 17315 var text = nucleus.text; 17316 17317 if (/^\\verb[^a-zA-Z]/.test(text)) { 17318 this.consume(); 17319 var arg = text.slice(5); 17320 var star = arg.charAt(0) === "*"; 17321 17322 if (star) { 17323 arg = arg.slice(1); 17324 } // Lexer's tokenRegex is constructed to always have matching 17325 // first/last characters. 17326 17327 17328 if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { 17329 throw new ParseError("\\verb assertion failed --\n please report what input caused this bug"); 17330 } 17331 17332 arg = arg.slice(1, -1); // remove first and last char 17333 17334 return { 17335 type: "verb", 17336 mode: "text", 17337 body: arg, 17338 star 17339 }; 17340 } // At this point, we should have a symbol, possibly with accents. 17341 // First expand any accented base symbol according to unicodeSymbols. 17342 17343 17344 if (unicodeSymbols.hasOwnProperty(text[0]) && !symbols[this.mode][text[0]]) { 17345 // This behavior is not strict (XeTeX-compatible) in math mode. 17346 if (this.settings.strict && this.mode === "math") { 17347 this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus); 17348 } 17349 17350 text = unicodeSymbols[text[0]] + text.substr(1); 17351 } // Strip off any combining characters 17352 17353 17354 var match = combiningDiacriticalMarksEndRegex.exec(text); 17355 17356 if (match) { 17357 text = text.substring(0, match.index); 17358 17359 if (text === 'i') { 17360 text = '\u0131'; // dotless i, in math and text mode 17361 } else if (text === 'j') { 17362 text = '\u0237'; // dotless j, in math and text mode 17363 } 17364 } // Recognize base symbol 17365 17366 17367 var symbol; 17368 17369 if (symbols[this.mode][text]) { 17370 if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) { 17371 this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus); 17372 } 17373 17374 var group = symbols[this.mode][text].group; 17375 var loc = SourceLocation.range(nucleus); 17376 var s; 17377 17378 if (ATOMS.hasOwnProperty(group)) { 17379 // $FlowFixMe 17380 var family = group; 17381 s = { 17382 type: "atom", 17383 mode: this.mode, 17384 family, 17385 loc, 17386 text 17387 }; 17388 } else { 17389 // $FlowFixMe 17390 s = { 17391 type: group, 17392 mode: this.mode, 17393 loc, 17394 text 17395 }; 17396 } // $FlowFixMe 17397 17398 17399 symbol = s; 17400 } else if (text.charCodeAt(0) >= 0x80) { 17401 // no symbol for e.g. ^ 17402 if (this.settings.strict) { 17403 if (!supportedCodepoint(text.charCodeAt(0))) { 17404 this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus); 17405 } else if (this.mode === "math") { 17406 this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus); 17407 } 17408 } // All nonmathematical Unicode characters are rendered as if they 17409 // are in text mode (wrapped in \text) because that's what it 17410 // takes to render them in LaTeX. Setting `mode: this.mode` is 17411 // another natural choice (the user requested math mode), but 17412 // this makes it more difficult for getCharacterMetrics() to 17413 // distinguish Unicode characters without metrics and those for 17414 // which we want to simulate the letter M. 17415 17416 17417 symbol = { 17418 type: "textord", 17419 mode: "text", 17420 loc: SourceLocation.range(nucleus), 17421 text 17422 }; 17423 } else { 17424 return null; // EOF, ^, _, {, }, etc. 17425 } 17426 17427 this.consume(); // Transform combining characters into accents 17428 17429 if (match) { 17430 for (var i = 0; i < match[0].length; i++) { 17431 var accent = match[0][i]; 17432 17433 if (!unicodeAccents[accent]) { 17434 throw new ParseError("Unknown accent ' " + accent + "'", nucleus); 17435 } 17436 17437 var command = unicodeAccents[accent][this.mode]; 17438 17439 if (!command) { 17440 throw new ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus); 17441 } 17442 17443 symbol = { 17444 type: "accent", 17445 mode: this.mode, 17446 loc: SourceLocation.range(nucleus), 17447 label: command, 17448 isStretchy: false, 17449 isShifty: true, 17450 // $FlowFixMe 17451 base: symbol 17452 }; 17453 } 17454 } // $FlowFixMe 17455 17456 17457 return symbol; 17458 } 17459 17460 } 17461 Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"]; 17462 17463 /** 17464 * Provides a single function for parsing an expression using a Parser 17465 * TODO(emily): Remove this 17466 */ 17467 17468 /** 17469 * Parses an expression using a Parser, then returns the parsed result. 17470 */ 17471 var parseTree = function parseTree(toParse, settings) { 17472 if (!(typeof toParse === 'string' || toParse instanceof String)) { 17473 throw new TypeError('KaTeX can only parse string typed expression'); 17474 } 17475 17476 var parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors 17477 17478 delete parser.gullet.macros.current["\\df@tag"]; 17479 var tree = parser.parse(); // Prevent a color definition from persisting between calls to katex.render(). 17480 17481 delete parser.gullet.macros.current["\\current@color"]; 17482 delete parser.gullet.macros.current["\\color"]; // If the input used \tag, it will set the \df@tag macro to the tag. 17483 // In this case, we separately parse the tag and wrap the tree. 17484 17485 if (parser.gullet.macros.get("\\df@tag")) { 17486 if (!settings.displayMode) { 17487 throw new ParseError("\\tag works only in display equations"); 17488 } 17489 17490 parser.gullet.feed("\\df@tag"); 17491 tree = [{ 17492 type: "tag", 17493 mode: "text", 17494 body: tree, 17495 tag: parser.parse() 17496 }]; 17497 } 17498 17499 return tree; 17500 }; 17501 17502 /* eslint no-console:0 */ 17503 17504 /** 17505 * Parse and build an expression, and place that expression in the DOM node 17506 * given. 17507 */ 17508 var render = function render(expression, baseNode, options) { 17509 baseNode.textContent = ""; 17510 var node = renderToDomTree(expression, options).toNode(); 17511 baseNode.appendChild(node); 17512 }; // KaTeX's styles don't work properly in quirks mode. Print out an error, and 17513 // disable rendering. 17514 17515 17516 if (typeof document !== "undefined") { 17517 if (document.compatMode !== "CSS1Compat") { 17518 typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype."); 17519 17520 render = function render() { 17521 throw new ParseError("KaTeX doesn't work in quirks mode."); 17522 }; 17523 } 17524 } 17525 /** 17526 * Parse and build an expression, and return the markup for that. 17527 */ 17528 17529 17530 var renderToString = function renderToString(expression, options) { 17531 var markup = renderToDomTree(expression, options).toMarkup(); 17532 return markup; 17533 }; 17534 /** 17535 * Parse an expression and return the parse tree. 17536 */ 17537 17538 17539 var generateParseTree = function generateParseTree(expression, options) { 17540 var settings = new Settings(options); 17541 return parseTree(expression, settings); 17542 }; 17543 /** 17544 * If the given error is a KaTeX ParseError and options.throwOnError is false, 17545 * renders the invalid LaTeX as a span with hover title giving the KaTeX 17546 * error message. Otherwise, simply throws the error. 17547 */ 17548 17549 17550 var renderError = function renderError(error, expression, options) { 17551 if (options.throwOnError || !(error instanceof ParseError)) { 17552 throw error; 17553 } 17554 17555 var node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]); 17556 node.setAttribute("title", error.toString()); 17557 node.setAttribute("style", "color:" + options.errorColor); 17558 return node; 17559 }; 17560 /** 17561 * Generates and returns the katex build tree. This is used for advanced 17562 * use cases (like rendering to custom output). 17563 */ 17564 17565 17566 var renderToDomTree = function renderToDomTree(expression, options) { 17567 var settings = new Settings(options); 17568 17569 try { 17570 var tree = parseTree(expression, settings); 17571 return buildTree(tree, expression, settings); 17572 } catch (error) { 17573 return renderError(error, expression, settings); 17574 } 17575 }; 17576 /** 17577 * Generates and returns the katex build tree, with just HTML (no MathML). 17578 * This is used for advanced use cases (like rendering to custom output). 17579 */ 17580 17581 17582 var renderToHTMLTree = function renderToHTMLTree(expression, options) { 17583 var settings = new Settings(options); 17584 17585 try { 17586 var tree = parseTree(expression, settings); 17587 return buildHTMLTree(tree, expression, settings); 17588 } catch (error) { 17589 return renderError(error, expression, settings); 17590 } 17591 }; 17592 17593 var katex = { 17594 /** 17595 * Current KaTeX version 17596 */ 17597 version: "0.13.0", 17598 17599 /** 17600 * Renders the given LaTeX into an HTML+MathML combination, and adds 17601 * it as a child to the specified DOM node. 17602 */ 17603 render, 17604 17605 /** 17606 * Renders the given LaTeX into an HTML+MathML combination string, 17607 * for sending to the client. 17608 */ 17609 renderToString, 17610 17611 /** 17612 * KaTeX error, usually during parsing. 17613 */ 17614 ParseError, 17615 17616 /** 17617 * Parses the given LaTeX into KaTeX's internal parse tree structure, 17618 * without rendering to HTML or MathML. 17619 * 17620 * NOTE: This method is not currently recommended for public use. 17621 * The internal tree representation is unstable and is very likely 17622 * to change. Use at your own risk. 17623 */ 17624 __parse: generateParseTree, 17625 17626 /** 17627 * Renders the given LaTeX into an HTML+MathML internal DOM tree 17628 * representation, without flattening that representation to a string. 17629 * 17630 * NOTE: This method is not currently recommended for public use. 17631 * The internal tree representation is unstable and is very likely 17632 * to change. Use at your own risk. 17633 */ 17634 __renderToDomTree: renderToDomTree, 17635 17636 /** 17637 * Renders the given LaTeX into an HTML internal DOM tree representation, 17638 * without MathML and without flattening that representation to a string. 17639 * 17640 * NOTE: This method is not currently recommended for public use. 17641 * The internal tree representation is unstable and is very likely 17642 * to change. Use at your own risk. 17643 */ 17644 __renderToHTMLTree: renderToHTMLTree, 17645 17646 /** 17647 * extends internal font metrics object with a new object 17648 * each key in the new object represents a font name 17649 */ 17650 __setFontMetrics: setFontMetrics, 17651 17652 /** 17653 * adds a new symbol to builtin symbols table 17654 */ 17655 __defineSymbol: defineSymbol, 17656 17657 /** 17658 * adds a new macro to builtin macro list 17659 */ 17660 __defineMacro: defineMacro, 17661 17662 /** 17663 * Expose the dom tree node types, which can be useful for type checking nodes. 17664 * 17665 * NOTE: This method is not currently recommended for public use. 17666 * The internal tree representation is unstable and is very likely 17667 * to change. Use at your own risk. 17668 */ 17669 __domTree: { 17670 Span, 17671 Anchor, 17672 SymbolNode, 17673 SvgNode, 17674 PathNode, 17675 LineNode 17676 } 17677 }; 17678 17679 export default katex;