1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.katex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 2/* eslint no-console:0 */ 3/** 4 * This is the main entry point for KaTeX. Here, we expose functions for 5 * rendering expressions either to DOM nodes or to markup strings. 6 * 7 * We also expose the ParseError class to check if errors thrown from KaTeX are 8 * errors in the expression, or errors in javascript handling. 9 */ 10 11var ParseError = require("./src/ParseError"); 12var Settings = require("./src/Settings"); 13 14var buildTree = require("./src/buildTree"); 15var parseTree = require("./src/parseTree"); 16var utils = require("./src/utils"); 17 18/** 19 * Parse and build an expression, and place that expression in the DOM node 20 * given. 21 */ 22var render = function(expression, baseNode, options) { 23 utils.clearNode(baseNode); 24 25 var settings = new Settings(options); 26 27 var tree = parseTree(expression, settings); 28 var node = buildTree(tree, expression, settings).toNode(); 29 30 baseNode.appendChild(node); 31}; 32 33// KaTeX's styles don't work properly in quirks mode. Print out an error, and 34// disable rendering. 35if (typeof document !== "undefined") { 36 if (document.compatMode !== "CSS1Compat") { 37 typeof console !== "undefined" && console.warn( 38 "Warning: KaTeX doesn't work in quirks mode. Make sure your " + 39 "website has a suitable doctype."); 40 41 render = function() { 42 throw new ParseError("KaTeX doesn't work in quirks mode."); 43 }; 44 } 45} 46 47/** 48 * Parse and build an expression, and return the markup for that. 49 */ 50var renderToString = function(expression, options) { 51 var settings = new Settings(options); 52 53 var tree = parseTree(expression, settings); 54 return buildTree(tree, expression, settings).toMarkup(); 55}; 56 57/** 58 * Parse an expression and return the parse tree. 59 */ 60var generateParseTree = function(expression, options) { 61 var settings = new Settings(options); 62 return parseTree(expression, settings); 63}; 64 65module.exports = { 66 render: render, 67 renderToString: renderToString, 68 /** 69 * NOTE: This method is not currently recommended for public use. 70 * The internal tree representation is unstable and is very likely 71 * to change. Use at your own risk. 72 */ 73 __parse: generateParseTree, 74 ParseError: ParseError 75}; 76 77},{"./src/ParseError":6,"./src/Settings":8,"./src/buildTree":13,"./src/parseTree":22,"./src/utils":25}],2:[function(require,module,exports){ 78/** @flow */ 79 80"use strict"; 81 82function getRelocatable(re) { 83 // In the future, this could use a WeakMap instead of an expando. 84 if (!re.__matchAtRelocatable) { 85 // Disjunctions are the lowest-precedence operator, so we can make any 86 // pattern match the empty string by appending `|()` to it: 87 // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-patterns 88 var source = re.source + "|()"; 89 90 // We always make the new regex global. 91 var flags = "g" + (re.ignoreCase ? "i" : "") + (re.multiline ? "m" : "") + (re.unicode ? "u" : "") 92 // sticky (/.../y) doesn't make sense in conjunction with our relocation 93 // logic, so we ignore it here. 94 ; 95 96 re.__matchAtRelocatable = new RegExp(source, flags); 97 } 98 return re.__matchAtRelocatable; 99} 100 101function matchAt(re, str, pos) { 102 if (re.global || re.sticky) { 103 throw new Error("matchAt(...): Only non-global regexes are supported"); 104 } 105 var reloc = getRelocatable(re); 106 reloc.lastIndex = pos; 107 var match = reloc.exec(str); 108 // Last capturing group is our sentinel that indicates whether the regex 109 // matched at the given location. 110 if (match[match.length - 1] == null) { 111 // Original regex matched. 112 match.length = match.length - 1; 113 return match; 114 } else { 115 return null; 116 } 117} 118 119module.exports = matchAt; 120},{}],3:[function(require,module,exports){ 121/** 122 * The Lexer class handles tokenizing the input in various ways. Since our 123 * parser expects us to be able to backtrack, the lexer allows lexing from any 124 * given starting point. 125 * 126 * Its main exposed function is the `lex` function, which takes a position to 127 * lex from and a type of token to lex. It defers to the appropriate `_innerLex` 128 * function. 129 * 130 * The various `_innerLex` functions perform the actual lexing of different 131 * kinds. 132 */ 133 134var matchAt = require("match-at"); 135 136var ParseError = require("./ParseError"); 137 138// The main lexer class 139function Lexer(input) { 140 this.input = input; 141 this.pos = 0; 142} 143 144/** 145 * The resulting token returned from `lex`. 146 * 147 * It consists of the token text plus some position information. 148 * The position information is essentially a range in an input string, 149 * but instead of referencing the bare input string, we refer to the lexer. 150 * That way it is possible to attach extra metadata to the input string, 151 * like for example a file name or similar. 152 * 153 * The position information (all three parameters) is optional, 154 * so it is OK to construct synthetic tokens if appropriate. 155 * Not providing available position information may lead to 156 * degraded error reporting, though. 157 * 158 * @param {string} text the text of this token 159 * @param {number=} start the start offset, zero-based inclusive 160 * @param {number=} end the end offset, zero-based exclusive 161 * @param {Lexer=} lexer the lexer which in turn holds the input string 162 */ 163function Token(text, start, end, lexer) { 164 this.text = text; 165 this.start = start; 166 this.end = end; 167 this.lexer = lexer; 168} 169 170/** 171 * Given a pair of tokens (this and endToken), compute a “Token” encompassing 172 * the whole input range enclosed by these two. 173 * 174 * @param {Token} endToken last token of the range, inclusive 175 * @param {string} text the text of the newly constructed token 176 */ 177Token.prototype.range = function(endToken, text) { 178 if (endToken.lexer !== this.lexer) { 179 return new Token(text); // sorry, no position information available 180 } 181 return new Token(text, this.start, endToken.end, this.lexer); 182}; 183 184/* The following tokenRegex 185 * - matches typical whitespace (but not NBSP etc.) using its first group 186 * - does not match any control character \x00-\x1f except whitespace 187 * - does not match a bare backslash 188 * - matches any ASCII character except those just mentioned 189 * - does not match the BMP private use area \uE000-\uF8FF 190 * - does not match bare surrogate code units 191 * - matches any BMP character except for those just described 192 * - matches any valid Unicode surrogate pair 193 * - matches a backslash followed by one or more letters 194 * - matches a backslash followed by any BMP character, including newline 195 * Just because the Lexer matches something doesn't mean it's valid input: 196 * If there is no matching function or symbol definition, the Parser will 197 * still reject the input. 198 */ 199var tokenRegex = new RegExp( 200 "([ \r\n\t]+)|" + // whitespace 201 "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint 202 "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair 203 "|\\\\(?:[a-zA-Z]+|[^\uD800-\uDFFF])" + // function name 204 ")" 205); 206 207/** 208 * This function lexes a single token. 209 */ 210Lexer.prototype.lex = function() { 211 var input = this.input; 212 var pos = this.pos; 213 if (pos === input.length) { 214 return new Token("EOF", pos, pos, this); 215 } 216 var match = matchAt(tokenRegex, input, pos); 217 if (match === null) { 218 throw new ParseError( 219 "Unexpected character: '" + input[pos] + "'", 220 new Token(input[pos], pos, pos + 1, this)); 221 } 222 var text = match[2] || " "; 223 var start = this.pos; 224 this.pos += match[0].length; 225 var end = this.pos; 226 return new Token(text, start, end, this); 227}; 228 229module.exports = Lexer; 230 231},{"./ParseError":6,"match-at":2}],4:[function(require,module,exports){ 232/** 233 * This file contains the “gullet” where macros are expanded 234 * until only non-macro tokens remain. 235 */ 236 237var Lexer = require("./Lexer"); 238 239function MacroExpander(input, macros) { 240 this.lexer = new Lexer(input); 241 this.macros = macros; 242 this.stack = []; // contains tokens in REVERSE order 243 this.discardedWhiteSpace = []; 244} 245 246/** 247 * Recursively expand first token, then return first non-expandable token. 248 */ 249MacroExpander.prototype.nextToken = function() { 250 for (;;) { 251 if (this.stack.length === 0) { 252 this.stack.push(this.lexer.lex()); 253 } 254 var topToken = this.stack.pop(); 255 var name = topToken.text; 256 if (!(name.charAt(0) === "\\" && this.macros.hasOwnProperty(name))) { 257 return topToken; 258 } 259 var expansion = this.macros[name]; 260 if (typeof expansion === "string") { 261 var bodyLexer = new Lexer(expansion); 262 expansion = []; 263 var tok = bodyLexer.lex(); 264 while (tok.text !== "EOF") { 265 expansion.push(tok); 266 tok = bodyLexer.lex(); 267 } 268 expansion.reverse(); // to fit in with stack using push and pop 269 this.macros[name] = expansion; 270 } 271 this.stack = this.stack.concat(expansion); 272 } 273}; 274 275MacroExpander.prototype.get = function(ignoreSpace) { 276 this.discardedWhiteSpace = []; 277 var token = this.nextToken(); 278 if (ignoreSpace) { 279 while (token.text === " ") { 280 this.discardedWhiteSpace.push(token); 281 token = this.nextToken(); 282 } 283 } 284 return token; 285}; 286 287/** 288 * Undo the effect of the preceding call to the get method. 289 * A call to this method MUST be immediately preceded and immediately followed 290 * by a call to get. Only used during mode switching, i.e. after one token 291 * was got in the old mode but should get got again in a new mode 292 * with possibly different whitespace handling. 293 */ 294MacroExpander.prototype.unget = function(token) { 295 this.stack.push(token); 296 while (this.discardedWhiteSpace.length !== 0) { 297 this.stack.push(this.discardedWhiteSpace.pop()); 298 } 299}; 300 301module.exports = MacroExpander; 302 303},{"./Lexer":3}],5:[function(require,module,exports){ 304/** 305 * This file contains information about the options that the Parser carries 306 * around with it while parsing. Data is held in an `Options` object, and when 307 * recursing, a new `Options` object can be created with the `.with*` and 308 * `.reset` functions. 309 */ 310 311/** 312 * This is the main options class. It contains the style, size, color, and font 313 * of the current parse level. It also contains the style and size of the parent 314 * parse level, so size changes can be handled efficiently. 315 * 316 * Each of the `.with*` and `.reset` functions passes its current style and size 317 * as the parentStyle and parentSize of the new options class, so parent 318 * handling is taken care of automatically. 319 */ 320function Options(data) { 321 this.style = data.style; 322 this.color = data.color; 323 this.size = data.size; 324 this.phantom = data.phantom; 325 this.font = data.font; 326 327 if (data.parentStyle === undefined) { 328 this.parentStyle = data.style; 329 } else { 330 this.parentStyle = data.parentStyle; 331 } 332 333 if (data.parentSize === undefined) { 334 this.parentSize = data.size; 335 } else { 336 this.parentSize = data.parentSize; 337 } 338} 339 340/** 341 * Returns a new options object with the same properties as "this". Properties 342 * from "extension" will be copied to the new options object. 343 */ 344Options.prototype.extend = function(extension) { 345 var data = { 346 style: this.style, 347 size: this.size, 348 color: this.color, 349 parentStyle: this.style, 350 parentSize: this.size, 351 phantom: this.phantom, 352 font: this.font 353 }; 354 355 for (var key in extension) { 356 if (extension.hasOwnProperty(key)) { 357 data[key] = extension[key]; 358 } 359 } 360 361 return new Options(data); 362}; 363 364/** 365 * Create a new options object with the given style. 366 */ 367Options.prototype.withStyle = function(style) { 368 return this.extend({ 369 style: style 370 }); 371}; 372 373/** 374 * Create a new options object with the given size. 375 */ 376Options.prototype.withSize = function(size) { 377 return this.extend({ 378 size: size 379 }); 380}; 381 382/** 383 * Create a new options object with the given color. 384 */ 385Options.prototype.withColor = function(color) { 386 return this.extend({ 387 color: color 388 }); 389}; 390 391/** 392 * Create a new options object with "phantom" set to true. 393 */ 394Options.prototype.withPhantom = function() { 395 return this.extend({ 396 phantom: true 397 }); 398}; 399 400/** 401 * Create a new options objects with the give font. 402 */ 403Options.prototype.withFont = function(font) { 404 return this.extend({ 405 font: font || this.font 406 }); 407}; 408 409/** 410 * Create a new options object with the same style, size, and color. This is 411 * used so that parent style and size changes are handled correctly. 412 */ 413Options.prototype.reset = function() { 414 return this.extend({}); 415}; 416 417/** 418 * A map of color names to CSS colors. 419 * TODO(emily): Remove this when we have real macros 420 */ 421var colorMap = { 422 "katex-blue": "#6495ed", 423 "katex-orange": "#ffa500", 424 "katex-pink": "#ff00af", 425 "katex-red": "#df0030", 426 "katex-green": "#28ae7b", 427 "katex-gray": "gray", 428 "katex-purple": "#9d38bd", 429 "katex-blueA": "#ccfaff", 430 "katex-blueB": "#80f6ff", 431 "katex-blueC": "#63d9ea", 432 "katex-blueD": "#11accd", 433 "katex-blueE": "#0c7f99", 434 "katex-tealA": "#94fff5", 435 "katex-tealB": "#26edd5", 436 "katex-tealC": "#01d1c1", 437 "katex-tealD": "#01a995", 438 "katex-tealE": "#208170", 439 "katex-greenA": "#b6ffb0", 440 "katex-greenB": "#8af281", 441 "katex-greenC": "#74cf70", 442 "katex-greenD": "#1fab54", 443 "katex-greenE": "#0d923f", 444 "katex-goldA": "#ffd0a9", 445 "katex-goldB": "#ffbb71", 446 "katex-goldC": "#ff9c39", 447 "katex-goldD": "#e07d10", 448 "katex-goldE": "#a75a05", 449 "katex-redA": "#fca9a9", 450 "katex-redB": "#ff8482", 451 "katex-redC": "#f9685d", 452 "katex-redD": "#e84d39", 453 "katex-redE": "#bc2612", 454 "katex-maroonA": "#ffbde0", 455 "katex-maroonB": "#ff92c6", 456 "katex-maroonC": "#ed5fa6", 457 "katex-maroonD": "#ca337c", 458 "katex-maroonE": "#9e034e", 459 "katex-purpleA": "#ddd7ff", 460 "katex-purpleB": "#c6b9fc", 461 "katex-purpleC": "#aa87ff", 462 "katex-purpleD": "#7854ab", 463 "katex-purpleE": "#543b78", 464 "katex-mintA": "#f5f9e8", 465 "katex-mintB": "#edf2df", 466 "katex-mintC": "#e0e5cc", 467 "katex-grayA": "#f6f7f7", 468 "katex-grayB": "#f0f1f2", 469 "katex-grayC": "#e3e5e6", 470 "katex-grayD": "#d6d8da", 471 "katex-grayE": "#babec2", 472 "katex-grayF": "#888d93", 473 "katex-grayG": "#626569", 474 "katex-grayH": "#3b3e40", 475 "katex-grayI": "#21242c", 476 "katex-kaBlue": "#314453", 477 "katex-kaGreen": "#71B307" 478}; 479 480/** 481 * Gets the CSS color of the current options object, accounting for the 482 * `colorMap`. 483 */ 484Options.prototype.getColor = function() { 485 if (this.phantom) { 486 return "transparent"; 487 } else { 488 return colorMap[this.color] || this.color; 489 } 490}; 491 492module.exports = Options; 493 494},{}],6:[function(require,module,exports){ 495/** 496 * This is the ParseError class, which is the main error thrown by KaTeX 497 * functions when something has gone wrong. This is used to distinguish internal 498 * errors from errors in the expression that the user provided. 499 * 500 * If possible, a caller should provide a Token or ParseNode with information 501 * about where in the source string the problem occurred. 502 * 503 * @param {string} message The error message 504 * @param {(Token|ParseNode)=} token An object providing position information 505 */ 506function ParseError(message, token) { 507 var error = "KaTeX parse error: " + message; 508 var start; 509 var end; 510 511 if (token && token.lexer && token.start <= token.end) { 512 // If we have the input and a position, make the error a bit fancier 513 514 // Get the input 515 var input = token.lexer.input; 516 517 // Prepend some information 518 start = token.start; 519 end = token.end; 520 if (start === input.length) { 521 error += " at end of input: "; 522 } else { 523 error += " at position " + (start + 1) + ": "; 524 } 525 526 // Underline token in question using combining underscores 527 var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); 528 529 // Extract some context from the input and add it to the error 530 var left; 531 if (start > 15) { 532 left = "…" + input.slice(start - 15, start); 533 } else { 534 left = input.slice(0, start); 535 } 536 var right; 537 if (end + 15 < input.length) { 538 right = input.slice(end, end + 15) + "…"; 539 } else { 540 right = input.slice(end); 541 } 542 error += left + underlined + right; 543 } 544 545 // Some hackery to make ParseError a prototype of Error 546 // See http://stackoverflow.com/a/8460753 547 var self = new Error(error); 548 self.name = "ParseError"; 549 self.__proto__ = ParseError.prototype; 550 551 self.position = start; 552 return self; 553} 554 555// More hackery 556ParseError.prototype.__proto__ = Error.prototype; 557 558module.exports = ParseError; 559 560},{}],7:[function(require,module,exports){ 561/* eslint no-constant-condition:0 */ 562var functions = require("./functions"); 563var environments = require("./environments"); 564var MacroExpander = require("./MacroExpander"); 565var symbols = require("./symbols"); 566var utils = require("./utils"); 567var cjkRegex = require("./unicodeRegexes").cjkRegex; 568 569var parseData = require("./parseData"); 570var ParseError = require("./ParseError"); 571 572/** 573 * This file contains the parser used to parse out a TeX expression from the 574 * input. Since TeX isn't context-free, standard parsers don't work particularly 575 * well. 576 * 577 * The strategy of this parser is as such: 578 * 579 * The main functions (the `.parse...` ones) take a position in the current 580 * parse string to parse tokens from. The lexer (found in Lexer.js, stored at 581 * this.lexer) also supports pulling out tokens at arbitrary places. When 582 * individual tokens are needed at a position, the lexer is called to pull out a 583 * token, which is then used. 584 * 585 * The parser has a property called "mode" indicating the mode that 586 * the parser is currently in. Currently it has to be one of "math" or 587 * "text", which denotes whether the current environment is a math-y 588 * one or a text-y one (e.g. inside \text). Currently, this serves to 589 * limit the functions which can be used in text mode. 590 * 591 * The main functions then return an object which contains the useful data that 592 * was parsed at its given point, and a new position at the end of the parsed 593 * data. The main functions can call each other and continue the parsing by 594 * using the returned position as a new starting point. 595 * 596 * There are also extra `.handle...` functions, which pull out some reused 597 * functionality into self-contained functions. 598 * 599 * The earlier functions return ParseNodes. 600 * The later functions (which are called deeper in the parse) sometimes return 601 * ParseFuncOrArgument, which contain a ParseNode as well as some data about 602 * whether the parsed object is a function which is missing some arguments, or a 603 * standalone object which can be used as an argument to another function. 604 */ 605 606/** 607 * Main Parser class 608 */ 609function Parser(input, settings) { 610 // Create a new macro expander (gullet) and (indirectly via that) also a 611 // new lexer (mouth) for this parser (stomach, in the language of TeX) 612 this.gullet = new MacroExpander(input, settings.macros); 613 // Store the settings for use in parsing 614 this.settings = settings; 615 // Count leftright depth (for \middle errors) 616 this.leftrightDepth = 0; 617} 618 619var ParseNode = parseData.ParseNode; 620 621/** 622 * An initial function (without its arguments), or an argument to a function. 623 * The `result` argument should be a ParseNode. 624 */ 625function ParseFuncOrArgument(result, isFunction, token) { 626 this.result = result; 627 // Is this a function (i.e. is it something defined in functions.js)? 628 this.isFunction = isFunction; 629 this.token = token; 630} 631 632/** 633 * Checks a result to make sure it has the right type, and throws an 634 * appropriate error otherwise. 635 * 636 * @param {boolean=} consume whether to consume the expected token, 637 * defaults to true 638 */ 639Parser.prototype.expect = function(text, consume) { 640 if (this.nextToken.text !== text) { 641 throw new ParseError( 642 "Expected '" + text + "', got '" + this.nextToken.text + "'", 643 this.nextToken 644 ); 645 } 646 if (consume !== false) { 647 this.consume(); 648 } 649}; 650 651/** 652 * Considers the current look ahead token as consumed, 653 * and fetches the one after that as the new look ahead. 654 */ 655Parser.prototype.consume = function() { 656 this.nextToken = this.gullet.get(this.mode === "math"); 657}; 658 659Parser.prototype.switchMode = function(newMode) { 660 this.gullet.unget(this.nextToken); 661 this.mode = newMode; 662 this.consume(); 663}; 664 665/** 666 * Main parsing function, which parses an entire input. 667 * 668 * @return {?Array.<ParseNode>} 669 */ 670Parser.prototype.parse = function() { 671 // Try to parse the input 672 this.mode = "math"; 673 this.consume(); 674 var parse = this.parseInput(); 675 return parse; 676}; 677 678/** 679 * Parses an entire input tree. 680 */ 681Parser.prototype.parseInput = function() { 682 // Parse an expression 683 var expression = this.parseExpression(false); 684 // If we succeeded, make sure there's an EOF at the end 685 this.expect("EOF", false); 686 return expression; 687}; 688 689var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"]; 690 691/** 692 * Parses an "expression", which is a list of atoms. 693 * 694 * @param {boolean} breakOnInfix Should the parsing stop when we hit infix 695 * nodes? This happens when functions have higher precendence 696 * than infix nodes in implicit parses. 697 * 698 * @param {?string} breakOnTokenText The text of the token that the expression 699 * should end with, or `null` if something else should end the 700 * expression. 701 * 702 * @return {ParseNode} 703 */ 704Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) { 705 var body = []; 706 // Keep adding atoms to the body until we can't parse any more atoms (either 707 // we reached the end, a }, or a \right) 708 while (true) { 709 var lex = this.nextToken; 710 if (endOfExpression.indexOf(lex.text) !== -1) { 711 break; 712 } 713 if (breakOnTokenText && lex.text === breakOnTokenText) { 714 break; 715 } 716 if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { 717 break; 718 } 719 var atom = this.parseAtom(); 720 if (!atom) { 721 if (!this.settings.throwOnError && lex.text[0] === "\\") { 722 var errorNode = this.handleUnsupportedCmd(); 723 body.push(errorNode); 724 continue; 725 } 726 727 break; 728 } 729 body.push(atom); 730 } 731 return this.handleInfixNodes(body); 732}; 733 734/** 735 * Rewrites infix operators such as \over with corresponding commands such 736 * as \frac. 737 * 738 * There can only be one infix operator per group. If there's more than one 739 * then the expression is ambiguous. This can be resolved by adding {}. 740 * 741 * @returns {Array} 742 */ 743Parser.prototype.handleInfixNodes = function(body) { 744 var overIndex = -1; 745 var funcName; 746 747 for (var i = 0; i < body.length; i++) { 748 var node = body[i]; 749 if (node.type === "infix") { 750 if (overIndex !== -1) { 751 throw new ParseError( 752 "only one infix operator per group", 753 node.value.token); 754 } 755 overIndex = i; 756 funcName = node.value.replaceWith; 757 } 758 } 759 760 if (overIndex !== -1) { 761 var numerNode; 762 var denomNode; 763 764 var numerBody = body.slice(0, overIndex); 765 var denomBody = body.slice(overIndex + 1); 766 767 if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { 768 numerNode = numerBody[0]; 769 } else { 770 numerNode = new ParseNode("ordgroup", numerBody, this.mode); 771 } 772 773 if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { 774 denomNode = denomBody[0]; 775 } else { 776 denomNode = new ParseNode("ordgroup", denomBody, this.mode); 777 } 778 779 var value = this.callFunction( 780 funcName, [numerNode, denomNode], null); 781 return [new ParseNode(value.type, value, this.mode)]; 782 } else { 783 return body; 784 } 785}; 786 787// The greediness of a superscript or subscript 788var SUPSUB_GREEDINESS = 1; 789 790/** 791 * Handle a subscript or superscript with nice errors. 792 */ 793Parser.prototype.handleSupSubscript = function(name) { 794 var symbolToken = this.nextToken; 795 var symbol = symbolToken.text; 796 this.consume(); 797 var group = this.parseGroup(); 798 799 if (!group) { 800 if (!this.settings.throwOnError && this.nextToken.text[0] === "\\") { 801 return this.handleUnsupportedCmd(); 802 } else { 803 throw new ParseError( 804 "Expected group after '" + symbol + "'", 805 symbolToken 806 ); 807 } 808 } else if (group.isFunction) { 809 // ^ and _ have a greediness, so handle interactions with functions' 810 // greediness 811 var funcGreediness = functions[group.result].greediness; 812 if (funcGreediness > SUPSUB_GREEDINESS) { 813 return this.parseFunction(group); 814 } else { 815 throw new ParseError( 816 "Got function '" + group.result + "' with no arguments " + 817 "as " + name, symbolToken); 818 } 819 } else { 820 return group.result; 821 } 822}; 823 824/** 825 * Converts the textual input of an unsupported command into a text node 826 * contained within a color node whose color is determined by errorColor 827 */ 828Parser.prototype.handleUnsupportedCmd = function() { 829 var text = this.nextToken.text; 830 var textordArray = []; 831 832 for (var i = 0; i < text.length; i++) { 833 textordArray.push(new ParseNode("textord", text[i], "text")); 834 } 835 836 var textNode = new ParseNode( 837 "text", 838 { 839 body: textordArray, 840 type: "text" 841 }, 842 this.mode); 843 844 var colorNode = new ParseNode( 845 "color", 846 { 847 color: this.settings.errorColor, 848 value: [textNode], 849 type: "color" 850 }, 851 this.mode); 852 853 this.consume(); 854 return colorNode; 855}; 856 857/** 858 * Parses a group with optional super/subscripts. 859 * 860 * @return {?ParseNode} 861 */ 862Parser.prototype.parseAtom = function() { 863 // The body of an atom is an implicit group, so that things like 864 // \left(x\right)^2 work correctly. 865 var base = this.parseImplicitGroup(); 866 867 // In text mode, we don't have superscripts or subscripts 868 if (this.mode === "text") { 869 return base; 870 } 871 872 // Note that base may be empty (i.e. null) at this point. 873 874 var superscript; 875 var subscript; 876 while (true) { 877 // Lex the first token 878 var lex = this.nextToken; 879 880 if (lex.text === "\\limits" || lex.text === "\\nolimits") { 881 // We got a limit control 882 if (!base || base.type !== "op") { 883 throw new ParseError( 884 "Limit controls must follow a math operator", 885 lex); 886 } else { 887 var limits = lex.text === "\\limits"; 888 base.value.limits = limits; 889 base.value.alwaysHandleSupSub = true; 890 } 891 this.consume(); 892 } else if (lex.text === "^") { 893 // We got a superscript start 894 if (superscript) { 895 throw new ParseError("Double superscript", lex); 896 } 897 superscript = this.handleSupSubscript("superscript"); 898 } else if (lex.text === "_") { 899 // We got a subscript start 900 if (subscript) { 901 throw new ParseError("Double subscript", lex); 902 } 903 subscript = this.handleSupSubscript("subscript"); 904 } else if (lex.text === "'") { 905 // We got a prime 906 var prime = new ParseNode("textord", "\\prime", this.mode); 907 908 // Many primes can be grouped together, so we handle this here 909 var primes = [prime]; 910 this.consume(); 911 // Keep lexing tokens until we get something that's not a prime 912 while (this.nextToken.text === "'") { 913 // For each one, add another prime to the list 914 primes.push(prime); 915 this.consume(); 916 } 917 // Put them into an ordgroup as the superscript 918 superscript = new ParseNode("ordgroup", primes, this.mode); 919 } else { 920 // If it wasn't ^, _, or ', stop parsing super/subscripts 921 break; 922 } 923 } 924 925 if (superscript || subscript) { 926 // If we got either a superscript or subscript, create a supsub 927 return new ParseNode("supsub", { 928 base: base, 929 sup: superscript, 930 sub: subscript 931 }, this.mode); 932 } else { 933 // Otherwise return the original body 934 return base; 935 } 936}; 937 938// A list of the size-changing functions, for use in parseImplicitGroup 939var sizeFuncs = [ 940 "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", 941 "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge" 942]; 943 944// A list of the style-changing functions, for use in parseImplicitGroup 945var styleFuncs = [ 946 "\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle" 947]; 948 949/** 950 * Parses an implicit group, which is a group that starts at the end of a 951 * specified, and ends right before a higher explicit group ends, or at EOL. It 952 * is used for functions that appear to affect the current style, like \Large or 953 * \textrm, where instead of keeping a style we just pretend that there is an 954 * implicit grouping after it until the end of the group. E.g. 955 * small text {\Large large text} small text again 956 * It is also used for \left and \right to get the correct grouping. 957 * 958 * @return {?ParseNode} 959 */ 960Parser.prototype.parseImplicitGroup = function() { 961 var start = this.parseSymbol(); 962 963 if (start == null) { 964 // If we didn't get anything we handle, fall back to parseFunction 965 return this.parseFunction(); 966 } 967 968 var func = start.result; 969 var body; 970 971 if (func === "\\left") { 972 // If we see a left: 973 // Parse the entire left function (including the delimiter) 974 var left = this.parseFunction(start); 975 // Parse out the implicit body 976 ++this.leftrightDepth; 977 body = this.parseExpression(false); 978 --this.leftrightDepth; 979 // Check the next token 980 this.expect("\\right", false); 981 var right = this.parseFunction(); 982 return new ParseNode("leftright", { 983 body: body, 984 left: left.value.value, 985 right: right.value.value 986 }, this.mode); 987 } else if (func === "\\begin") { 988 // begin...end is similar to left...right 989 var begin = this.parseFunction(start); 990 var envName = begin.value.name; 991 if (!environments.hasOwnProperty(envName)) { 992 throw new ParseError( 993 "No such environment: " + envName, begin.value.nameGroup); 994 } 995 // Build the environment object. Arguments and other information will 996 // be made available to the begin and end methods using properties. 997 var env = environments[envName]; 998 var args = this.parseArguments("\\begin{" + envName + "}", env); 999 var context = { 1000 mode: this.mode, 1001 envName: envName, 1002 parser: this, 1003 positions: args.pop() 1004 }; 1005 var result = env.handler(context, args); 1006 this.expect("\\end", false); 1007 var endNameToken = this.nextToken; 1008 var end = this.parseFunction(); 1009 if (end.value.name !== envName) { 1010 throw new ParseError( 1011 "Mismatch: \\begin{" + envName + "} matched " + 1012 "by \\end{" + end.value.name + "}", 1013 endNameToken); 1014 } 1015 result.position = end.position; 1016 return result; 1017 } else if (utils.contains(sizeFuncs, func)) { 1018 // If we see a sizing function, parse out the implict body 1019 body = this.parseExpression(false); 1020 return new ParseNode("sizing", { 1021 // Figure out what size to use based on the list of functions above 1022 size: "size" + (utils.indexOf(sizeFuncs, func) + 1), 1023 value: body 1024 }, this.mode); 1025 } else if (utils.contains(styleFuncs, func)) { 1026 // If we see a styling function, parse out the implict body 1027 body = this.parseExpression(true); 1028 return new ParseNode("styling", { 1029 // Figure out what style to use by pulling out the style from 1030 // the function name 1031 style: func.slice(1, func.length - 5), 1032 value: body 1033 }, this.mode); 1034 } else { 1035 // Defer to parseFunction if it's not a function we handle 1036 return this.parseFunction(start); 1037 } 1038}; 1039 1040/** 1041 * Parses an entire function, including its base and all of its arguments. 1042 * The base might either have been parsed already, in which case 1043 * it is provided as an argument, or it's the next group in the input. 1044 * 1045 * @param {ParseFuncOrArgument=} baseGroup optional as described above 1046 * @return {?ParseNode} 1047 */ 1048Parser.prototype.parseFunction = function(baseGroup) { 1049 if (!baseGroup) { 1050 baseGroup = this.parseGroup(); 1051 } 1052 1053 if (baseGroup) { 1054 if (baseGroup.isFunction) { 1055 var func = baseGroup.result; 1056 var funcData = functions[func]; 1057 if (this.mode === "text" && !funcData.allowedInText) { 1058 throw new ParseError( 1059 "Can't use function '" + func + "' in text mode", 1060 baseGroup.token); 1061 } 1062 1063 var args = this.parseArguments(func, funcData); 1064 var token = baseGroup.token; 1065 var result = this.callFunction(func, args, args.pop(), token); 1066 return new ParseNode(result.type, result, this.mode); 1067 } else { 1068 return baseGroup.result; 1069 } 1070 } else { 1071 return null; 1072 } 1073}; 1074 1075/** 1076 * Call a function handler with a suitable context and arguments. 1077 */ 1078Parser.prototype.callFunction = function(name, args, positions, token) { 1079 var context = { 1080 funcName: name, 1081 parser: this, 1082 positions: positions, 1083 token: token 1084 }; 1085 return functions[name].handler(context, args); 1086}; 1087 1088/** 1089 * Parses the arguments of a function or environment 1090 * 1091 * @param {string} func "\name" or "\begin{name}" 1092 * @param {{numArgs:number,numOptionalArgs:number|undefined}} funcData 1093 * @return the array of arguments, with the list of positions as last element 1094 */ 1095Parser.prototype.parseArguments = function(func, funcData) { 1096 var totalArgs = funcData.numArgs + funcData.numOptionalArgs; 1097 if (totalArgs === 0) { 1098 return [[this.pos]]; 1099 } 1100 1101 var baseGreediness = funcData.greediness; 1102 var positions = [this.pos]; 1103 var args = []; 1104 1105 for (var i = 0; i < totalArgs; i++) { 1106 var nextToken = this.nextToken; 1107 var argType = funcData.argTypes && funcData.argTypes[i]; 1108 var arg; 1109 if (i < funcData.numOptionalArgs) { 1110 if (argType) { 1111 arg = this.parseGroupOfType(argType, true); 1112 } else { 1113 arg = this.parseGroup(true); 1114 } 1115 if (!arg) { 1116 args.push(null); 1117 positions.push(this.pos); 1118 continue; 1119 } 1120 } else { 1121 if (argType) { 1122 arg = this.parseGroupOfType(argType); 1123 } else { 1124 arg = this.parseGroup(); 1125 } 1126 if (!arg) { 1127 if (!this.settings.throwOnError && 1128 this.nextToken.text[0] === "\\") { 1129 arg = new ParseFuncOrArgument( 1130 this.handleUnsupportedCmd(this.nextToken.text), 1131 false); 1132 } else { 1133 throw new ParseError( 1134 "Expected group after '" + func + "'", nextToken); 1135 } 1136 } 1137 } 1138 var argNode; 1139 if (arg.isFunction) { 1140 var argGreediness = 1141 functions[arg.result].greediness; 1142 if (argGreediness > baseGreediness) { 1143 argNode = this.parseFunction(arg); 1144 } else { 1145 throw new ParseError( 1146 "Got function '" + arg.result + "' as " + 1147 "argument to '" + func + "'", nextToken); 1148 } 1149 } else { 1150 argNode = arg.result; 1151 } 1152 args.push(argNode); 1153 positions.push(this.pos); 1154 } 1155 1156 args.push(positions); 1157 1158 return args; 1159}; 1160 1161 1162/** 1163 * Parses a group when the mode is changing. 1164 * 1165 * @return {?ParseFuncOrArgument} 1166 */ 1167Parser.prototype.parseGroupOfType = function(innerMode, optional) { 1168 var outerMode = this.mode; 1169 // Handle `original` argTypes 1170 if (innerMode === "original") { 1171 innerMode = outerMode; 1172 } 1173 1174 if (innerMode === "color") { 1175 return this.parseColorGroup(optional); 1176 } 1177 if (innerMode === "size") { 1178 return this.parseSizeGroup(optional); 1179 } 1180 1181 this.switchMode(innerMode); 1182 if (innerMode === "text") { 1183 // text mode is special because it should ignore the whitespace before 1184 // it 1185 while (this.nextToken.text === " ") { 1186 this.consume(); 1187 } 1188 } 1189 // By the time we get here, innerMode is one of "text" or "math". 1190 // We switch the mode of the parser, recurse, then restore the old mode. 1191 var res = this.parseGroup(optional); 1192 this.switchMode(outerMode); 1193 return res; 1194}; 1195 1196/** 1197 * Parses a group, essentially returning the string formed by the 1198 * brace-enclosed tokens plus some position information. 1199 * 1200 * @param {string} modeName Used to describe the mode in error messages 1201 * @param {boolean=} optional Whether the group is optional or required 1202 */ 1203Parser.prototype.parseStringGroup = function(modeName, optional) { 1204 if (optional && this.nextToken.text !== "[") { 1205 return null; 1206 } 1207 var outerMode = this.mode; 1208 this.mode = "text"; 1209 this.expect(optional ? "[" : "{"); 1210 var str = ""; 1211 var firstToken = this.nextToken; 1212 var lastToken = firstToken; 1213 while (this.nextToken.text !== (optional ? "]" : "}")) { 1214 if (this.nextToken.text === "EOF") { 1215 throw new ParseError( 1216 "Unexpected end of input in " + modeName, 1217 firstToken.range(this.nextToken, str)); 1218 } 1219 lastToken = this.nextToken; 1220 str += lastToken.text; 1221 this.consume(); 1222 } 1223 this.mode = outerMode; 1224 this.expect(optional ? "]" : "}"); 1225 return firstToken.range(lastToken, str); 1226}; 1227 1228/** 1229 * Parses a regex-delimited group: the largest sequence of tokens 1230 * whose concatenated strings match `regex`. Returns the string 1231 * formed by the tokens plus some position information. 1232 * 1233 * @param {RegExp} regex 1234 * @param {string} modeName Used to describe the mode in error messages 1235 */ 1236Parser.prototype.parseRegexGroup = function(regex, modeName) { 1237 var outerMode = this.mode; 1238 this.mode = "text"; 1239 var firstToken = this.nextToken; 1240 var lastToken = firstToken; 1241 var str = ""; 1242 while (this.nextToken.text !== "EOF" 1243 && regex.test(str + this.nextToken.text)) { 1244 lastToken = this.nextToken; 1245 str += lastToken.text; 1246 this.consume(); 1247 } 1248 if (str === "") { 1249 throw new ParseError( 1250 "Invalid " + modeName + ": '" + firstToken.text + "'", 1251 firstToken); 1252 } 1253 this.mode = outerMode; 1254 return firstToken.range(lastToken, str); 1255}; 1256 1257/** 1258 * Parses a color description. 1259 */ 1260Parser.prototype.parseColorGroup = function(optional) { 1261 var res = this.parseStringGroup("color", optional); 1262 if (!res) { 1263 return null; 1264 } 1265 var match = (/^(#[a-z0-9]+|[a-z]+)$/i).exec(res.text); 1266 if (!match) { 1267 throw new ParseError("Invalid color: '" + res.text + "'", res); 1268 } 1269 return new ParseFuncOrArgument( 1270 new ParseNode("color", match[0], this.mode), 1271 false); 1272}; 1273 1274/** 1275 * Parses a size specification, consisting of magnitude and unit. 1276 */ 1277Parser.prototype.parseSizeGroup = function(optional) { 1278 var res; 1279 if (!optional && this.nextToken.text !== "{") { 1280 res = this.parseRegexGroup( 1281 /^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size"); 1282 } else { 1283 res = this.parseStringGroup("size", optional); 1284 } 1285 if (!res) { 1286 return null; 1287 } 1288 var match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text); 1289 if (!match) { 1290 throw new ParseError("Invalid size: '" + res.text + "'", res); 1291 } 1292 var data = { 1293 number: +(match[1] + match[2]), // sign + magnitude, cast to number 1294 unit: match[3] 1295 }; 1296 if (data.unit !== "em" && data.unit !== "ex" && data.unit !== "mu") { 1297 throw new ParseError("Invalid unit: '" + data.unit + "'", res); 1298 } 1299 return new ParseFuncOrArgument( 1300 new ParseNode("color", data, this.mode), 1301 false); 1302}; 1303 1304/** 1305 * If the argument is false or absent, this parses an ordinary group, 1306 * which is either a single nucleus (like "x") or an expression 1307 * in braces (like "{x+y}"). 1308 * If the argument is true, it parses either a bracket-delimited expression 1309 * (like "[x+y]") or returns null to indicate the absence of a 1310 * bracket-enclosed group. 1311 * 1312 * @param {boolean=} optional Whether the group is optional or required 1313 * @return {?ParseFuncOrArgument} 1314 */ 1315Parser.prototype.parseGroup = function(optional) { 1316 var firstToken = this.nextToken; 1317 // Try to parse an open brace 1318 if (this.nextToken.text === (optional ? "[" : "{")) { 1319 // If we get a brace, parse an expression 1320 this.consume(); 1321 var expression = this.parseExpression(false, optional ? "]" : null); 1322 var lastToken = this.nextToken; 1323 // Make sure we get a close brace 1324 this.expect(optional ? "]" : "}"); 1325 if (this.mode === "text") { 1326 this.formLigatures(expression); 1327 } 1328 return new ParseFuncOrArgument( 1329 new ParseNode("ordgroup", expression, this.mode, 1330 firstToken, lastToken), 1331 false); 1332 } else { 1333 // Otherwise, just return a nucleus, or nothing for an optional group 1334 return optional ? null : this.parseSymbol(); 1335 } 1336}; 1337 1338/** 1339 * Form ligature-like combinations of characters for text mode. 1340 * This includes inputs like "--", "---", "``" and "''". 1341 * The result will simply replace multiple textord nodes with a single 1342 * character in each value by a single textord node having multiple 1343 * characters in its value. The representation is still ASCII source. 1344 * 1345 * @param {Array.<ParseNode>} group the nodes of this group, 1346 * list will be moified in place 1347 */ 1348Parser.prototype.formLigatures = function(group) { 1349 var i; 1350 var n = group.length - 1; 1351 for (i = 0; i < n; ++i) { 1352 var a = group[i]; 1353 var v = a.value; 1354 if (v === "-" && group[i + 1].value === "-") { 1355 if (i + 1 < n && group[i + 2].value === "-") { 1356 group.splice(i, 3, new ParseNode( 1357 "textord", "---", "text", a, group[i + 2])); 1358 n -= 2; 1359 } else { 1360 group.splice(i, 2, new ParseNode( 1361 "textord", "--", "text", a, group[i + 1])); 1362 n -= 1; 1363 } 1364 } 1365 if ((v === "'" || v === "`") && group[i + 1].value === v) { 1366 group.splice(i, 2, new ParseNode( 1367 "textord", v + v, "text", a, group[i + 1])); 1368 n -= 1; 1369 } 1370 } 1371}; 1372 1373/** 1374 * Parse a single symbol out of the string. Here, we handle both the functions 1375 * we have defined, as well as the single character symbols 1376 * 1377 * @return {?ParseFuncOrArgument} 1378 */ 1379Parser.prototype.parseSymbol = function() { 1380 var nucleus = this.nextToken; 1381 1382 if (functions[nucleus.text]) { 1383 this.consume(); 1384 // If there exists a function with this name, we return the function and 1385 // say that it is a function. 1386 return new ParseFuncOrArgument( 1387 nucleus.text, 1388 true, nucleus); 1389 } else if (symbols[this.mode][nucleus.text]) { 1390 this.consume(); 1391 // Otherwise if this is a no-argument function, find the type it 1392 // corresponds to in the symbols map 1393 return new ParseFuncOrArgument( 1394 new ParseNode(symbols[this.mode][nucleus.text].group, 1395 nucleus.text, this.mode, nucleus), 1396 false, nucleus); 1397 } else if (this.mode === "text" && cjkRegex.test(nucleus.text)) { 1398 this.consume(); 1399 return new ParseFuncOrArgument( 1400 new ParseNode("textord", nucleus.text, this.mode, nucleus), 1401 false, nucleus); 1402 } else { 1403 return null; 1404 } 1405}; 1406 1407Parser.prototype.ParseNode = ParseNode; 1408 1409module.exports = Parser; 1410 1411},{"./MacroExpander":4,"./ParseError":6,"./environments":16,"./functions":19,"./parseData":21,"./symbols":23,"./unicodeRegexes":24,"./utils":25}],8:[function(require,module,exports){ 1412/** 1413 * This is a module for storing settings passed into KaTeX. It correctly handles 1414 * default settings. 1415 */ 1416 1417/** 1418 * Helper function for getting a default value if the value is undefined 1419 */ 1420function get(option, defaultValue) { 1421 return option === undefined ? defaultValue : option; 1422} 1423 1424/** 1425 * The main Settings object 1426 * 1427 * The current options stored are: 1428 * - displayMode: Whether the expression should be typeset by default in 1429 * textstyle or displaystyle (default false) 1430 */ 1431function Settings(options) { 1432 // allow null options 1433 options = options || {}; 1434 this.displayMode = get(options.displayMode, false); 1435 this.throwOnError = get(options.throwOnError, true); 1436 this.errorColor = get(options.errorColor, "#cc0000"); 1437 this.macros = options.macros || {}; 1438} 1439 1440module.exports = Settings; 1441 1442},{}],9:[function(require,module,exports){ 1443/** 1444 * This file contains information and classes for the various kinds of styles 1445 * used in TeX. It provides a generic `Style` class, which holds information 1446 * about a specific style. It then provides instances of all the different kinds 1447 * of styles possible, and provides functions to move between them and get 1448 * information about them. 1449 */ 1450 1451var sigmas = require("./fontMetrics.js").sigmas; 1452 1453var metrics = [{}, {}, {}]; 1454var i; 1455for (var key in sigmas) { 1456 if (sigmas.hasOwnProperty(key)) { 1457 for (i = 0; i < 3; i++) { 1458 metrics[i][key] = sigmas[key][i]; 1459 } 1460 } 1461} 1462for (i = 0; i < 3; i++) { 1463 metrics[i].emPerEx = sigmas.xHeight[i] / sigmas.quad[i]; 1464} 1465 1466/** 1467 * The main style class. Contains a unique id for the style, a size (which is 1468 * the same for cramped and uncramped version of a style), a cramped flag, and a 1469 * size multiplier, which gives the size difference between a style and 1470 * textstyle. 1471 */ 1472function Style(id, size, multiplier, cramped) { 1473 this.id = id; 1474 this.size = size; 1475 this.cramped = cramped; 1476 this.sizeMultiplier = multiplier; 1477 this.metrics = metrics[size > 0 ? size - 1 : 0]; 1478} 1479 1480/** 1481 * Get the style of a superscript given a base in the current style. 1482 */ 1483Style.prototype.sup = function() { 1484 return styles[sup[this.id]]; 1485}; 1486 1487/** 1488 * Get the style of a subscript given a base in the current style. 1489 */ 1490Style.prototype.sub = function() { 1491 return styles[sub[this.id]]; 1492}; 1493 1494/** 1495 * Get the style of a fraction numerator given the fraction in the current 1496 * style. 1497 */ 1498Style.prototype.fracNum = function() { 1499 return styles[fracNum[this.id]]; 1500}; 1501 1502/** 1503 * Get the style of a fraction denominator given the fraction in the current 1504 * style. 1505 */ 1506Style.prototype.fracDen = function() { 1507 return styles[fracDen[this.id]]; 1508}; 1509 1510/** 1511 * Get the cramped version of a style (in particular, cramping a cramped style 1512 * doesn't change the style). 1513 */ 1514Style.prototype.cramp = function() { 1515 return styles[cramp[this.id]]; 1516}; 1517 1518/** 1519 * HTML class name, like "displaystyle cramped" 1520 */ 1521Style.prototype.cls = function() { 1522 return sizeNames[this.size] + (this.cramped ? " cramped" : " uncramped"); 1523}; 1524 1525/** 1526 * HTML Reset class name, like "reset-textstyle" 1527 */ 1528Style.prototype.reset = function() { 1529 return resetNames[this.size]; 1530}; 1531 1532/** 1533 * Return if this style is tightly spaced (scriptstyle/scriptscriptstyle) 1534 */ 1535Style.prototype.isTight = function() { 1536 return this.size >= 2; 1537}; 1538 1539// IDs of the different styles 1540var D = 0; 1541var Dc = 1; 1542var T = 2; 1543var Tc = 3; 1544var S = 4; 1545var Sc = 5; 1546var SS = 6; 1547var SSc = 7; 1548 1549// String names for the different sizes 1550var sizeNames = [ 1551 "displaystyle textstyle", 1552 "textstyle", 1553 "scriptstyle", 1554 "scriptscriptstyle" 1555]; 1556 1557// Reset names for the different sizes 1558var resetNames = [ 1559 "reset-textstyle", 1560 "reset-textstyle", 1561 "reset-scriptstyle", 1562 "reset-scriptscriptstyle" 1563]; 1564 1565// Instances of the different styles 1566var styles = [ 1567 new Style(D, 0, 1.0, false), 1568 new Style(Dc, 0, 1.0, true), 1569 new Style(T, 1, 1.0, false), 1570 new Style(Tc, 1, 1.0, true), 1571 new Style(S, 2, 0.7, false), 1572 new Style(Sc, 2, 0.7, true), 1573 new Style(SS, 3, 0.5, false), 1574 new Style(SSc, 3, 0.5, true) 1575]; 1576 1577// Lookup tables for switching from one style to another 1578var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; 1579var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; 1580var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; 1581var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; 1582var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; 1583 1584// We only export some of the styles. Also, we don't export the `Style` class so 1585// no more styles can be generated. 1586module.exports = { 1587 DISPLAY: styles[D], 1588 TEXT: styles[T], 1589 SCRIPT: styles[S], 1590 SCRIPTSCRIPT: styles[SS] 1591}; 1592 1593},{"./fontMetrics.js":17}],10:[function(require,module,exports){ 1594/* eslint no-console:0 */ 1595/** 1596 * This module contains general functions that can be used for building 1597 * different kinds of domTree nodes in a consistent manner. 1598 */ 1599 1600var domTree = require("./domTree"); 1601var fontMetrics = require("./fontMetrics"); 1602var symbols = require("./symbols"); 1603var utils = require("./utils"); 1604 1605var greekCapitals = [ 1606 "\\Gamma", 1607 "\\Delta", 1608 "\\Theta", 1609 "\\Lambda", 1610 "\\Xi", 1611 "\\Pi", 1612 "\\Sigma", 1613 "\\Upsilon", 1614 "\\Phi", 1615 "\\Psi", 1616 "\\Omega" 1617]; 1618 1619// The following have to be loaded from Main-Italic font, using class mainit 1620var mainitLetters = [ 1621 "\u0131", // dotless i, \imath 1622 "\u0237", // dotless j, \jmath 1623 "\u00a3" // \pounds 1624]; 1625 1626/** 1627 * Makes a symbolNode after translation via the list of symbols in symbols.js. 1628 * Correctly pulls out metrics for the character, and optionally takes a list of 1629 * classes to be attached to the node. 1630 * 1631 * TODO: make argument order closer to makeSpan 1632 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which 1633 * should if present come first in `classes`. 1634 */ 1635var makeSymbol = function(value, fontFamily, mode, options, classes) { 1636 // Replace the value with its replaced value from symbol.js 1637 if (symbols[mode][value] && symbols[mode][value].replace) { 1638 value = symbols[mode][value].replace; 1639 } 1640 1641 var metrics = fontMetrics.getCharacterMetrics(value, fontFamily); 1642 1643 var symbolNode; 1644 if (metrics) { 1645 var italic = metrics.italic; 1646 if (mode === "text") { 1647 italic = 0; 1648 } 1649 symbolNode = new domTree.symbolNode( 1650 value, metrics.height, metrics.depth, italic, metrics.skew, 1651 classes); 1652 } else { 1653 // TODO(emily): Figure out a good way to only print this in development 1654 typeof console !== "undefined" && console.warn( 1655 "No character metrics for '" + value + "' in style '" + 1656 fontFamily + "'"); 1657 symbolNode = new domTree.symbolNode(value, 0, 0, 0, 0, classes); 1658 } 1659 1660 if (options) { 1661 if (options.style.isTight()) { 1662 symbolNode.classes.push("mtight"); 1663 } 1664 if (options.getColor()) { 1665 symbolNode.style.color = options.getColor(); 1666 } 1667 } 1668 1669 return symbolNode; 1670}; 1671 1672/** 1673 * Makes a symbol in Main-Regular or AMS-Regular. 1674 * Used for rel, bin, open, close, inner, and punct. 1675 */ 1676var mathsym = function(value, mode, options, classes) { 1677 // Decide what font to render the symbol in by its entry in the symbols 1678 // table. 1679 // Have a special case for when the value = \ because the \ is used as a 1680 // textord in unsupported command errors but cannot be parsed as a regular 1681 // text ordinal and is therefore not present as a symbol in the symbols 1682 // table for text 1683 if (value === "\\" || symbols[mode][value].font === "main") { 1684 return makeSymbol(value, "Main-Regular", mode, options, classes); 1685 } else { 1686 return makeSymbol( 1687 value, "AMS-Regular", mode, options, classes.concat(["amsrm"])); 1688 } 1689}; 1690 1691/** 1692 * Makes a symbol in the default font for mathords and textords. 1693 */ 1694var mathDefault = function(value, mode, options, classes, type) { 1695 if (type === "mathord") { 1696 return mathit(value, mode, options, classes); 1697 } else if (type === "textord") { 1698 return makeSymbol( 1699 value, "Main-Regular", mode, options, classes.concat(["mathrm"])); 1700 } else { 1701 throw new Error("unexpected type: " + type + " in mathDefault"); 1702 } 1703}; 1704 1705/** 1706 * Makes a symbol in the italic math font. 1707 */ 1708var mathit = function(value, mode, options, classes) { 1709 if (/[0-9]/.test(value.charAt(0)) || 1710 // glyphs for \imath and \jmath do not exist in Math-Italic so we 1711 // need to use Main-Italic instead 1712 utils.contains(mainitLetters, value) || 1713 utils.contains(greekCapitals, value)) { 1714 return makeSymbol( 1715 value, "Main-Italic", mode, options, classes.concat(["mainit"])); 1716 } else { 1717 return makeSymbol( 1718 value, "Math-Italic", mode, options, classes.concat(["mathit"])); 1719 } 1720}; 1721 1722/** 1723 * Makes either a mathord or textord in the correct font and color. 1724 */ 1725var makeOrd = function(group, options, type) { 1726 var mode = group.mode; 1727 var value = group.value; 1728 if (symbols[mode][value] && symbols[mode][value].replace) { 1729 value = symbols[mode][value].replace; 1730 } 1731 1732 var classes = ["mord"]; 1733 1734 var font = options.font; 1735 if (font) { 1736 if (font === "mathit" || utils.contains(mainitLetters, value)) { 1737 return mathit(value, mode, options, classes); 1738 } else { 1739 var fontName = fontMap[font].fontName; 1740 if (fontMetrics.getCharacterMetrics(value, fontName)) { 1741 return makeSymbol( 1742 value, fontName, mode, options, classes.concat([font])); 1743 } else { 1744 return mathDefault(value, mode, options, classes, type); 1745 } 1746 } 1747 } else { 1748 return mathDefault(value, mode, options, classes, type); 1749 } 1750}; 1751 1752/** 1753 * Calculate the height, depth, and maxFontSize of an element based on its 1754 * children. 1755 */ 1756var sizeElementFromChildren = function(elem) { 1757 var height = 0; 1758 var depth = 0; 1759 var maxFontSize = 0; 1760 1761 if (elem.children) { 1762 for (var i = 0; i < elem.children.length; i++) { 1763 if (elem.children[i].height > height) { 1764 height = elem.children[i].height; 1765 } 1766 if (elem.children[i].depth > depth) { 1767 depth = elem.children[i].depth; 1768 } 1769 if (elem.children[i].maxFontSize > maxFontSize) { 1770 maxFontSize = elem.children[i].maxFontSize; 1771 } 1772 } 1773 } 1774 1775 elem.height = height; 1776 elem.depth = depth; 1777 elem.maxFontSize = maxFontSize; 1778}; 1779 1780/** 1781 * Makes a span with the given list of classes, list of children, and options. 1782 * 1783 * TODO: Ensure that `options` is always provided (currently some call sites 1784 * don't pass it). 1785 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which 1786 * should if present come first in `classes`. 1787 */ 1788var makeSpan = function(classes, children, options) { 1789 var span = new domTree.span(classes, children, options); 1790 1791 sizeElementFromChildren(span); 1792 1793 return span; 1794}; 1795 1796/** 1797 * Prepends the given children to the given span, updating height, depth, and 1798 * maxFontSize. 1799 */ 1800var prependChildren = function(span, children) { 1801 span.children = children.concat(span.children); 1802 1803 sizeElementFromChildren(span); 1804}; 1805 1806/** 1807 * Makes a document fragment with the given list of children. 1808 */ 1809var makeFragment = function(children) { 1810 var fragment = new domTree.documentFragment(children); 1811 1812 sizeElementFromChildren(fragment); 1813 1814 return fragment; 1815}; 1816 1817/** 1818 * Makes an element placed in each of the vlist elements to ensure that each 1819 * element has the same max font size. To do this, we create a zero-width space 1820 * with the correct font size. 1821 */ 1822var makeFontSizer = function(options, fontSize) { 1823 var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]); 1824 fontSizeInner.style.fontSize = 1825 (fontSize / options.style.sizeMultiplier) + "em"; 1826 1827 var fontSizer = makeSpan( 1828 ["fontsize-ensurer", "reset-" + options.size, "size5"], 1829 [fontSizeInner]); 1830 1831 return fontSizer; 1832}; 1833 1834/** 1835 * Makes a vertical list by stacking elements and kerns on top of each other. 1836 * Allows for many different ways of specifying the positioning method. 1837 * 1838 * Arguments: 1839 * - children: A list of child or kern nodes to be stacked on top of each other 1840 * (i.e. the first element will be at the bottom, and the last at 1841 * the top). Element nodes are specified as 1842 * {type: "elem", elem: node} 1843 * while kern nodes are specified as 1844 * {type: "kern", size: size} 1845 * - positionType: The method by which the vlist should be positioned. Valid 1846 * values are: 1847 * - "individualShift": The children list only contains elem 1848 * nodes, and each node contains an extra 1849 * "shift" value of how much it should be 1850 * shifted (note that shifting is always 1851 * moving downwards). positionData is 1852 * ignored. 1853 * - "top": The positionData specifies the topmost point of 1854 * the vlist (note this is expected to be a height, 1855 * so positive values move up) 1856 * - "bottom": The positionData specifies the bottommost point 1857 * of the vlist (note this is expected to be a 1858 * depth, so positive values move down 1859 * - "shift": The vlist will be positioned such that its 1860 * baseline is positionData away from the baseline 1861 * of the first child. Positive values move 1862 * downwards. 1863 * - "firstBaseline": The vlist will be positioned such that 1864 * its baseline is aligned with the 1865 * baseline of the first child. 1866 * positionData is ignored. (this is 1867 * equivalent to "shift" with 1868 * positionData=0) 1869 * - positionData: Data used in different ways depending on positionType 1870 * - options: An Options object 1871 * 1872 */ 1873var makeVList = function(children, positionType, positionData, options) { 1874 var depth; 1875 var currPos; 1876 var i; 1877 if (positionType === "individualShift") { 1878 var oldChildren = children; 1879 children = [oldChildren[0]]; 1880 1881 // Add in kerns to the list of children to get each element to be 1882 // shifted to the correct specified shift 1883 depth = -oldChildren[0].shift - oldChildren[0].elem.depth; 1884 currPos = depth; 1885 for (i = 1; i < oldChildren.length; i++) { 1886 var diff = -oldChildren[i].shift - currPos - 1887 oldChildren[i].elem.depth; 1888 var size = diff - 1889 (oldChildren[i - 1].elem.height + 1890 oldChildren[i - 1].elem.depth); 1891 1892 currPos = currPos + diff; 1893 1894 children.push({type: "kern", size: size}); 1895 children.push(oldChildren[i]); 1896 } 1897 } else if (positionType === "top") { 1898 // We always start at the bottom, so calculate the bottom by adding up 1899 // all the sizes 1900 var bottom = positionData; 1901 for (i = 0; i < children.length; i++) { 1902 if (children[i].type === "kern") { 1903 bottom -= children[i].size; 1904 } else { 1905 bottom -= children[i].elem.height + children[i].elem.depth; 1906 } 1907 } 1908 depth = bottom; 1909 } else if (positionType === "bottom") { 1910 depth = -positionData; 1911 } else if (positionType === "shift") { 1912 depth = -children[0].elem.depth - positionData; 1913 } else if (positionType === "firstBaseline") { 1914 depth = -children[0].elem.depth; 1915 } else { 1916 depth = 0; 1917 } 1918 1919 // Make the fontSizer 1920 var maxFontSize = 0; 1921 for (i = 0; i < children.length; i++) { 1922 if (children[i].type === "elem") { 1923 maxFontSize = Math.max(maxFontSize, children[i].elem.maxFontSize); 1924 } 1925 } 1926 var fontSizer = makeFontSizer(options, maxFontSize); 1927 1928 // Create a new list of actual children at the correct offsets 1929 var realChildren = []; 1930 currPos = depth; 1931 for (i = 0; i < children.length; i++) { 1932 if (children[i].type === "kern") { 1933 currPos += children[i].size; 1934 } else { 1935 var child = children[i].elem; 1936 1937 var shift = -child.depth - currPos; 1938 currPos += child.height + child.depth; 1939 1940 var childWrap = makeSpan([], [fontSizer, child]); 1941 childWrap.height -= shift; 1942 childWrap.depth += shift; 1943 childWrap.style.top = shift + "em"; 1944 1945 realChildren.push(childWrap); 1946 } 1947 } 1948 1949 // Add in an element at the end with no offset to fix the calculation of 1950 // baselines in some browsers (namely IE, sometimes safari) 1951 var baselineFix = makeSpan( 1952 ["baseline-fix"], [fontSizer, new domTree.symbolNode("\u200b")]); 1953 realChildren.push(baselineFix); 1954 1955 var vlist = makeSpan(["vlist"], realChildren); 1956 // Fix the final height and depth, in case there were kerns at the ends 1957 // since the makeSpan calculation won't take that in to account. 1958 vlist.height = Math.max(currPos, vlist.height); 1959 vlist.depth = Math.max(-depth, vlist.depth); 1960 return vlist; 1961}; 1962 1963// A table of size -> font size for the different sizing functions 1964var sizingMultiplier = { 1965 size1: 0.5, 1966 size2: 0.7, 1967 size3: 0.8, 1968 size4: 0.9, 1969 size5: 1.0, 1970 size6: 1.2, 1971 size7: 1.44, 1972 size8: 1.73, 1973 size9: 2.07, 1974 size10: 2.49 1975}; 1976 1977// A map of spacing functions to their attributes, like size and corresponding 1978// CSS class 1979var spacingFunctions = { 1980 "\\qquad": { 1981 size: "2em", 1982 className: "qquad" 1983 }, 1984 "\\quad": { 1985 size: "1em", 1986 className: "quad" 1987 }, 1988 "\\enspace": { 1989 size: "0.5em", 1990 className: "enspace" 1991 }, 1992 "\\;": { 1993 size: "0.277778em", 1994 className: "thickspace" 1995 }, 1996 "\\:": { 1997 size: "0.22222em", 1998 className: "mediumspace" 1999 }, 2000 "\\,": { 2001 size: "0.16667em", 2002 className: "thinspace" 2003 }, 2004 "\\!": { 2005 size: "-0.16667em", 2006 className: "negativethinspace" 2007 } 2008}; 2009 2010/** 2011 * Maps TeX font commands to objects containing: 2012 * - variant: string used for "mathvariant" attribute in buildMathML.js 2013 * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics 2014 */ 2015// A map between tex font commands an MathML mathvariant attribute values 2016var fontMap = { 2017 // styles 2018 "mathbf": { 2019 variant: "bold", 2020 fontName: "Main-Bold" 2021 }, 2022 "mathrm": { 2023 variant: "normal", 2024 fontName: "Main-Regular" 2025 }, 2026 "textit": { 2027 variant: "italic", 2028 fontName: "Main-Italic" 2029 }, 2030 2031 // "mathit" is missing because it requires the use of two fonts: Main-Italic 2032 // and Math-Italic. This is handled by a special case in makeOrd which ends 2033 // up calling mathit. 2034 2035 // families 2036 "mathbb": { 2037 variant: "double-struck", 2038 fontName: "AMS-Regular" 2039 }, 2040 "mathcal": { 2041 variant: "script", 2042 fontName: "Caligraphic-Regular" 2043 }, 2044 "mathfrak": { 2045 variant: "fraktur", 2046 fontName: "Fraktur-Regular" 2047 }, 2048 "mathscr": { 2049 variant: "script", 2050 fontName: "Script-Regular" 2051 }, 2052 "mathsf": { 2053 variant: "sans-serif", 2054 fontName: "SansSerif-Regular" 2055 }, 2056 "mathtt": { 2057 variant: "monospace", 2058 fontName: "Typewriter-Regular" 2059 } 2060}; 2061 2062module.exports = { 2063 fontMap: fontMap, 2064 makeSymbol: makeSymbol, 2065 mathsym: mathsym, 2066 makeSpan: makeSpan, 2067 makeFragment: makeFragment, 2068 makeVList: makeVList, 2069 makeOrd: makeOrd, 2070 prependChildren: prependChildren, 2071 sizingMultiplier: sizingMultiplier, 2072 spacingFunctions: spacingFunctions 2073}; 2074 2075},{"./domTree":15,"./fontMetrics":17,"./symbols":23,"./utils":25}],11:[function(require,module,exports){ 2076/* eslint no-console:0 */ 2077/** 2078 * This file does the main work of building a domTree structure from a parse 2079 * tree. The entry point is the `buildHTML` function, which takes a parse tree. 2080 * Then, the buildExpression, buildGroup, and various groupTypes functions are 2081 * called, to produce a final HTML tree. 2082 */ 2083 2084var ParseError = require("./ParseError"); 2085var Style = require("./Style"); 2086 2087var buildCommon = require("./buildCommon"); 2088var delimiter = require("./delimiter"); 2089var domTree = require("./domTree"); 2090var fontMetrics = require("./fontMetrics"); 2091var utils = require("./utils"); 2092 2093var makeSpan = buildCommon.makeSpan; 2094 2095var isSpace = function(node) { 2096 return node instanceof domTree.span && node.classes[0] === "mspace"; 2097}; 2098 2099// Binary atoms (first class `mbin`) change into ordinary atoms (`mord`) 2100// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6, 2101// and the text before Rule 19. 2102 2103var isBin = function(node) { 2104 return node && node.classes[0] === "mbin"; 2105}; 2106 2107var isBinLeftCanceller = function(node, isRealGroup) { 2108 // TODO: This code assumes that a node's math class is the first element 2109 // of its `classes` array. A later cleanup should ensure this, for 2110 // instance by changing the signature of `makeSpan`. 2111 if (node) { 2112 return utils.contains(["mbin", "mopen", "mrel", "mop", "mpunct"], 2113 node.classes[0]); 2114 } else { 2115 return isRealGroup; 2116 } 2117}; 2118 2119var isBinRightCanceller = function(node, isRealGroup) { 2120 if (node) { 2121 return utils.contains(["mrel", "mclose", "mpunct"], node.classes[0]); 2122 } else { 2123 return isRealGroup; 2124 } 2125}; 2126 2127/** 2128 * Take a list of nodes, build them in order, and return a list of the built 2129 * nodes. documentFragments are flattened into their contents, so the 2130 * returned list contains no fragments. `isRealGroup` is true if `expression` 2131 * is a real group (no atoms will be added on either side), as opposed to 2132 * a partial group (e.g. one created by \color). 2133 */ 2134var buildExpression = function(expression, options, isRealGroup) { 2135 // Parse expressions into `groups`. 2136 var groups = []; 2137 for (var i = 0; i < expression.length; i++) { 2138 var group = expression[i]; 2139 var output = buildGroup(group, options); 2140 if (output instanceof domTree.documentFragment) { 2141 Array.prototype.push.apply(groups, output.children); 2142 } else { 2143 groups.push(output); 2144 } 2145 } 2146 // At this point `groups` consists entirely of `symbolNode`s and `span`s. 2147 2148 // Explicit spaces (e.g., \;, \,) should be ignored with respect to atom 2149 // spacing (e.g., "add thick space between mord and mrel"). Since CSS 2150 // adjacency rules implement atom spacing, spaces should be invisible to 2151 // CSS. So we splice them out of `groups` and into the atoms themselves. 2152 var spaces = null; 2153 for (i = 0; i < groups.length; i++) { 2154 if (isSpace(groups[i])) { 2155 spaces = spaces || []; 2156 spaces.push(groups[i]); 2157 groups.splice(i, 1); 2158 i--; 2159 } else if (spaces) { 2160 if (groups[i] instanceof domTree.symbolNode) { 2161 groups[i] = makeSpan([].concat(groups[i].classes), [groups[i]]); 2162 } 2163 buildCommon.prependChildren(groups[i], spaces); 2164 spaces = null; 2165 } 2166 } 2167 if (spaces) { 2168 Array.prototype.push.apply(groups, spaces); 2169 } 2170 2171 // Binary operators change to ordinary symbols in some contexts. 2172 for (i = 0; i < groups.length; i++) { 2173 if (isBin(groups[i]) 2174 && (isBinLeftCanceller(groups[i - 1], isRealGroup) 2175 || isBinRightCanceller(groups[i + 1], isRealGroup))) { 2176 groups[i].classes[0] = "mord"; 2177 } 2178 } 2179 2180 return groups; 2181}; 2182 2183// Return math atom class (mclass) of a domTree. 2184var getTypeOfDomTree = function(node) { 2185 if (node instanceof domTree.documentFragment) { 2186 if (node.children.length) { 2187 return getTypeOfDomTree( 2188 node.children[node.children.length - 1]); 2189 } 2190 } else { 2191 if (utils.contains(["mord", "mop", "mbin", "mrel", "mopen", "mclose", 2192 "mpunct", "minner"], node.classes[0])) { 2193 return node.classes[0]; 2194 } 2195 } 2196 return null; 2197}; 2198 2199/** 2200 * Sometimes, groups perform special rules when they have superscripts or 2201 * subscripts attached to them. This function lets the `supsub` group know that 2202 * its inner element should handle the superscripts and subscripts instead of 2203 * handling them itself. 2204 */ 2205var shouldHandleSupSub = function(group, options) { 2206 if (!group) { 2207 return false; 2208 } else if (group.type === "op") { 2209 // Operators handle supsubs differently when they have limits 2210 // (e.g. `\displaystyle\sum_2^3`) 2211 return group.value.limits && 2212 (options.style.size === Style.DISPLAY.size || 2213 group.value.alwaysHandleSupSub); 2214 } else if (group.type === "accent") { 2215 return isCharacterBox(group.value.base); 2216 } else { 2217 return null; 2218 } 2219}; 2220 2221/** 2222 * Sometimes we want to pull out the innermost element of a group. In most 2223 * cases, this will just be the group itself, but when ordgroups and colors have 2224 * a single element, we want to pull that out. 2225 */ 2226var getBaseElem = function(group) { 2227 if (!group) { 2228 return false; 2229 } else if (group.type === "ordgroup") { 2230 if (group.value.length === 1) { 2231 return getBaseElem(group.value[0]); 2232 } else { 2233 return group; 2234 } 2235 } else if (group.type === "color") { 2236 if (group.value.value.length === 1) { 2237 return getBaseElem(group.value.value[0]); 2238 } else { 2239 return group; 2240 } 2241 } else if (group.type === "font") { 2242 return getBaseElem(group.value.body); 2243 } else { 2244 return group; 2245 } 2246}; 2247 2248/** 2249 * TeXbook algorithms often reference "character boxes", which are simply groups 2250 * with a single character in them. To decide if something is a character box, 2251 * we find its innermost group, and see if it is a single character. 2252 */ 2253var isCharacterBox = function(group) { 2254 var baseElem = getBaseElem(group); 2255 2256 // These are all they types of groups which hold single characters 2257 return baseElem.type === "mathord" || 2258 baseElem.type === "textord" || 2259 baseElem.type === "bin" || 2260 baseElem.type === "rel" || 2261 baseElem.type === "inner" || 2262 baseElem.type === "open" || 2263 baseElem.type === "close" || 2264 baseElem.type === "punct"; 2265}; 2266 2267var makeNullDelimiter = function(options, classes) { 2268 return makeSpan(classes.concat([ 2269 "sizing", "reset-" + options.size, "size5", 2270 options.style.reset(), Style.TEXT.cls(), 2271 "nulldelimiter"])); 2272}; 2273 2274/** 2275 * This is a map of group types to the function used to handle that type. 2276 * Simpler types come at the beginning, while complicated types come afterwards. 2277 */ 2278var groupTypes = {}; 2279 2280groupTypes.mathord = function(group, options) { 2281 return buildCommon.makeOrd(group, options, "mathord"); 2282}; 2283 2284groupTypes.textord = function(group, options) { 2285 return buildCommon.makeOrd(group, options, "textord"); 2286}; 2287 2288groupTypes.bin = function(group, options) { 2289 return buildCommon.mathsym( 2290 group.value, group.mode, options, ["mbin"]); 2291}; 2292 2293groupTypes.rel = function(group, options) { 2294 return buildCommon.mathsym( 2295 group.value, group.mode, options, ["mrel"]); 2296}; 2297 2298groupTypes.open = function(group, options) { 2299 return buildCommon.mathsym( 2300 group.value, group.mode, options, ["mopen"]); 2301}; 2302 2303groupTypes.close = function(group, options) { 2304 return buildCommon.mathsym( 2305 group.value, group.mode, options, ["mclose"]); 2306}; 2307 2308groupTypes.inner = function(group, options) { 2309 return buildCommon.mathsym( 2310 group.value, group.mode, options, ["minner"]); 2311}; 2312 2313groupTypes.punct = function(group, options) { 2314 return buildCommon.mathsym( 2315 group.value, group.mode, options, ["mpunct"]); 2316}; 2317 2318groupTypes.ordgroup = function(group, options) { 2319 return makeSpan( 2320 ["mord", options.style.cls()], 2321 buildExpression(group.value, options.reset(), true), 2322 options 2323 ); 2324}; 2325 2326groupTypes.text = function(group, options) { 2327 var newOptions = options.withFont(group.value.style); 2328 var inner = buildExpression(group.value.body, newOptions, true); 2329 for (var i = 0; i < inner.length - 1; i++) { 2330 if (inner[i].tryCombine(inner[i + 1])) { 2331 inner.splice(i + 1, 1); 2332 i--; 2333 } 2334 } 2335 return makeSpan(["mord", "text", newOptions.style.cls()], 2336 inner, newOptions); 2337}; 2338 2339groupTypes.color = function(group, options) { 2340 var elements = buildExpression( 2341 group.value.value, 2342 options.withColor(group.value.color), 2343 false 2344 ); 2345 2346 // \color isn't supposed to affect the type of the elements it contains. 2347 // To accomplish this, we wrap the results in a fragment, so the inner 2348 // elements will be able to directly interact with their neighbors. For 2349 // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3` 2350 return new buildCommon.makeFragment(elements); 2351}; 2352 2353groupTypes.supsub = function(group, options) { 2354 // Superscript and subscripts are handled in the TeXbook on page 2355 // 445-446, rules 18(a-f). 2356 2357 // Here is where we defer to the inner group if it should handle 2358 // superscripts and subscripts itself. 2359 if (shouldHandleSupSub(group.value.base, options)) { 2360 return groupTypes[group.value.base.type](group, options); 2361 } 2362 2363 var base = buildGroup(group.value.base, options.reset()); 2364 var supmid; 2365 var submid; 2366 var sup; 2367 var sub; 2368 2369 var style = options.style; 2370 var newOptions; 2371 2372 if (group.value.sup) { 2373 newOptions = options.withStyle(style.sup()); 2374 sup = buildGroup(group.value.sup, newOptions); 2375 supmid = makeSpan([style.reset(), style.sup().cls()], 2376 [sup], newOptions); 2377 } 2378 2379 if (group.value.sub) { 2380 newOptions = options.withStyle(style.sub()); 2381 sub = buildGroup(group.value.sub, newOptions); 2382 submid = makeSpan([style.reset(), style.sub().cls()], 2383 [sub], newOptions); 2384 } 2385 2386 // Rule 18a 2387 var supShift; 2388 var subShift; 2389 if (isCharacterBox(group.value.base)) { 2390 supShift = 0; 2391 subShift = 0; 2392 } else { 2393 supShift = base.height - style.metrics.supDrop; 2394 subShift = base.depth + style.metrics.subDrop; 2395 } 2396 2397 // Rule 18c 2398 var minSupShift; 2399 if (style === Style.DISPLAY) { 2400 minSupShift = style.metrics.sup1; 2401 } else if (style.cramped) { 2402 minSupShift = style.metrics.sup3; 2403 } else { 2404 minSupShift = style.metrics.sup2; 2405 } 2406 2407 // scriptspace is a font-size-independent size, so scale it 2408 // appropriately 2409 var multiplier = Style.TEXT.sizeMultiplier * 2410 style.sizeMultiplier; 2411 var scriptspace = 2412 (0.5 / fontMetrics.metrics.ptPerEm) / multiplier + "em"; 2413 2414 var supsub; 2415 if (!group.value.sup) { 2416 // Rule 18b 2417 subShift = Math.max( 2418 subShift, style.metrics.sub1, 2419 sub.height - 0.8 * style.metrics.xHeight); 2420 2421 supsub = buildCommon.makeVList([ 2422 {type: "elem", elem: submid} 2423 ], "shift", subShift, options); 2424 2425 supsub.children[0].style.marginRight = scriptspace; 2426 2427 // Subscripts shouldn't be shifted by the base's italic correction. 2428 // Account for that by shifting the subscript back the appropriate 2429 // amount. Note we only do this when the base is a single symbol. 2430 if (base instanceof domTree.symbolNode) { 2431 supsub.children[0].style.marginLeft = -base.italic + "em"; 2432 } 2433 } else if (!group.value.sub) { 2434 // Rule 18c, d 2435 supShift = Math.max(supShift, minSupShift, 2436 sup.depth + 0.25 * style.metrics.xHeight); 2437 2438 supsub = buildCommon.makeVList([ 2439 {type: "elem", elem: supmid} 2440 ], "shift", -supShift, options); 2441 2442 supsub.children[0].style.marginRight = scriptspace; 2443 } else { 2444 supShift = Math.max( 2445 supShift, minSupShift, sup.depth + 0.25 * style.metrics.xHeight); 2446 subShift = Math.max(subShift, style.metrics.sub2); 2447 2448 var ruleWidth = fontMetrics.metrics.defaultRuleThickness; 2449 2450 // Rule 18e 2451 if ((supShift - sup.depth) - (sub.height - subShift) < 2452 4 * ruleWidth) { 2453 subShift = 4 * ruleWidth - (supShift - sup.depth) + sub.height; 2454 var psi = 0.8 * style.metrics.xHeight - (supShift - sup.depth); 2455 if (psi > 0) { 2456 supShift += psi; 2457 subShift -= psi; 2458 } 2459 } 2460 2461 supsub = buildCommon.makeVList([ 2462 {type: "elem", elem: submid, shift: subShift}, 2463 {type: "elem", elem: supmid, shift: -supShift} 2464 ], "individualShift", null, options); 2465 2466 // See comment above about subscripts not being shifted 2467 if (base instanceof domTree.symbolNode) { 2468 supsub.children[0].style.marginLeft = -base.italic + "em"; 2469 } 2470 2471 supsub.children[0].style.marginRight = scriptspace; 2472 supsub.children[1].style.marginRight = scriptspace; 2473 } 2474 2475 // We ensure to wrap the supsub vlist in a span.msupsub to reset text-align 2476 var mclass = getTypeOfDomTree(base) || "mord"; 2477 return makeSpan([mclass], 2478 [base, makeSpan(["msupsub"], [supsub])], 2479 options); 2480}; 2481 2482groupTypes.genfrac = function(group, options) { 2483 // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). 2484 // Figure out what style this fraction should be in based on the 2485 // function used 2486 var style = options.style; 2487 if (group.value.size === "display") { 2488 style = Style.DISPLAY; 2489 } else if (group.value.size === "text") { 2490 style = Style.TEXT; 2491 } 2492 2493 var nstyle = style.fracNum(); 2494 var dstyle = style.fracDen(); 2495 var newOptions; 2496 2497 newOptions = options.withStyle(nstyle); 2498 var numer = buildGroup(group.value.numer, newOptions); 2499 var numerreset = makeSpan([style.reset(), nstyle.cls()], 2500 [numer], newOptions); 2501 2502 newOptions = options.withStyle(dstyle); 2503 var denom = buildGroup(group.value.denom, newOptions); 2504 var denomreset = makeSpan([style.reset(), dstyle.cls()], 2505 [denom], newOptions); 2506 2507 var ruleWidth; 2508 if (group.value.hasBarLine) { 2509 ruleWidth = fontMetrics.metrics.defaultRuleThickness / 2510 options.style.sizeMultiplier; 2511 } else { 2512 ruleWidth = 0; 2513 } 2514 2515 // Rule 15b 2516 var numShift; 2517 var clearance; 2518 var denomShift; 2519 if (style.size === Style.DISPLAY.size) { 2520 numShift = style.metrics.num1; 2521 if (ruleWidth > 0) { 2522 clearance = 3 * ruleWidth; 2523 } else { 2524 clearance = 7 * fontMetrics.metrics.defaultRuleThickness; 2525 } 2526 denomShift = style.metrics.denom1; 2527 } else { 2528 if (ruleWidth > 0) { 2529 numShift = style.metrics.num2; 2530 clearance = ruleWidth; 2531 } else { 2532 numShift = style.metrics.num3; 2533 clearance = 3 * fontMetrics.metrics.defaultRuleThickness; 2534 } 2535 denomShift = style.metrics.denom2; 2536 } 2537 2538 var frac; 2539 if (ruleWidth === 0) { 2540 // Rule 15c 2541 var candidateClearance = 2542 (numShift - numer.depth) - (denom.height - denomShift); 2543 if (candidateClearance < clearance) { 2544 numShift += 0.5 * (clearance - candidateClearance); 2545 denomShift += 0.5 * (clearance - candidateClearance); 2546 } 2547 2548 frac = buildCommon.makeVList([ 2549 {type: "elem", elem: denomreset, shift: denomShift}, 2550 {type: "elem", elem: numerreset, shift: -numShift} 2551 ], "individualShift", null, options); 2552 } else { 2553 // Rule 15d 2554 var axisHeight = style.metrics.axisHeight; 2555 2556 if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth) < 2557 clearance) { 2558 numShift += 2559 clearance - ((numShift - numer.depth) - 2560 (axisHeight + 0.5 * ruleWidth)); 2561 } 2562 2563 if ((axisHeight - 0.5 * ruleWidth) - (denom.height - denomShift) < 2564 clearance) { 2565 denomShift += 2566 clearance - ((axisHeight - 0.5 * ruleWidth) - 2567 (denom.height - denomShift)); 2568 } 2569 2570 var mid = makeSpan( 2571 [options.style.reset(), Style.TEXT.cls(), "frac-line"]); 2572 // Manually set the height of the line because its height is 2573 // created in CSS 2574 mid.height = ruleWidth; 2575 2576 var midShift = -(axisHeight - 0.5 * ruleWidth); 2577 2578 frac = buildCommon.makeVList([ 2579 {type: "elem", elem: denomreset, shift: denomShift}, 2580 {type: "elem", elem: mid, shift: midShift}, 2581 {type: "elem", elem: numerreset, shift: -numShift} 2582 ], "individualShift", null, options); 2583 } 2584 2585 // Since we manually change the style sometimes (with \dfrac or \tfrac), 2586 // account for the possible size change here. 2587 frac.height *= style.sizeMultiplier / options.style.sizeMultiplier; 2588 frac.depth *= style.sizeMultiplier / options.style.sizeMultiplier; 2589 2590 // Rule 15e 2591 var delimSize; 2592 if (style.size === Style.DISPLAY.size) { 2593 delimSize = style.metrics.delim1; 2594 } else { 2595 delimSize = style.metrics.delim2; 2596 } 2597 2598 var leftDelim; 2599 var rightDelim; 2600 if (group.value.leftDelim == null) { 2601 leftDelim = makeNullDelimiter(options, ["mopen"]); 2602 } else { 2603 leftDelim = delimiter.customSizedDelim( 2604 group.value.leftDelim, delimSize, true, 2605 options.withStyle(style), group.mode, ["mopen"]); 2606 } 2607 if (group.value.rightDelim == null) { 2608 rightDelim = makeNullDelimiter(options, ["mclose"]); 2609 } else { 2610 rightDelim = delimiter.customSizedDelim( 2611 group.value.rightDelim, delimSize, true, 2612 options.withStyle(style), group.mode, ["mclose"]); 2613 } 2614 2615 return makeSpan( 2616 ["mord", options.style.reset(), style.cls()], 2617 [leftDelim, makeSpan(["mfrac"], [frac]), rightDelim], 2618 options); 2619}; 2620 2621var calculateSize = function(sizeValue, style) { 2622 var x = sizeValue.number; 2623 if (sizeValue.unit === "ex") { 2624 x *= style.metrics.emPerEx; 2625 } else if (sizeValue.unit === "mu") { 2626 x /= 18; 2627 } 2628 return x; 2629}; 2630 2631groupTypes.array = function(group, options) { 2632 var r; 2633 var c; 2634 var nr = group.value.body.length; 2635 var nc = 0; 2636 var body = new Array(nr); 2637 2638 var style = options.style; 2639 2640 // Horizontal spacing 2641 var pt = 1 / fontMetrics.metrics.ptPerEm; 2642 var arraycolsep = 5 * pt; // \arraycolsep in article.cls 2643 2644 // Vertical spacing 2645 var baselineskip = 12 * pt; // see size10.clo 2646 // Default \arraystretch from lttab.dtx 2647 // TODO(gagern): may get redefined once we have user-defined macros 2648 var arraystretch = utils.deflt(group.value.arraystretch, 1); 2649 var arrayskip = arraystretch * baselineskip; 2650 var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and 2651 var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx 2652 2653 var totalHeight = 0; 2654 for (r = 0; r < group.value.body.length; ++r) { 2655 var inrow = group.value.body[r]; 2656 var height = arstrutHeight; // \@array adds an \@arstrut 2657 var depth = arstrutDepth; // to each tow (via the template) 2658 2659 if (nc < inrow.length) { 2660 nc = inrow.length; 2661 } 2662 2663 var outrow = new Array(inrow.length); 2664 for (c = 0; c < inrow.length; ++c) { 2665 var elt = buildGroup(inrow[c], options); 2666 if (depth < elt.depth) { 2667 depth = elt.depth; 2668 } 2669 if (height < elt.height) { 2670 height = elt.height; 2671 } 2672 outrow[c] = elt; 2673 } 2674 2675 var gap = 0; 2676 if (group.value.rowGaps[r]) { 2677 gap = calculateSize(group.value.rowGaps[r].value, style); 2678 if (gap > 0) { // \@argarraycr 2679 gap += arstrutDepth; 2680 if (depth < gap) { 2681 depth = gap; // \@xargarraycr 2682 } 2683 gap = 0; 2684 } 2685 } 2686 2687 outrow.height = height; 2688 outrow.depth = depth; 2689 totalHeight += height; 2690 outrow.pos = totalHeight; 2691 totalHeight += depth + gap; // \@yargarraycr 2692 body[r] = outrow; 2693 } 2694 2695 var offset = totalHeight / 2 + style.metrics.axisHeight; 2696 var colDescriptions = group.value.cols || []; 2697 var cols = []; 2698 var colSep; 2699 var colDescrNum; 2700 for (c = 0, colDescrNum = 0; 2701 // Continue while either there are more columns or more column 2702 // descriptions, so trailing separators don't get lost. 2703 c < nc || colDescrNum < colDescriptions.length; 2704 ++c, ++colDescrNum) { 2705 2706 var colDescr = colDescriptions[colDescrNum] || {}; 2707 2708 var firstSeparator = true; 2709 while (colDescr.type === "separator") { 2710 // If there is more than one separator in a row, add a space 2711 // between them. 2712 if (!firstSeparator) { 2713 colSep = makeSpan(["arraycolsep"], []); 2714 colSep.style.width = 2715 fontMetrics.metrics.doubleRuleSep + "em"; 2716 cols.push(colSep); 2717 } 2718 2719 if (colDescr.separator === "|") { 2720 var separator = makeSpan( 2721 ["vertical-separator"], 2722 []); 2723 separator.style.height = totalHeight + "em"; 2724 separator.style.verticalAlign = 2725 -(totalHeight - offset) + "em"; 2726 2727 cols.push(separator); 2728 } else { 2729 throw new ParseError( 2730 "Invalid separator type: " + colDescr.separator); 2731 } 2732 2733 colDescrNum++; 2734 colDescr = colDescriptions[colDescrNum] || {}; 2735 firstSeparator = false; 2736 } 2737 2738 if (c >= nc) { 2739 continue; 2740 } 2741 2742 var sepwidth; 2743 if (c > 0 || group.value.hskipBeforeAndAfter) { 2744 sepwidth = utils.deflt(colDescr.pregap, arraycolsep); 2745 if (sepwidth !== 0) { 2746 colSep = makeSpan(["arraycolsep"], []); 2747 colSep.style.width = sepwidth + "em"; 2748 cols.push(colSep); 2749 } 2750 } 2751 2752 var col = []; 2753 for (r = 0; r < nr; ++r) { 2754 var row = body[r]; 2755 var elem = row[c]; 2756 if (!elem) { 2757 continue; 2758 } 2759 var shift = row.pos - offset; 2760 elem.depth = row.depth; 2761 elem.height = row.height; 2762 col.push({type: "elem", elem: elem, shift: shift}); 2763 } 2764 2765 col = buildCommon.makeVList(col, "individualShift", null, options); 2766 col = makeSpan( 2767 ["col-align-" + (colDescr.align || "c")], 2768 [col]); 2769 cols.push(col); 2770 2771 if (c < nc - 1 || group.value.hskipBeforeAndAfter) { 2772 sepwidth = utils.deflt(colDescr.postgap, arraycolsep); 2773 if (sepwidth !== 0) { 2774 colSep = makeSpan(["arraycolsep"], []); 2775 colSep.style.width = sepwidth + "em"; 2776 cols.push(colSep); 2777 } 2778 } 2779 } 2780 body = makeSpan(["mtable"], cols); 2781 return makeSpan(["mord"], [body], options); 2782}; 2783 2784groupTypes.spacing = function(group, options) { 2785 if (group.value === "\\ " || group.value === "\\space" || 2786 group.value === " " || group.value === "~") { 2787 // Spaces are generated by adding an actual space. Each of these 2788 // things has an entry in the symbols table, so these will be turned 2789 // into appropriate outputs. 2790 if (group.mode === "text") { 2791 return buildCommon.makeOrd(group, options, "textord"); 2792 } else { 2793 return makeSpan(["mspace"], 2794 [buildCommon.mathsym(group.value, group.mode, options)], 2795 options); 2796 } 2797 } else { 2798 // Other kinds of spaces are of arbitrary width. We use CSS to 2799 // generate these. 2800 return makeSpan( 2801 ["mspace", 2802 buildCommon.spacingFunctions[group.value].className], 2803 [], options); 2804 } 2805}; 2806 2807groupTypes.llap = function(group, options) { 2808 var inner = makeSpan( 2809 ["inner"], [buildGroup(group.value.body, options.reset())]); 2810 var fix = makeSpan(["fix"], []); 2811 return makeSpan( 2812 ["mord", "llap", options.style.cls()], [inner, fix], options); 2813}; 2814 2815groupTypes.rlap = function(group, options) { 2816 var inner = makeSpan( 2817 ["inner"], [buildGroup(group.value.body, options.reset())]); 2818 var fix = makeSpan(["fix"], []); 2819 return makeSpan( 2820 ["mord", "rlap", options.style.cls()], [inner, fix], options); 2821}; 2822 2823groupTypes.op = function(group, options) { 2824 // Operators are handled in the TeXbook pg. 443-444, rule 13(a). 2825 var supGroup; 2826 var subGroup; 2827 var hasLimits = false; 2828 if (group.type === "supsub") { 2829 // If we have limits, supsub will pass us its group to handle. Pull 2830 // out the superscript and subscript and set the group to the op in 2831 // its base. 2832 supGroup = group.value.sup; 2833 subGroup = group.value.sub; 2834 group = group.value.base; 2835 hasLimits = true; 2836 } 2837 2838 var style = options.style; 2839 2840 // Most operators have a large successor symbol, but these don't. 2841 var noSuccessor = [ 2842 "\\smallint" 2843 ]; 2844 2845 var large = false; 2846 if (style.size === Style.DISPLAY.size && 2847 group.value.symbol && 2848 !utils.contains(noSuccessor, group.value.body)) { 2849 2850 // Most symbol operators get larger in displaystyle (rule 13) 2851 large = true; 2852 } 2853 2854 var base; 2855 var baseShift = 0; 2856 var slant = 0; 2857 if (group.value.symbol) { 2858 // If this is a symbol, create the symbol. 2859 var fontName = large ? "Size2-Regular" : "Size1-Regular"; 2860 base = buildCommon.makeSymbol( 2861 group.value.body, fontName, "math", options, 2862 ["mop", "op-symbol", large ? "large-op" : "small-op"]); 2863 2864 // Shift the symbol so its center lies on the axis (rule 13). It 2865 // appears that our fonts have the centers of the symbols already 2866 // almost on the axis, so these numbers are very small. Note we 2867 // don't actually apply this here, but instead it is used either in 2868 // the vlist creation or separately when there are no limits. 2869 baseShift = (base.height - base.depth) / 2 - 2870 style.metrics.axisHeight * style.sizeMultiplier; 2871 2872 // The slant of the symbol is just its italic correction. 2873 slant = base.italic; 2874 } else if (group.value.value) { 2875 // If this is a list, compose that list. 2876 var inner = buildExpression(group.value.value, options, true); 2877 2878 base = makeSpan(["mop"], inner, options); 2879 } else { 2880 // Otherwise, this is a text operator. Build the text from the 2881 // operator's name. 2882 // TODO(emily): Add a space in the middle of some of these 2883 // operators, like \limsup 2884 var output = []; 2885 for (var i = 1; i < group.value.body.length; i++) { 2886 output.push(buildCommon.mathsym(group.value.body[i], group.mode)); 2887 } 2888 base = makeSpan(["mop"], output, options); 2889 } 2890 2891 if (hasLimits) { 2892 // IE 8 clips \int if it is in a display: inline-block. We wrap it 2893 // in a new span so it is an inline, and works. 2894 base = makeSpan([], [base]); 2895 2896 var supmid; 2897 var supKern; 2898 var submid; 2899 var subKern; 2900 var newOptions; 2901 // We manually have to handle the superscripts and subscripts. This, 2902 // aside from the kern calculations, is copied from supsub. 2903 if (supGroup) { 2904 newOptions = options.withStyle(style.sup()); 2905 var sup = buildGroup(supGroup, newOptions); 2906 supmid = makeSpan([style.reset(), style.sup().cls()], 2907 [sup], newOptions); 2908 2909 supKern = Math.max( 2910 fontMetrics.metrics.bigOpSpacing1, 2911 fontMetrics.metrics.bigOpSpacing3 - sup.depth); 2912 } 2913 2914 if (subGroup) { 2915 newOptions = options.withStyle(style.sub()); 2916 var sub = buildGroup(subGroup, newOptions); 2917 submid = makeSpan([style.reset(), style.sub().cls()], 2918 [sub], newOptions); 2919 2920 subKern = Math.max( 2921 fontMetrics.metrics.bigOpSpacing2, 2922 fontMetrics.metrics.bigOpSpacing4 - sub.height); 2923 } 2924 2925 // Build the final group as a vlist of the possible subscript, base, 2926 // and possible superscript. 2927 var finalGroup; 2928 var top; 2929 var bottom; 2930 if (!supGroup) { 2931 top = base.height - baseShift; 2932 2933 finalGroup = buildCommon.makeVList([ 2934 {type: "kern", size: fontMetrics.metrics.bigOpSpacing5}, 2935 {type: "elem", elem: submid}, 2936 {type: "kern", size: subKern}, 2937 {type: "elem", elem: base} 2938 ], "top", top, options); 2939 2940 // Here, we shift the limits by the slant of the symbol. Note 2941 // that we are supposed to shift the limits by 1/2 of the slant, 2942 // but since we are centering the limits adding a full slant of 2943 // margin will shift by 1/2 that. 2944 finalGroup.children[0].style.marginLeft = -slant + "em"; 2945 } else if (!subGroup) { 2946 bottom = base.depth + baseShift; 2947 2948 finalGroup = buildCommon.makeVList([ 2949 {type: "elem", elem: base}, 2950 {type: "kern", size: supKern}, 2951 {type: "elem", elem: supmid}, 2952 {type: "kern", size: fontMetrics.metrics.bigOpSpacing5} 2953 ], "bottom", bottom, options); 2954 2955 // See comment above about slants 2956 finalGroup.children[1].style.marginLeft = slant + "em"; 2957 } else if (!supGroup && !subGroup) { 2958 // This case probably shouldn't occur (this would mean the 2959 // supsub was sending us a group with no superscript or 2960 // subscript) but be safe. 2961 return base; 2962 } else { 2963 bottom = fontMetrics.metrics.bigOpSpacing5 + 2964 submid.height + submid.depth + 2965 subKern + 2966 base.depth + baseShift; 2967 2968 finalGroup = buildCommon.makeVList([ 2969 {type: "kern", size: fontMetrics.metrics.bigOpSpacing5}, 2970 {type: "elem", elem: submid}, 2971 {type: "kern", size: subKern}, 2972 {type: "elem", elem: base}, 2973 {type: "kern", size: supKern}, 2974 {type: "elem", elem: supmid}, 2975 {type: "kern", size: fontMetrics.metrics.bigOpSpacing5} 2976 ], "bottom", bottom, options); 2977 2978 // See comment above about slants 2979 finalGroup.children[0].style.marginLeft = -slant + "em"; 2980 finalGroup.children[2].style.marginLeft = slant + "em"; 2981 } 2982 2983 return makeSpan(["mop", "op-limits"], [finalGroup], options); 2984 } else { 2985 if (group.value.symbol) { 2986 base.style.top = baseShift + "em"; 2987 } 2988 2989 return base; 2990 } 2991}; 2992 2993groupTypes.mod = function(group, options) { 2994 var inner = []; 2995 2996 if (group.value.modType === "bmod") { 2997 // “\nonscript\mskip-\medmuskip\mkern5mu” 2998 if (!options.style.isTight()) { 2999 inner.push(makeSpan( 3000 ["mspace", "negativemediumspace"], [], options)); 3001 } 3002 inner.push(makeSpan(["mspace", "thickspace"], [], options)); 3003 } else if (options.style.size === Style.DISPLAY.size) { 3004 inner.push(makeSpan(["mspace", "quad"], [], options)); 3005 } else if (group.value.modType === "mod") { 3006 inner.push(makeSpan(["mspace", "twelvemuspace"], [], options)); 3007 } else { 3008 inner.push(makeSpan(["mspace", "eightmuspace"], [], options)); 3009 } 3010 3011 if (group.value.modType === "pod" || group.value.modType === "pmod") { 3012 inner.push(buildCommon.mathsym("(", group.mode)); 3013 } 3014 3015 if (group.value.modType !== "pod") { 3016 var modInner = [ 3017 buildCommon.mathsym("m", group.mode), 3018 buildCommon.mathsym("o", group.mode), 3019 buildCommon.mathsym("d", group.mode)]; 3020 if (group.value.modType === "bmod") { 3021 inner.push(makeSpan(["mbin"], modInner, options)); 3022 // “\mkern5mu\nonscript\mskip-\medmuskip” 3023 inner.push(makeSpan(["mspace", "thickspace"], [], options)); 3024 if (!options.style.isTight()) { 3025 inner.push(makeSpan( 3026 ["mspace", "negativemediumspace"], [], options)); 3027 } 3028 } else { 3029 Array.prototype.push.apply(inner, modInner); 3030 inner.push(makeSpan(["mspace", "sixmuspace"], [], options)); 3031 } 3032 } 3033 3034 if (group.value.value) { 3035 Array.prototype.push.apply(inner, 3036 buildExpression(group.value.value, options, false)); 3037 } 3038 3039 if (group.value.modType === "pod" || group.value.modType === "pmod") { 3040 inner.push(buildCommon.mathsym(")", group.mode)); 3041 } 3042 3043 return buildCommon.makeFragment(inner); 3044}; 3045 3046groupTypes.katex = function(group, options) { 3047 // The KaTeX logo. The offsets for the K and a were chosen to look 3048 // good, but the offsets for the T, E, and X were taken from the 3049 // definition of \TeX in TeX (see TeXbook pg. 356) 3050 var k = makeSpan( 3051 ["k"], [buildCommon.mathsym("K", group.mode)], options); 3052 var a = makeSpan( 3053 ["a"], [buildCommon.mathsym("A", group.mode)], options); 3054 3055 a.height = (a.height + 0.2) * 0.75; 3056 a.depth = (a.height - 0.2) * 0.75; 3057 3058 var t = makeSpan( 3059 ["t"], [buildCommon.mathsym("T", group.mode)], options); 3060 var e = makeSpan( 3061 ["e"], [buildCommon.mathsym("E", group.mode)], options); 3062 3063 e.height = (e.height - 0.2155); 3064 e.depth = (e.depth + 0.2155); 3065 3066 var x = makeSpan( 3067 ["x"], [buildCommon.mathsym("X", group.mode)], options); 3068 3069 return makeSpan( 3070 ["mord", "katex-logo"], [k, a, t, e, x], options); 3071}; 3072 3073groupTypes.overline = function(group, options) { 3074 // Overlines are handled in the TeXbook pg 443, Rule 9. 3075 var style = options.style; 3076 3077 // Build the inner group in the cramped style. 3078 var innerGroup = buildGroup(group.value.body, 3079 options.withStyle(style.cramp())); 3080 3081 var ruleWidth = fontMetrics.metrics.defaultRuleThickness / 3082 style.sizeMultiplier; 3083 3084 // Create the line above the body 3085 var line = makeSpan( 3086 [style.reset(), Style.TEXT.cls(), "overline-line"]); 3087 line.height = ruleWidth; 3088 line.maxFontSize = 1.0; 3089 3090 // Generate the vlist, with the appropriate kerns 3091 var vlist = buildCommon.makeVList([ 3092 {type: "elem", elem: innerGroup}, 3093 {type: "kern", size: 3 * ruleWidth}, 3094 {type: "elem", elem: line}, 3095 {type: "kern", size: ruleWidth} 3096 ], "firstBaseline", null, options); 3097 3098 return makeSpan(["mord", "overline"], [vlist], options); 3099}; 3100 3101groupTypes.underline = function(group, options) { 3102 // Underlines are handled in the TeXbook pg 443, Rule 10. 3103 var style = options.style; 3104 3105 // Build the inner group. 3106 var innerGroup = buildGroup(group.value.body, options); 3107 3108 var ruleWidth = fontMetrics.metrics.defaultRuleThickness / 3109 style.sizeMultiplier; 3110 3111 // Create the line above the body 3112 var line = makeSpan([style.reset(), Style.TEXT.cls(), "underline-line"]); 3113 line.height = ruleWidth; 3114 line.maxFontSize = 1.0; 3115 3116 // Generate the vlist, with the appropriate kerns 3117 var vlist = buildCommon.makeVList([ 3118 {type: "kern", size: ruleWidth}, 3119 {type: "elem", elem: line}, 3120 {type: "kern", size: 3 * ruleWidth}, 3121 {type: "elem", elem: innerGroup} 3122 ], "top", innerGroup.height, options); 3123 3124 return makeSpan(["mord", "underline"], [vlist], options); 3125}; 3126 3127groupTypes.sqrt = function(group, options) { 3128 // Square roots are handled in the TeXbook pg. 443, Rule 11. 3129 var style = options.style; 3130 3131 // First, we do the same steps as in overline to build the inner group 3132 // and line 3133 var inner = buildGroup(group.value.body, options.withStyle(style.cramp())); 3134 3135 var ruleWidth = fontMetrics.metrics.defaultRuleThickness / 3136 style.sizeMultiplier; 3137 3138 var line = makeSpan( 3139 [style.reset(), Style.TEXT.cls(), "sqrt-line"], [], 3140 options); 3141 line.height = ruleWidth; 3142 line.maxFontSize = 1.0; 3143 3144 var phi = ruleWidth; 3145 if (style.id < Style.TEXT.id) { 3146 phi = style.metrics.xHeight; 3147 } 3148 3149 // Calculate the clearance between the body and line 3150 var lineClearance = ruleWidth + phi / 4; 3151 3152 var innerHeight = (inner.height + inner.depth) * style.sizeMultiplier; 3153 var minDelimiterHeight = innerHeight + lineClearance + ruleWidth; 3154 3155 // Create a \surd delimiter of the required minimum size 3156 var delim = makeSpan(["sqrt-sign"], [ 3157 delimiter.customSizedDelim("\\surd", minDelimiterHeight, 3158 false, options, group.mode)], 3159 options); 3160 3161 var delimDepth = (delim.height + delim.depth) - ruleWidth; 3162 3163 // Adjust the clearance based on the delimiter size 3164 if (delimDepth > inner.height + inner.depth + lineClearance) { 3165 lineClearance = 3166 (lineClearance + delimDepth - inner.height - inner.depth) / 2; 3167 } 3168 3169 // Shift the delimiter so that its top lines up with the top of the line 3170 var delimShift = -(inner.height + lineClearance + ruleWidth) + delim.height; 3171 delim.style.top = delimShift + "em"; 3172 delim.height -= delimShift; 3173 delim.depth += delimShift; 3174 3175 // We add a special case here, because even when `inner` is empty, we 3176 // still get a line. So, we use a simple heuristic to decide if we 3177 // should omit the body entirely. (note this doesn't work for something 3178 // like `\sqrt{\rlap{x}}`, but if someone is doing that they deserve for 3179 // it not to work. 3180 var body; 3181 if (inner.height === 0 && inner.depth === 0) { 3182 body = makeSpan(); 3183 } else { 3184 body = buildCommon.makeVList([ 3185 {type: "elem", elem: inner}, 3186 {type: "kern", size: lineClearance}, 3187 {type: "elem", elem: line}, 3188 {type: "kern", size: ruleWidth} 3189 ], "firstBaseline", null, options); 3190 } 3191 3192 if (!group.value.index) { 3193 return makeSpan(["mord", "sqrt"], [delim, body], options); 3194 } else { 3195 // Handle the optional root index 3196 3197 // The index is always in scriptscript style 3198 var newOptions = options.withStyle(Style.SCRIPTSCRIPT); 3199 var root = buildGroup(group.value.index, newOptions); 3200 var rootWrap = makeSpan( 3201 [style.reset(), Style.SCRIPTSCRIPT.cls()], 3202 [root], 3203 newOptions); 3204 3205 // Figure out the height and depth of the inner part 3206 var innerRootHeight = Math.max(delim.height, body.height); 3207 var innerRootDepth = Math.max(delim.depth, body.depth); 3208 3209 // The amount the index is shifted by. This is taken from the TeX 3210 // source, in the definition of `\r@@t`. 3211 var toShift = 0.6 * (innerRootHeight - innerRootDepth); 3212 3213 // Build a VList with the superscript shifted up correctly 3214 var rootVList = buildCommon.makeVList( 3215 [{type: "elem", elem: rootWrap}], 3216 "shift", -toShift, options); 3217 // Add a class surrounding it so we can add on the appropriate 3218 // kerning 3219 var rootVListWrap = makeSpan(["root"], [rootVList]); 3220 3221 return makeSpan(["mord", "sqrt"], 3222 [rootVListWrap, delim, body], options); 3223 } 3224}; 3225 3226groupTypes.sizing = function(group, options) { 3227 // Handle sizing operators like \Huge. Real TeX doesn't actually allow 3228 // these functions inside of math expressions, so we do some special 3229 // handling. 3230 var inner = buildExpression(group.value.value, 3231 options.withSize(group.value.size), false); 3232 3233 // Compute the correct maxFontSize. 3234 var style = options.style; 3235 var fontSize = buildCommon.sizingMultiplier[group.value.size]; 3236 fontSize = fontSize * style.sizeMultiplier; 3237 3238 // Add size-resetting classes to the inner list and set maxFontSize 3239 // manually. Handle nested size changes. 3240 for (var i = 0; i < inner.length; i++) { 3241 var pos = utils.indexOf(inner[i].classes, "sizing"); 3242 if (pos < 0) { 3243 inner[i].classes.push("sizing", "reset-" + options.size, 3244 group.value.size, style.cls()); 3245 inner[i].maxFontSize = fontSize; 3246 } else if (inner[i].classes[pos + 1] === "reset-" + group.value.size) { 3247 // This is a nested size change: e.g., inner[i] is the "b" in 3248 // `\Huge a \small b`. Override the old size (the `reset-` class) 3249 // but not the new size. 3250 inner[i].classes[pos + 1] = "reset-" + options.size; 3251 } 3252 } 3253 3254 return buildCommon.makeFragment(inner); 3255}; 3256 3257groupTypes.styling = function(group, options) { 3258 // Style changes are handled in the TeXbook on pg. 442, Rule 3. 3259 3260 // Figure out what style we're changing to. 3261 var styleMap = { 3262 "display": Style.DISPLAY, 3263 "text": Style.TEXT, 3264 "script": Style.SCRIPT, 3265 "scriptscript": Style.SCRIPTSCRIPT 3266 }; 3267 3268 var newStyle = styleMap[group.value.style]; 3269 var newOptions = options.withStyle(newStyle); 3270 3271 // Build the inner expression in the new style. 3272 var inner = buildExpression( 3273 group.value.value, newOptions, false); 3274 3275 // Add style-resetting classes to the inner list. Handle nested changes. 3276 for (var i = 0; i < inner.length; i++) { 3277 var pos = utils.indexOf(inner[i].classes, newStyle.reset()); 3278 if (pos < 0) { 3279 inner[i].classes.push(options.style.reset(), newStyle.cls()); 3280 } else { 3281 // This is a nested style change, as `\textstyle a\scriptstyle b`. 3282 // Only override the old style (the reset class). 3283 inner[i].classes[pos] = options.style.reset(); 3284 } 3285 } 3286 3287 return new buildCommon.makeFragment(inner); 3288}; 3289 3290groupTypes.font = function(group, options) { 3291 var font = group.value.font; 3292 return buildGroup(group.value.body, options.withFont(font)); 3293}; 3294 3295groupTypes.delimsizing = function(group, options) { 3296 var delim = group.value.value; 3297 3298 if (delim === ".") { 3299 // Empty delimiters still count as elements, even though they don't 3300 // show anything. 3301 return makeSpan([group.value.mclass]); 3302 } 3303 3304 // Use delimiter.sizedDelim to generate the delimiter. 3305 return delimiter.sizedDelim( 3306 delim, group.value.size, options, group.mode, 3307 [group.value.mclass]); 3308}; 3309 3310groupTypes.leftright = function(group, options) { 3311 // Build the inner expression 3312 var inner = buildExpression(group.value.body, options.reset(), true); 3313 3314 var innerHeight = 0; 3315 var innerDepth = 0; 3316 var hadMiddle = false; 3317 3318 // Calculate its height and depth 3319 for (var i = 0; i < inner.length; i++) { 3320 if (inner[i].isMiddle) { 3321 hadMiddle = true; 3322 } else { 3323 innerHeight = Math.max(inner[i].height, innerHeight); 3324 innerDepth = Math.max(inner[i].depth, innerDepth); 3325 } 3326 } 3327 3328 var style = options.style; 3329 3330 // The size of delimiters is the same, regardless of what style we are 3331 // in. Thus, to correctly calculate the size of delimiter we need around 3332 // a group, we scale down the inner size based on the size. 3333 innerHeight *= style.sizeMultiplier; 3334 innerDepth *= style.sizeMultiplier; 3335 3336 var leftDelim; 3337 if (group.value.left === ".") { 3338 // Empty delimiters in \left and \right make null delimiter spaces. 3339 leftDelim = makeNullDelimiter(options, ["mopen"]); 3340 } else { 3341 // Otherwise, use leftRightDelim to generate the correct sized 3342 // delimiter. 3343 leftDelim = delimiter.leftRightDelim( 3344 group.value.left, innerHeight, innerDepth, options, 3345 group.mode, ["mopen"]); 3346 } 3347 // Add it to the beginning of the expression 3348 inner.unshift(leftDelim); 3349 3350 // Handle middle delimiters 3351 if (hadMiddle) { 3352 for (i = 1; i < inner.length; i++) { 3353 if (inner[i].isMiddle) { 3354 // Apply the options that were active when \middle was called 3355 inner[i] = delimiter.leftRightDelim( 3356 inner[i].isMiddle.value, innerHeight, innerDepth, 3357 inner[i].isMiddle.options, group.mode, []); 3358 } 3359 } 3360 } 3361 3362 var rightDelim; 3363 // Same for the right delimiter 3364 if (group.value.right === ".") { 3365 rightDelim = makeNullDelimiter(options, ["mclose"]); 3366 } else { 3367 rightDelim = delimiter.leftRightDelim( 3368 group.value.right, innerHeight, innerDepth, options, 3369 group.mode, ["mclose"]); 3370 } 3371 // Add it to the end of the expression. 3372 inner.push(rightDelim); 3373 3374 return makeSpan( 3375 ["minner", style.cls()], inner, options); 3376}; 3377 3378groupTypes.middle = function(group, options) { 3379 var middleDelim; 3380 if (group.value.value === ".") { 3381 middleDelim = makeNullDelimiter(options, []); 3382 } else { 3383 middleDelim = delimiter.sizedDelim( 3384 group.value.value, 1, options, 3385 group.mode, []); 3386 middleDelim.isMiddle = {value: group.value.value, options: options}; 3387 } 3388 return middleDelim; 3389}; 3390 3391groupTypes.rule = function(group, options) { 3392 // Make an empty span for the rule 3393 var rule = makeSpan(["mord", "rule"], [], options); 3394 var style = options.style; 3395 3396 // Calculate the shift, width, and height of the rule, and account for units 3397 var shift = 0; 3398 if (group.value.shift) { 3399 shift = calculateSize(group.value.shift, style); 3400 } 3401 3402 var width = calculateSize(group.value.width, style); 3403 var height = calculateSize(group.value.height, style); 3404 3405 // The sizes of rules are absolute, so make it larger if we are in a 3406 // smaller style. 3407 shift /= style.sizeMultiplier; 3408 width /= style.sizeMultiplier; 3409 height /= style.sizeMultiplier; 3410 3411 // Style the rule to the right size 3412 rule.style.borderRightWidth = width + "em"; 3413 rule.style.borderTopWidth = height + "em"; 3414 rule.style.bottom = shift + "em"; 3415 3416 // Record the height and width 3417 rule.width = width; 3418 rule.height = height + shift; 3419 rule.depth = -shift; 3420 3421 return rule; 3422}; 3423 3424groupTypes.kern = function(group, options) { 3425 // Make an empty span for the rule 3426 var rule = makeSpan(["mord", "rule"], [], options); 3427 var style = options.style; 3428 3429 var dimension = 0; 3430 if (group.value.dimension) { 3431 dimension = calculateSize(group.value.dimension, style); 3432 } 3433 3434 dimension /= style.sizeMultiplier; 3435 3436 rule.style.marginLeft = dimension + "em"; 3437 3438 return rule; 3439}; 3440 3441groupTypes.accent = function(group, options) { 3442 // Accents are handled in the TeXbook pg. 443, rule 12. 3443 var base = group.value.base; 3444 var style = options.style; 3445 3446 var supsubGroup; 3447 if (group.type === "supsub") { 3448 // If our base is a character box, and we have superscripts and 3449 // subscripts, the supsub will defer to us. In particular, we want 3450 // to attach the superscripts and subscripts to the inner body (so 3451 // that the position of the superscripts and subscripts won't be 3452 // affected by the height of the accent). We accomplish this by 3453 // sticking the base of the accent into the base of the supsub, and 3454 // rendering that, while keeping track of where the accent is. 3455 3456 // The supsub group is the group that was passed in 3457 var supsub = group; 3458 // The real accent group is the base of the supsub group 3459 group = supsub.value.base; 3460 // The character box is the base of the accent group 3461 base = group.value.base; 3462 // Stick the character box into the base of the supsub group 3463 supsub.value.base = base; 3464 3465 // Rerender the supsub group with its new base, and store that 3466 // result. 3467 supsubGroup = buildGroup( 3468 supsub, options.reset()); 3469 } 3470 3471 // Build the base group 3472 var body = buildGroup( 3473 base, options.withStyle(style.cramp())); 3474 3475 // Calculate the skew of the accent. This is based on the line "If the 3476 // nucleus is not a single character, let s = 0; otherwise set s to the 3477 // kern amount for the nucleus followed by the \skewchar of its font." 3478 // Note that our skew metrics are just the kern between each character 3479 // and the skewchar. 3480 var skew; 3481 if (isCharacterBox(base)) { 3482 // If the base is a character box, then we want the skew of the 3483 // innermost character. To do that, we find the innermost character: 3484 var baseChar = getBaseElem(base); 3485 // Then, we render its group to get the symbol inside it 3486 var baseGroup = buildGroup( 3487 baseChar, options.withStyle(style.cramp())); 3488 // Finally, we pull the skew off of the symbol. 3489 skew = baseGroup.skew; 3490 // Note that we now throw away baseGroup, because the layers we 3491 // removed with getBaseElem might contain things like \color which 3492 // we can't get rid of. 3493 // TODO(emily): Find a better way to get the skew 3494 } else { 3495 skew = 0; 3496 } 3497 3498 // calculate the amount of space between the body and the accent 3499 var clearance = Math.min( 3500 body.height, 3501 style.metrics.xHeight); 3502 3503 // Build the accent 3504 var accent = buildCommon.makeSymbol( 3505 group.value.accent, "Main-Regular", "math", options); 3506 // Remove the italic correction of the accent, because it only serves to 3507 // shift the accent over to a place we don't want. 3508 accent.italic = 0; 3509 3510 // The \vec character that the fonts use is a combining character, and 3511 // thus shows up much too far to the left. To account for this, we add a 3512 // specific class which shifts the accent over to where we want it. 3513 // TODO(emily): Fix this in a better way, like by changing the font 3514 var vecClass = group.value.accent === "\\vec" ? "accent-vec" : null; 3515 3516 var accentBody = makeSpan(["accent-body", vecClass], [ 3517 makeSpan([], [accent])]); 3518 3519 accentBody = buildCommon.makeVList([ 3520 {type: "elem", elem: body}, 3521 {type: "kern", size: -clearance}, 3522 {type: "elem", elem: accentBody} 3523 ], "firstBaseline", null, options); 3524 3525 // Shift the accent over by the skew. Note we shift by twice the skew 3526 // because we are centering the accent, so by adding 2*skew to the left, 3527 // we shift it to the right by 1*skew. 3528 accentBody.children[1].style.marginLeft = 2 * skew + "em"; 3529 3530 var accentWrap = makeSpan(["mord", "accent"], [accentBody], options); 3531 3532 if (supsubGroup) { 3533 // Here, we replace the "base" child of the supsub with our newly 3534 // generated accent. 3535 supsubGroup.children[0] = accentWrap; 3536 3537 // Since we don't rerun the height calculation after replacing the 3538 // accent, we manually recalculate height. 3539 supsubGroup.height = Math.max(accentWrap.height, supsubGroup.height); 3540 3541 // Accents should always be ords, even when their innards are not. 3542 supsubGroup.classes[0] = "mord"; 3543 3544 return supsubGroup; 3545 } else { 3546 return accentWrap; 3547 } 3548}; 3549 3550groupTypes.phantom = function(group, options) { 3551 var elements = buildExpression( 3552 group.value.value, 3553 options.withPhantom(), 3554 false 3555 ); 3556 3557 // \phantom isn't supposed to affect the elements it contains. 3558 // See "color" for more details. 3559 return new buildCommon.makeFragment(elements); 3560}; 3561 3562groupTypes.mclass = function(group, options) { 3563 var elements = buildExpression(group.value.value, options, true); 3564 3565 return makeSpan([group.value.mclass], elements, options); 3566}; 3567 3568/** 3569 * buildGroup is the function that takes a group and calls the correct groupType 3570 * function for it. It also handles the interaction of size and style changes 3571 * between parents and children. 3572 */ 3573var buildGroup = function(group, options) { 3574 if (!group) { 3575 return makeSpan(); 3576 } 3577 3578 if (groupTypes[group.type]) { 3579 // Call the groupTypes function 3580 var groupNode = groupTypes[group.type](group, options); 3581 var multiplier; 3582 3583 // If the style changed between the parent and the current group, 3584 // account for the size difference 3585 if (options.style !== options.parentStyle) { 3586 multiplier = options.style.sizeMultiplier / 3587 options.parentStyle.sizeMultiplier; 3588 3589 groupNode.height *= multiplier; 3590 groupNode.depth *= multiplier; 3591 } 3592 3593 // If the size changed between the parent and the current group, account 3594 // for that size difference. 3595 if (options.size !== options.parentSize) { 3596 multiplier = buildCommon.sizingMultiplier[options.size] / 3597 buildCommon.sizingMultiplier[options.parentSize]; 3598 3599 groupNode.height *= multiplier; 3600 groupNode.depth *= multiplier; 3601 } 3602 3603 return groupNode; 3604 } else { 3605 throw new ParseError( 3606 "Got group of unknown type: '" + group.type + "'"); 3607 } 3608}; 3609 3610/** 3611 * Take an entire parse tree, and build it into an appropriate set of HTML 3612 * nodes. 3613 */ 3614var buildHTML = function(tree, options) { 3615 // buildExpression is destructive, so we need to make a clone 3616 // of the incoming tree so that it isn't accidentally changed 3617 tree = JSON.parse(JSON.stringify(tree)); 3618 3619 // Build the expression contained in the tree 3620 var expression = buildExpression(tree, options, true); 3621 var body = makeSpan(["base", options.style.cls()], expression, options); 3622 3623 // Add struts, which ensure that the top of the HTML element falls at the 3624 // height of the expression, and the bottom of the HTML element falls at the 3625 // depth of the expression. 3626 var topStrut = makeSpan(["strut"]); 3627 var bottomStrut = makeSpan(["strut", "bottom"]); 3628 3629 topStrut.style.height = body.height + "em"; 3630 bottomStrut.style.height = (body.height + body.depth) + "em"; 3631 // We'd like to use `vertical-align: top` but in IE 9 this lowers the 3632 // baseline of the box to the bottom of this strut (instead staying in the 3633 // normal place) so we use an absolute value for vertical-align instead 3634 bottomStrut.style.verticalAlign = -body.depth + "em"; 3635 3636 // Wrap the struts and body together 3637 var htmlNode = makeSpan(["katex-html"], [topStrut, bottomStrut, body]); 3638 3639 htmlNode.setAttribute("aria-hidden", "true"); 3640 3641 return htmlNode; 3642}; 3643 3644module.exports = buildHTML; 3645 3646},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./delimiter":14,"./domTree":15,"./fontMetrics":17,"./utils":25}],12:[function(require,module,exports){ 3647/** 3648 * This file converts a parse tree into a cooresponding MathML tree. The main 3649 * entry point is the `buildMathML` function, which takes a parse tree from the 3650 * parser. 3651 */ 3652 3653var buildCommon = require("./buildCommon"); 3654var fontMetrics = require("./fontMetrics"); 3655var mathMLTree = require("./mathMLTree"); 3656var ParseError = require("./ParseError"); 3657var symbols = require("./symbols"); 3658var utils = require("./utils"); 3659 3660var makeSpan = buildCommon.makeSpan; 3661var fontMap = buildCommon.fontMap; 3662 3663/** 3664 * Takes a symbol and converts it into a MathML text node after performing 3665 * optional replacement from symbols.js. 3666 */ 3667var makeText = function(text, mode) { 3668 if (symbols[mode][text] && symbols[mode][text].replace) { 3669 text = symbols[mode][text].replace; 3670 } 3671 3672 return new mathMLTree.TextNode(text); 3673}; 3674 3675/** 3676 * Returns the math variant as a string or null if none is required. 3677 */ 3678var getVariant = function(group, options) { 3679 var font = options.font; 3680 if (!font) { 3681 return null; 3682 } 3683 3684 var mode = group.mode; 3685 if (font === "mathit") { 3686 return "italic"; 3687 } 3688 3689 var value = group.value; 3690 if (utils.contains(["\\imath", "\\jmath"], value)) { 3691 return null; 3692 } 3693 3694 if (symbols[mode][value] && symbols[mode][value].replace) { 3695 value = symbols[mode][value].replace; 3696 } 3697 3698 var fontName = fontMap[font].fontName; 3699 if (fontMetrics.getCharacterMetrics(value, fontName)) { 3700 return fontMap[options.font].variant; 3701 } 3702 3703 return null; 3704}; 3705 3706/** 3707 * Functions for handling the different types of groups found in the parse 3708 * tree. Each function should take a parse group and return a MathML node. 3709 */ 3710var groupTypes = {}; 3711 3712groupTypes.mathord = function(group, options) { 3713 var node = new mathMLTree.MathNode( 3714 "mi", 3715 [makeText(group.value, group.mode)]); 3716 3717 var variant = getVariant(group, options); 3718 if (variant) { 3719 node.setAttribute("mathvariant", variant); 3720 } 3721 return node; 3722}; 3723 3724groupTypes.textord = function(group, options) { 3725 var text = makeText(group.value, group.mode); 3726 3727 var variant = getVariant(group, options) || "normal"; 3728 3729 var node; 3730 if (/[0-9]/.test(group.value)) { 3731 // TODO(kevinb) merge adjacent <mn> nodes 3732 // do it as a post processing step 3733 node = new mathMLTree.MathNode("mn", [text]); 3734 if (options.font) { 3735 node.setAttribute("mathvariant", variant); 3736 } 3737 } else { 3738 node = new mathMLTree.MathNode("mi", [text]); 3739 node.setAttribute("mathvariant", variant); 3740 } 3741 3742 return node; 3743}; 3744 3745groupTypes.bin = function(group) { 3746 var node = new mathMLTree.MathNode( 3747 "mo", [makeText(group.value, group.mode)]); 3748 3749 return node; 3750}; 3751 3752groupTypes.rel = function(group) { 3753 var node = new mathMLTree.MathNode( 3754 "mo", [makeText(group.value, group.mode)]); 3755 3756 return node; 3757}; 3758 3759groupTypes.open = function(group) { 3760 var node = new mathMLTree.MathNode( 3761 "mo", [makeText(group.value, group.mode)]); 3762 3763 return node; 3764}; 3765 3766groupTypes.close = function(group) { 3767 var node = new mathMLTree.MathNode( 3768 "mo", [makeText(group.value, group.mode)]); 3769 3770 return node; 3771}; 3772 3773groupTypes.inner = function(group) { 3774 var node = new mathMLTree.MathNode( 3775 "mo", [makeText(group.value, group.mode)]); 3776 3777 return node; 3778}; 3779 3780groupTypes.punct = function(group) { 3781 var node = new mathMLTree.MathNode( 3782 "mo", [makeText(group.value, group.mode)]); 3783 3784 node.setAttribute("separator", "true"); 3785 3786 return node; 3787}; 3788 3789groupTypes.ordgroup = function(group, options) { 3790 var inner = buildExpression(group.value, options); 3791 3792 var node = new mathMLTree.MathNode("mrow", inner); 3793 3794 return node; 3795}; 3796 3797groupTypes.text = function(group, options) { 3798 var inner = buildExpression(group.value.body, options); 3799 3800 var node = new mathMLTree.MathNode("mtext", inner); 3801 3802 return node; 3803}; 3804 3805groupTypes.color = function(group, options) { 3806 var inner = buildExpression(group.value.value, options); 3807 3808 var node = new mathMLTree.MathNode("mstyle", inner); 3809 3810 node.setAttribute("mathcolor", group.value.color); 3811 3812 return node; 3813}; 3814 3815groupTypes.supsub = function(group, options) { 3816 var children = [buildGroup(group.value.base, options)]; 3817 3818 if (group.value.sub) { 3819 children.push(buildGroup(group.value.sub, options)); 3820 } 3821 3822 if (group.value.sup) { 3823 children.push(buildGroup(group.value.sup, options)); 3824 } 3825 3826 var nodeType; 3827 if (!group.value.sub) { 3828 nodeType = "msup"; 3829 } else if (!group.value.sup) { 3830 nodeType = "msub"; 3831 } else { 3832 nodeType = "msubsup"; 3833 } 3834 3835 var node = new mathMLTree.MathNode(nodeType, children); 3836 3837 return node; 3838}; 3839 3840groupTypes.genfrac = function(group, options) { 3841 var node = new mathMLTree.MathNode( 3842 "mfrac", 3843 [buildGroup(group.value.numer, options), 3844 buildGroup(group.value.denom, options)]); 3845 3846 if (!group.value.hasBarLine) { 3847 node.setAttribute("linethickness", "0px"); 3848 } 3849 3850 if (group.value.leftDelim != null || group.value.rightDelim != null) { 3851 var withDelims = []; 3852 3853 if (group.value.leftDelim != null) { 3854 var leftOp = new mathMLTree.MathNode( 3855 "mo", [new mathMLTree.TextNode(group.value.leftDelim)]); 3856 3857 leftOp.setAttribute("fence", "true"); 3858 3859 withDelims.push(leftOp); 3860 } 3861 3862 withDelims.push(node); 3863 3864 if (group.value.rightDelim != null) { 3865 var rightOp = new mathMLTree.MathNode( 3866 "mo", [new mathMLTree.TextNode(group.value.rightDelim)]); 3867 3868 rightOp.setAttribute("fence", "true"); 3869 3870 withDelims.push(rightOp); 3871 } 3872 3873 var outerNode = new mathMLTree.MathNode("mrow", withDelims); 3874 3875 return outerNode; 3876 } 3877 3878 return node; 3879}; 3880 3881groupTypes.array = function(group, options) { 3882 return new mathMLTree.MathNode( 3883 "mtable", group.value.body.map(function(row) { 3884 return new mathMLTree.MathNode( 3885 "mtr", row.map(function(cell) { 3886 return new mathMLTree.MathNode( 3887 "mtd", [buildGroup(cell, options)]); 3888 })); 3889 })); 3890}; 3891 3892groupTypes.sqrt = function(group, options) { 3893 var node; 3894 if (group.value.index) { 3895 node = new mathMLTree.MathNode( 3896 "mroot", [ 3897 buildGroup(group.value.body, options), 3898 buildGroup(group.value.index, options) 3899 ]); 3900 } else { 3901 node = new mathMLTree.MathNode( 3902 "msqrt", [buildGroup(group.value.body, options)]); 3903 } 3904 3905 return node; 3906}; 3907 3908groupTypes.leftright = function(group, options) { 3909 var inner = buildExpression(group.value.body, options); 3910 3911 if (group.value.left !== ".") { 3912 var leftNode = new mathMLTree.MathNode( 3913 "mo", [makeText(group.value.left, group.mode)]); 3914 3915 leftNode.setAttribute("fence", "true"); 3916 3917 inner.unshift(leftNode); 3918 } 3919 3920 if (group.value.right !== ".") { 3921 var rightNode = new mathMLTree.MathNode( 3922 "mo", [makeText(group.value.right, group.mode)]); 3923 3924 rightNode.setAttribute("fence", "true"); 3925 3926 inner.push(rightNode); 3927 } 3928 3929 var outerNode = new mathMLTree.MathNode("mrow", inner); 3930 3931 return outerNode; 3932}; 3933 3934groupTypes.middle = function(group, options) { 3935 var middleNode = new mathMLTree.MathNode( 3936 "mo", [makeText(group.value.middle, group.mode)]); 3937 middleNode.setAttribute("fence", "true"); 3938 return middleNode; 3939}; 3940 3941groupTypes.accent = function(group, options) { 3942 var accentNode = new mathMLTree.MathNode( 3943 "mo", [makeText(group.value.accent, group.mode)]); 3944 3945 var node = new mathMLTree.MathNode( 3946 "mover", 3947 [buildGroup(group.value.base, options), 3948 accentNode]); 3949 3950 node.setAttribute("accent", "true"); 3951 3952 return node; 3953}; 3954 3955groupTypes.spacing = function(group) { 3956 var node; 3957 3958 if (group.value === "\\ " || group.value === "\\space" || 3959 group.value === " " || group.value === "~") { 3960 node = new mathMLTree.MathNode( 3961 "mtext", [new mathMLTree.TextNode("\u00a0")]); 3962 } else { 3963 node = new mathMLTree.MathNode("mspace"); 3964 3965 node.setAttribute( 3966 "width", buildCommon.spacingFunctions[group.value].size); 3967 } 3968 3969 return node; 3970}; 3971 3972groupTypes.op = function(group, options) { 3973 var node; 3974 3975 // TODO(emily): handle big operators using the `largeop` attribute 3976 3977 if (group.value.symbol) { 3978 // This is a symbol. Just add the symbol. 3979 node = new mathMLTree.MathNode( 3980 "mo", [makeText(group.value.body, group.mode)]); 3981 } else if (group.value.value) { 3982 // This is an operator with children. Add them. 3983 node = new mathMLTree.MathNode( 3984 "mo", buildExpression(group.value.value, options)); 3985 } else { 3986 // This is a text operator. Add all of the characters from the 3987 // operator's name. 3988 // TODO(emily): Add a space in the middle of some of these 3989 // operators, like \limsup. 3990 node = new mathMLTree.MathNode( 3991 "mi", [new mathMLTree.TextNode(group.value.body.slice(1))]); 3992 } 3993 3994 return node; 3995}; 3996 3997groupTypes.mod = function(group, options) { 3998 var inner = []; 3999 4000 if (group.value.modType === "pod" || group.value.modType === "pmod") { 4001 inner.push(new mathMLTree.MathNode( 4002 "mo", [makeText("(", group.mode)])); 4003 } 4004 if (group.value.modType !== "pod") { 4005 inner.push(new mathMLTree.MathNode( 4006 "mo", [makeText("mod", group.mode)])); 4007 } 4008 if (group.value.value) { 4009 var space = new mathMLTree.MathNode("mspace"); 4010 space.setAttribute("width", "0.333333em"); 4011 inner.push(space); 4012 inner = inner.concat(buildExpression(group.value.value, options)); 4013 } 4014 if (group.value.modType === "pod" || group.value.modType === "pmod") { 4015 inner.push(new mathMLTree.MathNode( 4016 "mo", [makeText(")", group.mode)])); 4017 } 4018 4019 return new mathMLTree.MathNode("mo", inner); 4020}; 4021 4022groupTypes.katex = function(group) { 4023 var node = new mathMLTree.MathNode( 4024 "mtext", [new mathMLTree.TextNode("KaTeX")]); 4025 4026 return node; 4027}; 4028 4029groupTypes.font = function(group, options) { 4030 var font = group.value.font; 4031 return buildGroup(group.value.body, options.withFont(font)); 4032}; 4033 4034groupTypes.delimsizing = function(group) { 4035 var children = []; 4036 4037 if (group.value.value !== ".") { 4038 children.push(makeText(group.value.value, group.mode)); 4039 } 4040 4041 var node = new mathMLTree.MathNode("mo", children); 4042 4043 if (group.value.mclass === "mopen" || 4044 group.value.mclass === "mclose") { 4045 // Only some of the delimsizing functions act as fences, and they 4046 // return "mopen" or "mclose" mclass. 4047 node.setAttribute("fence", "true"); 4048 } else { 4049 // Explicitly disable fencing if it's not a fence, to override the 4050 // defaults. 4051 node.setAttribute("fence", "false"); 4052 } 4053 4054 return node; 4055}; 4056 4057groupTypes.styling = function(group, options) { 4058 var inner = buildExpression(group.value.value, options); 4059 4060 var node = new mathMLTree.MathNode("mstyle", inner); 4061 4062 var styleAttributes = { 4063 "display": ["0", "true"], 4064 "text": ["0", "false"], 4065 "script": ["1", "false"], 4066 "scriptscript": ["2", "false"] 4067 }; 4068 4069 var attr = styleAttributes[group.value.style]; 4070 4071 node.setAttribute("scriptlevel", attr[0]); 4072 node.setAttribute("displaystyle", attr[1]); 4073 4074 return node; 4075}; 4076 4077groupTypes.sizing = function(group, options) { 4078 var inner = buildExpression(group.value.value, options); 4079 4080 var node = new mathMLTree.MathNode("mstyle", inner); 4081 4082 // TODO(emily): This doesn't produce the correct size for nested size 4083 // changes, because we don't keep state of what style we're currently 4084 // in, so we can't reset the size to normal before changing it. Now 4085 // that we're passing an options parameter we should be able to fix 4086 // this. 4087 node.setAttribute( 4088 "mathsize", buildCommon.sizingMultiplier[group.value.size] + "em"); 4089 4090 return node; 4091}; 4092 4093groupTypes.overline = function(group, options) { 4094 var operator = new mathMLTree.MathNode( 4095 "mo", [new mathMLTree.TextNode("\u203e")]); 4096 operator.setAttribute("stretchy", "true"); 4097 4098 var node = new mathMLTree.MathNode( 4099 "mover", 4100 [buildGroup(group.value.body, options), 4101 operator]); 4102 node.setAttribute("accent", "true"); 4103 4104 return node; 4105}; 4106 4107groupTypes.underline = function(group, options) { 4108 var operator = new mathMLTree.MathNode( 4109 "mo", [new mathMLTree.TextNode("\u203e")]); 4110 operator.setAttribute("stretchy", "true"); 4111 4112 var node = new mathMLTree.MathNode( 4113 "munder", 4114 [buildGroup(group.value.body, options), 4115 operator]); 4116 node.setAttribute("accentunder", "true"); 4117 4118 return node; 4119}; 4120 4121groupTypes.rule = function(group) { 4122 // TODO(emily): Figure out if there's an actual way to draw black boxes 4123 // in MathML. 4124 var node = new mathMLTree.MathNode("mrow"); 4125 4126 return node; 4127}; 4128 4129groupTypes.kern = function(group) { 4130 // TODO(kevin): Figure out if there's a way to add space in MathML 4131 var node = new mathMLTree.MathNode("mrow"); 4132 4133 return node; 4134}; 4135 4136groupTypes.llap = function(group, options) { 4137 var node = new mathMLTree.MathNode( 4138 "mpadded", [buildGroup(group.value.body, options)]); 4139 4140 node.setAttribute("lspace", "-1width"); 4141 node.setAttribute("width", "0px"); 4142 4143 return node; 4144}; 4145 4146groupTypes.rlap = function(group, options) { 4147 var node = new mathMLTree.MathNode( 4148 "mpadded", [buildGroup(group.value.body, options)]); 4149 4150 node.setAttribute("width", "0px"); 4151 4152 return node; 4153}; 4154 4155groupTypes.phantom = function(group, options) { 4156 var inner = buildExpression(group.value.value, options); 4157 return new mathMLTree.MathNode("mphantom", inner); 4158}; 4159 4160groupTypes.mclass = function(group, options) { 4161 var inner = buildExpression(group.value.value, options); 4162 return new mathMLTree.MathNode("mstyle", inner); 4163}; 4164 4165/** 4166 * Takes a list of nodes, builds them, and returns a list of the generated 4167 * MathML nodes. A little simpler than the HTML version because we don't do any 4168 * previous-node handling. 4169 */ 4170var buildExpression = function(expression, options) { 4171 var groups = []; 4172 for (var i = 0; i < expression.length; i++) { 4173 var group = expression[i]; 4174 groups.push(buildGroup(group, options)); 4175 } 4176 return groups; 4177}; 4178 4179/** 4180 * Takes a group from the parser and calls the appropriate groupTypes function 4181 * on it to produce a MathML node. 4182 */ 4183var buildGroup = function(group, options) { 4184 if (!group) { 4185 return new mathMLTree.MathNode("mrow"); 4186 } 4187 4188 if (groupTypes[group.type]) { 4189 // Call the groupTypes function 4190 return groupTypes[group.type](group, options); 4191 } else { 4192 throw new ParseError( 4193 "Got group of unknown type: '" + group.type + "'"); 4194 } 4195}; 4196 4197/** 4198 * Takes a full parse tree and settings and builds a MathML representation of 4199 * it. In particular, we put the elements from building the parse tree into a 4200 * <semantics> tag so we can also include that TeX source as an annotation. 4201 * 4202 * Note that we actually return a domTree element with a `<math>` inside it so 4203 * we can do appropriate styling. 4204 */ 4205var buildMathML = function(tree, texExpression, options) { 4206 var expression = buildExpression(tree, options); 4207 4208 // Wrap up the expression in an mrow so it is presented in the semantics 4209 // tag correctly. 4210 var wrapper = new mathMLTree.MathNode("mrow", expression); 4211 4212 // Build a TeX annotation of the source 4213 var annotation = new mathMLTree.MathNode( 4214 "annotation", [new mathMLTree.TextNode(texExpression)]); 4215 4216 annotation.setAttribute("encoding", "application/x-tex"); 4217 4218 var semantics = new mathMLTree.MathNode( 4219 "semantics", [wrapper, annotation]); 4220 4221 var math = new mathMLTree.MathNode("math", [semantics]); 4222 4223 // You can't style <math> nodes, so we wrap the node in a span. 4224 return makeSpan(["katex-mathml"], [math]); 4225}; 4226 4227module.exports = buildMathML; 4228 4229},{"./ParseError":6,"./buildCommon":10,"./fontMetrics":17,"./mathMLTree":20,"./symbols":23,"./utils":25}],13:[function(require,module,exports){ 4230var buildHTML = require("./buildHTML"); 4231var buildMathML = require("./buildMathML"); 4232var buildCommon = require("./buildCommon"); 4233var Options = require("./Options"); 4234var Settings = require("./Settings"); 4235var Style = require("./Style"); 4236 4237var makeSpan = buildCommon.makeSpan; 4238 4239var buildTree = function(tree, expression, settings) { 4240 settings = settings || new Settings({}); 4241 4242 var startStyle = Style.TEXT; 4243 if (settings.displayMode) { 4244 startStyle = Style.DISPLAY; 4245 } 4246 4247 // Setup the default options 4248 var options = new Options({ 4249 style: startStyle, 4250 size: "size5" 4251 }); 4252 4253 // `buildHTML` sometimes messes with the parse tree (like turning bins -> 4254 // ords), so we build the MathML version first. 4255 var mathMLNode = buildMathML(tree, expression, options); 4256 var htmlNode = buildHTML(tree, options); 4257 4258 var katexNode = makeSpan(["katex"], [ 4259 mathMLNode, htmlNode 4260 ]); 4261 4262 if (settings.displayMode) { 4263 return makeSpan(["katex-display"], [katexNode]); 4264 } else { 4265 return katexNode; 4266 } 4267}; 4268 4269module.exports = buildTree; 4270 4271},{"./Options":5,"./Settings":8,"./Style":9,"./buildCommon":10,"./buildHTML":11,"./buildMathML":12}],14:[function(require,module,exports){ 4272/** 4273 * This file deals with creating delimiters of various sizes. The TeXbook 4274 * discusses these routines on page 441-442, in the "Another subroutine sets box 4275 * x to a specified variable delimiter" paragraph. 4276 * 4277 * There are three main routines here. `makeSmallDelim` makes a delimiter in the 4278 * normal font, but in either text, script, or scriptscript style. 4279 * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1, 4280 * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of 4281 * smaller pieces that are stacked on top of one another. 4282 * 4283 * The functions take a parameter `center`, which determines if the delimiter 4284 * should be centered around the axis. 4285 * 4286 * Then, there are three exposed functions. `sizedDelim` makes a delimiter in 4287 * one of the given sizes. This is used for things like `\bigl`. 4288 * `customSizedDelim` makes a delimiter with a given total height+depth. It is 4289 * called in places like `\sqrt`. `leftRightDelim` makes an appropriate 4290 * delimiter which surrounds an expression of a given height an depth. It is 4291 * used in `\left` and `\right`. 4292 */ 4293 4294var ParseError = require("./ParseError"); 4295var Style = require("./Style"); 4296 4297var buildCommon = require("./buildCommon"); 4298var fontMetrics = require("./fontMetrics"); 4299var symbols = require("./symbols"); 4300var utils = require("./utils"); 4301 4302var makeSpan = buildCommon.makeSpan; 4303 4304/** 4305 * Get the metrics for a given symbol and font, after transformation (i.e. 4306 * after following replacement from symbols.js) 4307 */ 4308var getMetrics = function(symbol, font) { 4309 if (symbols.math[symbol] && symbols.math[symbol].replace) { 4310 return fontMetrics.getCharacterMetrics( 4311 symbols.math[symbol].replace, font); 4312 } else { 4313 return fontMetrics.getCharacterMetrics( 4314 symbol, font); 4315 } 4316}; 4317 4318/** 4319 * Builds a symbol in the given font size (note size is an integer) 4320 */ 4321var mathrmSize = function(value, size, mode, options) { 4322 return buildCommon.makeSymbol(value, "Size" + size + "-Regular", 4323 mode, options); 4324}; 4325 4326/** 4327 * Puts a delimiter span in a given style, and adds appropriate height, depth, 4328 * and maxFontSizes. 4329 */ 4330var styleWrap = function(delim, toStyle, options, classes) { 4331 classes = classes || []; 4332 var span = makeSpan( 4333 classes.concat(["style-wrap", options.style.reset(), toStyle.cls()]), 4334 [delim], options); 4335 4336 var multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier; 4337 4338 span.height *= multiplier; 4339 span.depth *= multiplier; 4340 span.maxFontSize = toStyle.sizeMultiplier; 4341 4342 return span; 4343}; 4344 4345/** 4346 * Makes a small delimiter. This is a delimiter that comes in the Main-Regular 4347 * font, but is restyled to either be in textstyle, scriptstyle, or 4348 * scriptscriptstyle. 4349 */ 4350var makeSmallDelim = function(delim, style, center, options, mode, classes) { 4351 var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options); 4352 4353 var span = styleWrap(text, style, options, classes); 4354 4355 if (center) { 4356 var shift = 4357 (1 - options.style.sizeMultiplier / style.sizeMultiplier) * 4358 options.style.metrics.axisHeight; 4359 4360 span.style.top = shift + "em"; 4361 span.height -= shift; 4362 span.depth += shift; 4363 } 4364 4365 return span; 4366}; 4367 4368/** 4369 * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2, 4370 * Size3, or Size4 fonts. It is always rendered in textstyle. 4371 */ 4372var makeLargeDelim = function(delim, size, center, options, mode, classes) { 4373 var inner = mathrmSize(delim, size, mode, options); 4374 4375 var span = styleWrap( 4376 makeSpan(["delimsizing", "size" + size], [inner], options), 4377 Style.TEXT, options, classes); 4378 4379 if (center) { 4380 var shift = (1 - options.style.sizeMultiplier) * 4381 options.style.metrics.axisHeight; 4382 4383 span.style.top = shift + "em"; 4384 span.height -= shift; 4385 span.depth += shift; 4386 } 4387 4388 return span; 4389}; 4390 4391/** 4392 * Make an inner span with the given offset and in the given font. This is used 4393 * in `makeStackedDelim` to make the stacking pieces for the delimiter. 4394 */ 4395var makeInner = function(symbol, font, mode) { 4396 var sizeClass; 4397 // Apply the correct CSS class to choose the right font. 4398 if (font === "Size1-Regular") { 4399 sizeClass = "delim-size1"; 4400 } else if (font === "Size4-Regular") { 4401 sizeClass = "delim-size4"; 4402 } 4403 4404 var inner = makeSpan( 4405 ["delimsizinginner", sizeClass], 4406 [makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); 4407 4408 // Since this will be passed into `makeVList` in the end, wrap the element 4409 // in the appropriate tag that VList uses. 4410 return {type: "elem", elem: inner}; 4411}; 4412 4413/** 4414 * Make a stacked delimiter out of a given delimiter, with the total height at 4415 * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook. 4416 */ 4417var makeStackedDelim = function(delim, heightTotal, center, options, mode, 4418 classes) { 4419 // There are four parts, the top, an optional middle, a repeated part, and a 4420 // bottom. 4421 var top; 4422 var middle; 4423 var repeat; 4424 var bottom; 4425 top = repeat = bottom = delim; 4426 middle = null; 4427 // Also keep track of what font the delimiters are in 4428 var font = "Size1-Regular"; 4429 4430 // We set the parts and font based on the symbol. Note that we use 4431 // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the 4432 // repeats of the arrows 4433 if (delim === "\\uparrow") { 4434 repeat = bottom = "\u23d0"; 4435 } else if (delim === "\\Uparrow") { 4436 repeat = bottom = "\u2016"; 4437 } else if (delim === "\\downarrow") { 4438 top = repeat = "\u23d0"; 4439 } else if (delim === "\\Downarrow") { 4440 top = repeat = "\u2016"; 4441 } else if (delim === "\\updownarrow") { 4442 top = "\\uparrow"; 4443 repeat = "\u23d0"; 4444 bottom = "\\downarrow"; 4445 } else if (delim === "\\Updownarrow") { 4446 top = "\\Uparrow"; 4447 repeat = "\u2016"; 4448 bottom = "\\Downarrow"; 4449 } else if (delim === "[" || delim === "\\lbrack") { 4450 top = "\u23a1"; 4451 repeat = "\u23a2"; 4452 bottom = "\u23a3"; 4453 font = "Size4-Regular"; 4454 } else if (delim === "]" || delim === "\\rbrack") { 4455 top = "\u23a4"; 4456 repeat = "\u23a5"; 4457 bottom = "\u23a6"; 4458 font = "Size4-Regular"; 4459 } else if (delim === "\\lfloor") { 4460 repeat = top = "\u23a2"; 4461 bottom = "\u23a3"; 4462 font = "Size4-Regular"; 4463 } else if (delim === "\\lceil") { 4464 top = "\u23a1"; 4465 repeat = bottom = "\u23a2"; 4466 font = "Size4-Regular"; 4467 } else if (delim === "\\rfloor") { 4468 repeat = top = "\u23a5"; 4469 bottom = "\u23a6"; 4470 font = "Size4-Regular"; 4471 } else if (delim === "\\rceil") { 4472 top = "\u23a4"; 4473 repeat = bottom = "\u23a5"; 4474 font = "Size4-Regular"; 4475 } else if (delim === "(") { 4476 top = "\u239b"; 4477 repeat = "\u239c"; 4478 bottom = "\u239d"; 4479 font = "Size4-Regular"; 4480 } else if (delim === ")") { 4481 top = "\u239e"; 4482 repeat = "\u239f"; 4483 bottom = "\u23a0"; 4484 font = "Size4-Regular"; 4485 } else if (delim === "\\{" || delim === "\\lbrace") { 4486 top = "\u23a7"; 4487 middle = "\u23a8"; 4488 bottom = "\u23a9"; 4489 repeat = "\u23aa"; 4490 font = "Size4-Regular"; 4491 } else if (delim === "\\}" || delim === "\\rbrace") { 4492 top = "\u23ab"; 4493 middle = "\u23ac"; 4494 bottom = "\u23ad"; 4495 repeat = "\u23aa"; 4496 font = "Size4-Regular"; 4497 } else if (delim === "\\lgroup") { 4498 top = "\u23a7"; 4499 bottom = "\u23a9"; 4500 repeat = "\u23aa"; 4501 font = "Size4-Regular"; 4502 } else if (delim === "\\rgroup") { 4503 top = "\u23ab"; 4504 bottom = "\u23ad"; 4505 repeat = "\u23aa"; 4506 font = "Size4-Regular"; 4507 } else if (delim === "\\lmoustache") { 4508 top = "\u23a7"; 4509 bottom = "\u23ad"; 4510 repeat = "\u23aa"; 4511 font = "Size4-Regular"; 4512 } else if (delim === "\\rmoustache") { 4513 top = "\u23ab"; 4514 bottom = "\u23a9"; 4515 repeat = "\u23aa"; 4516 font = "Size4-Regular"; 4517 } else if (delim === "\\surd") { 4518 top = "\ue001"; 4519 bottom = "\u23b7"; 4520 repeat = "\ue000"; 4521 font = "Size4-Regular"; 4522 } 4523 4524 // Get the metrics of the four sections 4525 var topMetrics = getMetrics(top, font); 4526 var topHeightTotal = topMetrics.height + topMetrics.depth; 4527 var repeatMetrics = getMetrics(repeat, font); 4528 var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; 4529 var bottomMetrics = getMetrics(bottom, font); 4530 var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; 4531 var middleHeightTotal = 0; 4532 var middleFactor = 1; 4533 if (middle !== null) { 4534 var middleMetrics = getMetrics(middle, font); 4535 middleHeightTotal = middleMetrics.height + middleMetrics.depth; 4536 middleFactor = 2; // repeat symmetrically above and below middle 4537 } 4538 4539 // Calcuate the minimal height that the delimiter can have. 4540 // It is at least the size of the top, bottom, and optional middle combined. 4541 var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; 4542 4543 // Compute the number of copies of the repeat symbol we will need 4544 var repeatCount = Math.ceil( 4545 (heightTotal - minHeight) / (middleFactor * repeatHeightTotal)); 4546 4547 // Compute the total height of the delimiter including all the symbols 4548 var realHeightTotal = 4549 minHeight + repeatCount * middleFactor * repeatHeightTotal; 4550 4551 // The center of the delimiter is placed at the center of the axis. Note 4552 // that in this context, "center" means that the delimiter should be 4553 // centered around the axis in the current style, while normally it is 4554 // centered around the axis in textstyle. 4555 var axisHeight = options.style.metrics.axisHeight; 4556 if (center) { 4557 axisHeight *= options.style.sizeMultiplier; 4558 } 4559 // Calculate the depth 4560 var depth = realHeightTotal / 2 - axisHeight; 4561 4562 // Now, we start building the pieces that will go into the vlist 4563 4564 // Keep a list of the inner pieces 4565 var inners = []; 4566 4567 // Add the bottom symbol 4568 inners.push(makeInner(bottom, font, mode)); 4569 4570 var i; 4571 if (middle === null) { 4572 // Add that many symbols 4573 for (i = 0; i < repeatCount; i++) { 4574 inners.push(makeInner(repeat, font, mode)); 4575 } 4576 } else { 4577 // When there is a middle bit, we need the middle part and two repeated 4578 // sections 4579 for (i = 0; i < repeatCount; i++) { 4580 inners.push(makeInner(repeat, font, mode)); 4581 } 4582 inners.push(makeInner(middle, font, mode)); 4583 for (i = 0; i < repeatCount; i++) { 4584 inners.push(makeInner(repeat, font, mode)); 4585 } 4586 } 4587 4588 // Add the top symbol 4589 inners.push(makeInner(top, font, mode)); 4590 4591 // Finally, build the vlist 4592 var inner = buildCommon.makeVList(inners, "bottom", depth, options); 4593 4594 return styleWrap( 4595 makeSpan(["delimsizing", "mult"], [inner], options), 4596 Style.TEXT, options, classes); 4597}; 4598 4599// There are three kinds of delimiters, delimiters that stack when they become 4600// too large 4601var stackLargeDelimiters = [ 4602 "(", ")", "[", "\\lbrack", "]", "\\rbrack", 4603 "\\{", "\\lbrace", "\\}", "\\rbrace", 4604 "\\lfloor", "\\rfloor", "\\lceil", "\\rceil", 4605 "\\surd" 4606]; 4607 4608// delimiters that always stack 4609var stackAlwaysDelimiters = [ 4610 "\\uparrow", "\\downarrow", "\\updownarrow", 4611 "\\Uparrow", "\\Downarrow", "\\Updownarrow", 4612 "|", "\\|", "\\vert", "\\Vert", 4613 "\\lvert", "\\rvert", "\\lVert", "\\rVert", 4614 "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache" 4615]; 4616 4617// and delimiters that never stack 4618var stackNeverDelimiters = [ 4619 "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt" 4620]; 4621 4622// Metrics of the different sizes. Found by looking at TeX's output of 4623// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ 4624// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. 4625var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; 4626 4627/** 4628 * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4. 4629 */ 4630var makeSizedDelim = function(delim, size, options, mode, classes) { 4631 // < and > turn into \langle and \rangle in delimiters 4632 if (delim === "<" || delim === "\\lt") { 4633 delim = "\\langle"; 4634 } else if (delim === ">" || delim === "\\gt") { 4635 delim = "\\rangle"; 4636 } 4637 4638 // Sized delimiters are never centered. 4639 if (utils.contains(stackLargeDelimiters, delim) || 4640 utils.contains(stackNeverDelimiters, delim)) { 4641 return makeLargeDelim(delim, size, false, options, mode, classes); 4642 } else if (utils.contains(stackAlwaysDelimiters, delim)) { 4643 return makeStackedDelim( 4644 delim, sizeToMaxHeight[size], false, options, mode, classes); 4645 } else { 4646 throw new ParseError("Illegal delimiter: '" + delim + "'"); 4647 } 4648}; 4649 4650/** 4651 * There are three different sequences of delimiter sizes that the delimiters 4652 * follow depending on the kind of delimiter. This is used when creating custom 4653 * sized delimiters to decide whether to create a small, large, or stacked 4654 * delimiter. 4655 * 4656 * In real TeX, these sequences aren't explicitly defined, but are instead 4657 * defined inside the font metrics. Since there are only three sequences that 4658 * are possible for the delimiters that TeX defines, it is easier to just encode 4659 * them explicitly here. 4660 */ 4661 4662// Delimiters that never stack try small delimiters and large delimiters only 4663var stackNeverDelimiterSequence = [ 4664 {type: "small", style: Style.SCRIPTSCRIPT}, 4665 {type: "small", style: Style.SCRIPT}, 4666 {type: "small", style: Style.TEXT}, 4667 {type: "large", size: 1}, 4668 {type: "large", size: 2}, 4669 {type: "large", size: 3}, 4670 {type: "large", size: 4} 4671]; 4672 4673// Delimiters that always stack try the small delimiters first, then stack 4674var stackAlwaysDelimiterSequence = [ 4675 {type: "small", style: Style.SCRIPTSCRIPT}, 4676 {type: "small", style: Style.SCRIPT}, 4677 {type: "small", style: Style.TEXT}, 4678 {type: "stack"} 4679]; 4680 4681// Delimiters that stack when large try the small and then large delimiters, and 4682// stack afterwards 4683var stackLargeDelimiterSequence = [ 4684 {type: "small", style: Style.SCRIPTSCRIPT}, 4685 {type: "small", style: Style.SCRIPT}, 4686 {type: "small", style: Style.TEXT}, 4687 {type: "large", size: 1}, 4688 {type: "large", size: 2}, 4689 {type: "large", size: 3}, 4690 {type: "large", size: 4}, 4691 {type: "stack"} 4692]; 4693 4694/** 4695 * Get the font used in a delimiter based on what kind of delimiter it is. 4696 */ 4697var delimTypeToFont = function(type) { 4698 if (type.type === "small") { 4699 return "Main-Regular"; 4700 } else if (type.type === "large") { 4701 return "Size" + type.size + "-Regular"; 4702 } else if (type.type === "stack") { 4703 return "Size4-Regular"; 4704 } 4705}; 4706 4707/** 4708 * Traverse a sequence of types of delimiters to decide what kind of delimiter 4709 * should be used to create a delimiter of the given height+depth. 4710 */ 4711var traverseSequence = function(delim, height, sequence, options) { 4712 // Here, we choose the index we should start at in the sequences. In smaller 4713 // sizes (which correspond to larger numbers in style.size) we start earlier 4714 // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts 4715 // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2 4716 var start = Math.min(2, 3 - options.style.size); 4717 for (var i = start; i < sequence.length; i++) { 4718 if (sequence[i].type === "stack") { 4719 // This is always the last delimiter, so we just break the loop now. 4720 break; 4721 } 4722 4723 var metrics = getMetrics(delim, delimTypeToFont(sequence[i])); 4724 var heightDepth = metrics.height + metrics.depth; 4725 4726 // Small delimiters are scaled down versions of the same font, so we 4727 // account for the style change size. 4728 4729 if (sequence[i].type === "small") { 4730 heightDepth *= sequence[i].style.sizeMultiplier; 4731 } 4732 4733 // Check if the delimiter at this size works for the given height. 4734 if (heightDepth > height) { 4735 return sequence[i]; 4736 } 4737 } 4738 4739 // If we reached the end of the sequence, return the last sequence element. 4740 return sequence[sequence.length - 1]; 4741}; 4742 4743/** 4744 * Make a delimiter of a given height+depth, with optional centering. Here, we 4745 * traverse the sequences, and create a delimiter that the sequence tells us to. 4746 */ 4747var makeCustomSizedDelim = function(delim, height, center, options, mode, 4748 classes) { 4749 if (delim === "<" || delim === "\\lt") { 4750 delim = "\\langle"; 4751 } else if (delim === ">" || delim === "\\gt") { 4752 delim = "\\rangle"; 4753 } 4754 4755 // Decide what sequence to use 4756 var sequence; 4757 if (utils.contains(stackNeverDelimiters, delim)) { 4758 sequence = stackNeverDelimiterSequence; 4759 } else if (utils.contains(stackLargeDelimiters, delim)) { 4760 sequence = stackLargeDelimiterSequence; 4761 } else { 4762 sequence = stackAlwaysDelimiterSequence; 4763 } 4764 4765 // Look through the sequence 4766 var delimType = traverseSequence(delim, height, sequence, options); 4767 4768 // Depending on the sequence element we decided on, call the appropriate 4769 // function. 4770 if (delimType.type === "small") { 4771 return makeSmallDelim(delim, delimType.style, center, options, mode, 4772 classes); 4773 } else if (delimType.type === "large") { 4774 return makeLargeDelim(delim, delimType.size, center, options, mode, 4775 classes); 4776 } else if (delimType.type === "stack") { 4777 return makeStackedDelim(delim, height, center, options, mode, classes); 4778 } 4779}; 4780 4781/** 4782 * Make a delimiter for use with `\left` and `\right`, given a height and depth 4783 * of an expression that the delimiters surround. 4784 */ 4785var makeLeftRightDelim = function(delim, height, depth, options, mode, 4786 classes) { 4787 // We always center \left/\right delimiters, so the axis is always shifted 4788 var axisHeight = 4789 options.style.metrics.axisHeight * options.style.sizeMultiplier; 4790 4791 // Taken from TeX source, tex.web, function make_left_right 4792 var delimiterFactor = 901; 4793 var delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm; 4794 4795 var maxDistFromAxis = Math.max( 4796 height - axisHeight, depth + axisHeight); 4797 4798 var totalHeight = Math.max( 4799 // In real TeX, calculations are done using integral values which are 4800 // 65536 per pt, or 655360 per em. So, the division here truncates in 4801 // TeX but doesn't here, producing different results. If we wanted to 4802 // exactly match TeX's calculation, we could do 4803 // Math.floor(655360 * maxDistFromAxis / 500) * 4804 // delimiterFactor / 655360 4805 // (To see the difference, compare 4806 // x^{x^{\left(\rule{0.1em}{0.68em}\right)}} 4807 // in TeX and KaTeX) 4808 maxDistFromAxis / 500 * delimiterFactor, 4809 2 * maxDistFromAxis - delimiterExtend); 4810 4811 // Finally, we defer to `makeCustomSizedDelim` with our calculated total 4812 // height 4813 return makeCustomSizedDelim(delim, totalHeight, true, options, mode, 4814 classes); 4815}; 4816 4817module.exports = { 4818 sizedDelim: makeSizedDelim, 4819 customSizedDelim: makeCustomSizedDelim, 4820 leftRightDelim: makeLeftRightDelim 4821}; 4822 4823},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./fontMetrics":17,"./symbols":23,"./utils":25}],15:[function(require,module,exports){ 4824/** 4825 * These objects store the data about the DOM nodes we create, as well as some 4826 * extra data. They can then be transformed into real DOM nodes with the 4827 * `toNode` function or HTML markup using `toMarkup`. They are useful for both 4828 * storing extra properties on the nodes, as well as providing a way to easily 4829 * work with the DOM. 4830 * 4831 * Similar functions for working with MathML nodes exist in mathMLTree.js. 4832 */ 4833var unicodeRegexes = require("./unicodeRegexes"); 4834var utils = require("./utils"); 4835 4836/** 4837 * Create an HTML className based on a list of classes. In addition to joining 4838 * with spaces, we also remove null or empty classes. 4839 */ 4840var createClass = function(classes) { 4841 classes = classes.slice(); 4842 for (var i = classes.length - 1; i >= 0; i--) { 4843 if (!classes[i]) { 4844 classes.splice(i, 1); 4845 } 4846 } 4847 4848 return classes.join(" "); 4849}; 4850 4851/** 4852 * This node represents a span node, with a className, a list of children, and 4853 * an inline style. It also contains information about its height, depth, and 4854 * maxFontSize. 4855 */ 4856function span(classes, children, options) { 4857 this.classes = classes || []; 4858 this.children = children || []; 4859 this.height = 0; 4860 this.depth = 0; 4861 this.maxFontSize = 0; 4862 this.style = {}; 4863 this.attributes = {}; 4864 if (options) { 4865 if (options.style.isTight()) { 4866 this.classes.push("mtight"); 4867 } 4868 if (options.getColor()) { 4869 this.style.color = options.getColor(); 4870 } 4871 } 4872} 4873 4874/** 4875 * Sets an arbitrary attribute on the span. Warning: use this wisely. Not all 4876 * browsers support attributes the same, and having too many custom attributes 4877 * is probably bad. 4878 */ 4879span.prototype.setAttribute = function(attribute, value) { 4880 this.attributes[attribute] = value; 4881}; 4882 4883span.prototype.tryCombine = function(sibling) { 4884 return false; 4885}; 4886 4887/** 4888 * Convert the span into an HTML node 4889 */ 4890span.prototype.toNode = function() { 4891 var span = document.createElement("span"); 4892 4893 // Apply the class 4894 span.className = createClass(this.classes); 4895 4896 // Apply inline styles 4897 for (var style in this.style) { 4898 if (Object.prototype.hasOwnProperty.call(this.style, style)) { 4899 span.style[style] = this.style[style]; 4900 } 4901 } 4902 4903 // Apply attributes 4904 for (var attr in this.attributes) { 4905 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 4906 span.setAttribute(attr, this.attributes[attr]); 4907 } 4908 } 4909 4910 // Append the children, also as HTML nodes 4911 for (var i = 0; i < this.children.length; i++) { 4912 span.appendChild(this.children[i].toNode()); 4913 } 4914 4915 return span; 4916}; 4917 4918/** 4919 * Convert the span into an HTML markup string 4920 */ 4921span.prototype.toMarkup = function() { 4922 var markup = "<span"; 4923 4924 // Add the class 4925 if (this.classes.length) { 4926 markup += " class=\""; 4927 markup += utils.escape(createClass(this.classes)); 4928 markup += "\""; 4929 } 4930 4931 var styles = ""; 4932 4933 // Add the styles, after hyphenation 4934 for (var style in this.style) { 4935 if (this.style.hasOwnProperty(style)) { 4936 styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; 4937 } 4938 } 4939 4940 if (styles) { 4941 markup += " style=\"" + utils.escape(styles) + "\""; 4942 } 4943 4944 // Add the attributes 4945 for (var attr in this.attributes) { 4946 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 4947 markup += " " + attr + "=\""; 4948 markup += utils.escape(this.attributes[attr]); 4949 markup += "\""; 4950 } 4951 } 4952 4953 markup += ">"; 4954 4955 // Add the markup of the children, also as markup 4956 for (var i = 0; i < this.children.length; i++) { 4957 markup += this.children[i].toMarkup(); 4958 } 4959 4960 markup += "</span>"; 4961 4962 return markup; 4963}; 4964 4965/** 4966 * This node represents a document fragment, which contains elements, but when 4967 * placed into the DOM doesn't have any representation itself. Thus, it only 4968 * contains children and doesn't have any HTML properties. It also keeps track 4969 * of a height, depth, and maxFontSize. 4970 */ 4971function documentFragment(children) { 4972 this.children = children || []; 4973 this.height = 0; 4974 this.depth = 0; 4975 this.maxFontSize = 0; 4976} 4977 4978/** 4979 * Convert the fragment into a node 4980 */ 4981documentFragment.prototype.toNode = function() { 4982 // Create a fragment 4983 var frag = document.createDocumentFragment(); 4984 4985 // Append the children 4986 for (var i = 0; i < this.children.length; i++) { 4987 frag.appendChild(this.children[i].toNode()); 4988 } 4989 4990 return frag; 4991}; 4992 4993/** 4994 * Convert the fragment into HTML markup 4995 */ 4996documentFragment.prototype.toMarkup = function() { 4997 var markup = ""; 4998 4999 // Simply concatenate the markup for the children together 5000 for (var i = 0; i < this.children.length; i++) { 5001 markup += this.children[i].toMarkup(); 5002 } 5003 5004 return markup; 5005}; 5006 5007var iCombinations = { 5008 'î': '\u0131\u0302', 5009 'ï': '\u0131\u0308', 5010 'í': '\u0131\u0301', 5011 // 'ī': '\u0131\u0304', // enable when we add Extended Latin 5012 'ì': '\u0131\u0300' 5013}; 5014 5015/** 5016 * A symbol node contains information about a single symbol. It either renders 5017 * to a single text node, or a span with a single text node in it, depending on 5018 * whether it has CSS classes, styles, or needs italic correction. 5019 */ 5020function symbolNode(value, height, depth, italic, skew, classes, style) { 5021 this.value = value || ""; 5022 this.height = height || 0; 5023 this.depth = depth || 0; 5024 this.italic = italic || 0; 5025 this.skew = skew || 0; 5026 this.classes = classes || []; 5027 this.style = style || {}; 5028 this.maxFontSize = 0; 5029 5030 // Mark CJK characters with specific classes so that we can specify which 5031 // fonts to use. This allows us to render these characters with a serif 5032 // font in situations where the browser would either default to a sans serif 5033 // or render a placeholder character. 5034 if (unicodeRegexes.cjkRegex.test(value)) { 5035 // I couldn't find any fonts that contained Hangul as well as all of 5036 // the other characters we wanted to test there for it gets its own 5037 // CSS class. 5038 if (unicodeRegexes.hangulRegex.test(value)) { 5039 this.classes.push('hangul_fallback'); 5040 } else { 5041 this.classes.push('cjk_fallback'); 5042 } 5043 } 5044 5045 if (/[îïíì]/.test(this.value)) { // add ī when we add Extended Latin 5046 this.value = iCombinations[this.value]; 5047 } 5048} 5049 5050symbolNode.prototype.tryCombine = function(sibling) { 5051 if (!sibling 5052 || !(sibling instanceof symbolNode) 5053 || this.italic > 0 5054 || createClass(this.classes) !== createClass(sibling.classes) 5055 || this.skew !== sibling.skew 5056 || this.maxFontSize !== sibling.maxFontSize) { 5057 return false; 5058 } 5059 for (var style in this.style) { 5060 if (this.style.hasOwnProperty(style) 5061 && this.style[style] !== sibling.style[style]) { 5062 return false; 5063 } 5064 } 5065 for (style in sibling.style) { 5066 if (sibling.style.hasOwnProperty(style) 5067 && this.style[style] !== sibling.style[style]) { 5068 return false; 5069 } 5070 } 5071 this.value += sibling.value; 5072 this.height = Math.max(this.height, sibling.height); 5073 this.depth = Math.max(this.depth, sibling.depth); 5074 this.italic = sibling.italic; 5075 return true; 5076}; 5077 5078/** 5079 * Creates a text node or span from a symbol node. Note that a span is only 5080 * created if it is needed. 5081 */ 5082symbolNode.prototype.toNode = function() { 5083 var node = document.createTextNode(this.value); 5084 var span = null; 5085 5086 if (this.italic > 0) { 5087 span = document.createElement("span"); 5088 span.style.marginRight = this.italic + "em"; 5089 } 5090 5091 if (this.classes.length > 0) { 5092 span = span || document.createElement("span"); 5093 span.className = createClass(this.classes); 5094 } 5095 5096 for (var style in this.style) { 5097 if (this.style.hasOwnProperty(style)) { 5098 span = span || document.createElement("span"); 5099 span.style[style] = this.style[style]; 5100 } 5101 } 5102 5103 if (span) { 5104 span.appendChild(node); 5105 return span; 5106 } else { 5107 return node; 5108 } 5109}; 5110 5111/** 5112 * Creates markup for a symbol node. 5113 */ 5114symbolNode.prototype.toMarkup = function() { 5115 // TODO(alpert): More duplication than I'd like from 5116 // span.prototype.toMarkup and symbolNode.prototype.toNode... 5117 var needsSpan = false; 5118 5119 var markup = "<span"; 5120 5121 if (this.classes.length) { 5122 needsSpan = true; 5123 markup += " class=\""; 5124 markup += utils.escape(createClass(this.classes)); 5125 markup += "\""; 5126 } 5127 5128 var styles = ""; 5129 5130 if (this.italic > 0) { 5131 styles += "margin-right:" + this.italic + "em;"; 5132 } 5133 for (var style in this.style) { 5134 if (this.style.hasOwnProperty(style)) { 5135 styles += utils.hyphenate(style) + ":" + this.style[style] + ";"; 5136 } 5137 } 5138 5139 if (styles) { 5140 needsSpan = true; 5141 markup += " style=\"" + utils.escape(styles) + "\""; 5142 } 5143 5144 var escaped = utils.escape(this.value); 5145 if (needsSpan) { 5146 markup += ">"; 5147 markup += escaped; 5148 markup += "</span>"; 5149 return markup; 5150 } else { 5151 return escaped; 5152 } 5153}; 5154 5155module.exports = { 5156 span: span, 5157 documentFragment: documentFragment, 5158 symbolNode: symbolNode 5159}; 5160 5161},{"./unicodeRegexes":24,"./utils":25}],16:[function(require,module,exports){ 5162/* eslint no-constant-condition:0 */ 5163var parseData = require("./parseData"); 5164var ParseError = require("./ParseError"); 5165var Style = require("./Style"); 5166 5167var ParseNode = parseData.ParseNode; 5168 5169/** 5170 * Parse the body of the environment, with rows delimited by \\ and 5171 * columns delimited by &, and create a nested list in row-major order 5172 * with one group per cell. 5173 */ 5174function parseArray(parser, result) { 5175 var row = []; 5176 var body = [row]; 5177 var rowGaps = []; 5178 while (true) { 5179 var cell = parser.parseExpression(false, null); 5180 row.push(new ParseNode("ordgroup", cell, parser.mode)); 5181 var next = parser.nextToken.text; 5182 if (next === "&") { 5183 parser.consume(); 5184 } else if (next === "\\end") { 5185 break; 5186 } else if (next === "\\\\" || next === "\\cr") { 5187 var cr = parser.parseFunction(); 5188 rowGaps.push(cr.value.size); 5189 row = []; 5190 body.push(row); 5191 } else { 5192 throw new ParseError("Expected & or \\\\ or \\end", 5193 parser.nextToken); 5194 } 5195 } 5196 result.body = body; 5197 result.rowGaps = rowGaps; 5198 return new ParseNode(result.type, result, parser.mode); 5199} 5200 5201/* 5202 * An environment definition is very similar to a function definition: 5203 * it is declared with a name or a list of names, a set of properties 5204 * and a handler containing the actual implementation. 5205 * 5206 * The properties include: 5207 * - numArgs: The number of arguments after the \begin{name} function. 5208 * - argTypes: (optional) Just like for a function 5209 * - allowedInText: (optional) Whether or not the environment is allowed inside 5210 * text mode (default false) (not enforced yet) 5211 * - numOptionalArgs: (optional) Just like for a function 5212 * A bare number instead of that object indicates the numArgs value. 5213 * 5214 * The handler function will receive two arguments 5215 * - context: information and references provided by the parser 5216 * - args: an array of arguments passed to \begin{name} 5217 * The context contains the following properties: 5218 * - envName: the name of the environment, one of the listed names. 5219 * - parser: the parser object 5220 * - lexer: the lexer object 5221 * - positions: the positions associated with these arguments from args. 5222 * The handler must return a ParseResult. 5223 */ 5224 5225function defineEnvironment(names, props, handler) { 5226 if (typeof names === "string") { 5227 names = [names]; 5228 } 5229 if (typeof props === "number") { 5230 props = { numArgs: props }; 5231 } 5232 // Set default values of environments 5233 var data = { 5234 numArgs: props.numArgs || 0, 5235 argTypes: props.argTypes, 5236 greediness: 1, 5237 allowedInText: !!props.allowedInText, 5238 numOptionalArgs: props.numOptionalArgs || 0, 5239 handler: handler 5240 }; 5241 for (var i = 0; i < names.length; ++i) { 5242 module.exports[names[i]] = data; 5243 } 5244} 5245 5246// Arrays are part of LaTeX, defined in lttab.dtx so its documentation 5247// is part of the source2e.pdf file of LaTeX2e source documentation. 5248defineEnvironment("array", { 5249 numArgs: 1 5250}, function(context, args) { 5251 var colalign = args[0]; 5252 colalign = colalign.value.map ? colalign.value : [colalign]; 5253 var cols = colalign.map(function(node) { 5254 var ca = node.value; 5255 if ("lcr".indexOf(ca) !== -1) { 5256 return { 5257 type: "align", 5258 align: ca 5259 }; 5260 } else if (ca === "|") { 5261 return { 5262 type: "separator", 5263 separator: "|" 5264 }; 5265 } 5266 throw new ParseError( 5267 "Unknown column alignment: " + node.value, 5268 node); 5269 }); 5270 var res = { 5271 type: "array", 5272 cols: cols, 5273 hskipBeforeAndAfter: true // \@preamble in lttab.dtx 5274 }; 5275 res = parseArray(context.parser, res); 5276 return res; 5277}); 5278 5279// The matrix environments of amsmath builds on the array environment 5280// of LaTeX, which is discussed above. 5281defineEnvironment([ 5282 "matrix", 5283 "pmatrix", 5284 "bmatrix", 5285 "Bmatrix", 5286 "vmatrix", 5287 "Vmatrix" 5288], { 5289}, function(context) { 5290 var delimiters = { 5291 "matrix": null, 5292 "pmatrix": ["(", ")"], 5293 "bmatrix": ["[", "]"], 5294 "Bmatrix": ["\\{", "\\}"], 5295 "vmatrix": ["|", "|"], 5296 "Vmatrix": ["\\Vert", "\\Vert"] 5297 }[context.envName]; 5298 var res = { 5299 type: "array", 5300 hskipBeforeAndAfter: false // \hskip -\arraycolsep in amsmath 5301 }; 5302 res = parseArray(context.parser, res); 5303 if (delimiters) { 5304 res = new ParseNode("leftright", { 5305 body: [res], 5306 left: delimiters[0], 5307 right: delimiters[1] 5308 }, context.mode); 5309 } 5310 return res; 5311}); 5312 5313// A cases environment (in amsmath.sty) is almost equivalent to 5314// \def\arraystretch{1.2}% 5315// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. 5316defineEnvironment("cases", { 5317}, function(context) { 5318 var res = { 5319 type: "array", 5320 arraystretch: 1.2, 5321 cols: [{ 5322 type: "align", 5323 align: "l", 5324 pregap: 0, 5325 // TODO(kevinb) get the current style. 5326 // For now we use the metrics for TEXT style which is what we were 5327 // doing before. Before attempting to get the current style we 5328 // should look at TeX's behavior especially for \over and matrices. 5329 postgap: Style.TEXT.metrics.quad 5330 }, { 5331 type: "align", 5332 align: "l", 5333 pregap: 0, 5334 postgap: 0 5335 }] 5336 }; 5337 res = parseArray(context.parser, res); 5338 res = new ParseNode("leftright", { 5339 body: [res], 5340 left: "\\{", 5341 right: "." 5342 }, context.mode); 5343 return res; 5344}); 5345 5346// An aligned environment is like the align* environment 5347// except it operates within math mode. 5348// Note that we assume \nomallineskiplimit to be zero, 5349// so that \strut@ is the same as \strut. 5350defineEnvironment("aligned", { 5351}, function(context) { 5352 var res = { 5353 type: "array", 5354 cols: [] 5355 }; 5356 res = parseArray(context.parser, res); 5357 var emptyGroup = new ParseNode("ordgroup", [], context.mode); 5358 var numCols = 0; 5359 res.value.body.forEach(function(row) { 5360 var i; 5361 for (i = 1; i < row.length; i += 2) { 5362 row[i].value.unshift(emptyGroup); 5363 } 5364 if (numCols < row.length) { 5365 numCols = row.length; 5366 } 5367 }); 5368 for (var i = 0; i < numCols; ++i) { 5369 var align = "r"; 5370 var pregap = 0; 5371 if (i % 2 === 1) { 5372 align = "l"; 5373 } else if (i > 0) { 5374 pregap = 2; // one \qquad between columns 5375 } 5376 res.value.cols[i] = { 5377 type: "align", 5378 align: align, 5379 pregap: pregap, 5380 postgap: 0 5381 }; 5382 } 5383 return res; 5384}); 5385 5386},{"./ParseError":6,"./Style":9,"./parseData":21}],17:[function(require,module,exports){ 5387/* eslint no-unused-vars:0 */ 5388 5389var Style = require("./Style"); 5390var cjkRegex = require("./unicodeRegexes").cjkRegex; 5391 5392/** 5393 * This file contains metrics regarding fonts and individual symbols. The sigma 5394 * and xi variables, as well as the metricMap map contain data extracted from 5395 * TeX, TeX font metrics, and the TTF files. These data are then exposed via the 5396 * `metrics` variable and the getCharacterMetrics function. 5397 */ 5398 5399// In TeX, there are actually three sets of dimensions, one for each of 5400// textstyle, scriptstyle, and scriptscriptstyle. These are provided in the 5401// the arrays below, in that order. 5402// 5403// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively. 5404// This was determined by running the folllowing script: 5405// 5406// latex -interaction=nonstopmode \ 5407// '\documentclass{article}\usepackage{amsmath}\begin{document}' \ 5408// '$a$ \expandafter\show\the\textfont2' \ 5409// '\expandafter\show\the\scriptfont2' \ 5410// '\expandafter\show\the\scriptscriptfont2' \ 5411// '\stop' 5412// 5413// The metrics themselves were retreived using the following commands: 5414// 5415// tftopl cmsy10 5416// tftopl cmsy7 5417// tftopl cmsy5 5418// 5419// The output of each of these commands is quite lengthy. The only part we 5420// care about is the FONTDIMEN section. Each value is measured in EMs. 5421var sigmas = { 5422 slant: [0.250, 0.250, 0.250], // sigma1 5423 space: [0.000, 0.000, 0.000], // sigma2 5424 stretch: [0.000, 0.000, 0.000], // sigma3 5425 shrink: [0.000, 0.000, 0.000], // sigma4 5426 xHeight: [0.431, 0.431, 0.431], // sigma5 5427 quad: [1.000, 1.171, 1.472], // sigma6 5428 extraSpace: [0.000, 0.000, 0.000], // sigma7 5429 num1: [0.677, 0.732, 0.925], // sigma8 5430 num2: [0.394, 0.384, 0.387], // sigma9 5431 num3: [0.444, 0.471, 0.504], // sigma10 5432 denom1: [0.686, 0.752, 1.025], // sigma11 5433 denom2: [0.345, 0.344, 0.532], // sigma12 5434 sup1: [0.413, 0.503, 0.504], // sigma13 5435 sup2: [0.363, 0.431, 0.404], // sigma14 5436 sup3: [0.289, 0.286, 0.294], // sigma15 5437 sub1: [0.150, 0.143, 0.200], // sigma16 5438 sub2: [0.247, 0.286, 0.400], // sigma17 5439 supDrop: [0.386, 0.353, 0.494], // sigma18 5440 subDrop: [0.050, 0.071, 0.100], // sigma19 5441 delim1: [2.390, 1.700, 1.980], // sigma20 5442 delim2: [1.010, 1.157, 1.420], // sigma21 5443 axisHeight: [0.250, 0.250, 0.250] // sigma22 5444}; 5445 5446// These font metrics are extracted from TeX by using 5447// \font\a=cmex10 5448// \showthe\fontdimenX\a 5449// where X is the corresponding variable number. These correspond to the font 5450// parameters of the extension fonts (family 3). See the TeXbook, page 441. 5451var xi1 = 0; 5452var xi2 = 0; 5453var xi3 = 0; 5454var xi4 = 0; 5455var xi5 = 0.431; 5456var xi6 = 1; 5457var xi7 = 0; 5458var xi8 = 0.04; 5459var xi9 = 0.111; 5460var xi10 = 0.166; 5461var xi11 = 0.2; 5462var xi12 = 0.6; 5463var xi13 = 0.1; 5464 5465// This value determines how large a pt is, for metrics which are defined in 5466// terms of pts. 5467// This value is also used in katex.less; if you change it make sure the values 5468// match. 5469var ptPerEm = 10.0; 5470 5471// The space between adjacent `|` columns in an array definition. From 5472// `\showthe\doublerulesep` in LaTeX. 5473var doubleRuleSep = 2.0 / ptPerEm; 5474 5475/** 5476 * This is just a mapping from common names to real metrics 5477 */ 5478var metrics = { 5479 defaultRuleThickness: xi8, 5480 bigOpSpacing1: xi9, 5481 bigOpSpacing2: xi10, 5482 bigOpSpacing3: xi11, 5483 bigOpSpacing4: xi12, 5484 bigOpSpacing5: xi13, 5485 ptPerEm: ptPerEm, 5486 doubleRuleSep: doubleRuleSep 5487}; 5488 5489// This map contains a mapping from font name and character code to character 5490// metrics, including height, depth, italic correction, and skew (kern from the 5491// character to the corresponding \skewchar) 5492// This map is generated via `make metrics`. It should not be changed manually. 5493var metricMap = require("./fontMetricsData"); 5494 5495// These are very rough approximations. We default to Times New Roman which 5496// should have Latin-1 and Cyrillic characters, but may not depending on the 5497// operating system. The metrics do not account for extra height from the 5498// accents. In the case of Cyrillic characters which have both ascenders and 5499// descenders we prefer approximations with ascenders, primarily to prevent 5500// the fraction bar or root line from intersecting the glyph. 5501// TODO(kevinb) allow union of multiple glyph metrics for better accuracy. 5502var extraCharacterMap = { 5503 // Latin-1 5504 'À': 'A', 5505 'Á': 'A', 5506 'Â': 'A', 5507 'Ã': 'A', 5508 'Ä': 'A', 5509 'Å': 'A', 5510 'Æ': 'A', 5511 'Ç': 'C', 5512 'È': 'E', 5513 'É': 'E', 5514 'Ê': 'E', 5515 'Ë': 'E', 5516 'Ì': 'I', 5517 'Í': 'I', 5518 'Î': 'I', 5519 'Ï': 'I', 5520 'Ð': 'D', 5521 'Ñ': 'N', 5522 'Ò': 'O', 5523 'Ó': 'O', 5524 'Ô': 'O', 5525 'Õ': 'O', 5526 'Ö': 'O', 5527 'Ø': 'O', 5528 'Ù': 'U', 5529 'Ú': 'U', 5530 'Û': 'U', 5531 'Ü': 'U', 5532 'Ý': 'Y', 5533 'Þ': 'o', 5534 'ß': 'B', 5535 'à': 'a', 5536 'á': 'a', 5537 'â': 'a', 5538 'ã': 'a', 5539 'ä': 'a', 5540 'å': 'a', 5541 'æ': 'a', 5542 'ç': 'c', 5543 'è': 'e', 5544 'é': 'e', 5545 'ê': 'e', 5546 'ë': 'e', 5547 'ì': 'i', 5548 'í': 'i', 5549 'î': 'i', 5550 'ï': 'i', 5551 'ð': 'd', 5552 'ñ': 'n', 5553 'ò': 'o', 5554 'ó': 'o', 5555 'ô': 'o', 5556 'õ': 'o', 5557 'ö': 'o', 5558 'ø': 'o', 5559 'ù': 'u', 5560 'ú': 'u', 5561 'û': 'u', 5562 'ü': 'u', 5563 'ý': 'y', 5564 'þ': 'o', 5565 'ÿ': 'y', 5566 5567 // Cyrillic 5568 'А': 'A', 5569 'Б': 'B', 5570 'В': 'B', 5571 'Г': 'F', 5572 'Д': 'A', 5573 'Е': 'E', 5574 'Ж': 'K', 5575 'З': '3', 5576 'И': 'N', 5577 'Й': 'N', 5578 'К': 'K', 5579 'Л': 'N', 5580 'М': 'M', 5581 'Н': 'H', 5582 'О': 'O', 5583 'П': 'N', 5584 'Р': 'P', 5585 'С': 'C', 5586 'Т': 'T', 5587 'У': 'y', 5588 'Ф': 'O', 5589 'Х': 'X', 5590 'Ц': 'U', 5591 'Ч': 'h', 5592 'Ш': 'W', 5593 'Щ': 'W', 5594 'Ъ': 'B', 5595 'Ы': 'X', 5596 'Ь': 'B', 5597 'Э': '3', 5598 'Ю': 'X', 5599 'Я': 'R', 5600 'а': 'a', 5601 'б': 'b', 5602 'в': 'a', 5603 'г': 'r', 5604 'д': 'y', 5605 'е': 'e', 5606 'ж': 'm', 5607 'з': 'e', 5608 'и': 'n', 5609 'й': 'n', 5610 'к': 'n', 5611 'л': 'n', 5612 'м': 'm', 5613 'н': 'n', 5614 'о': 'o', 5615 'п': 'n', 5616 'р': 'p', 5617 'с': 'c', 5618 'т': 'o', 5619 'у': 'y', 5620 'ф': 'b', 5621 'х': 'x', 5622 'ц': 'n', 5623 'ч': 'n', 5624 'ш': 'w', 5625 'щ': 'w', 5626 'ъ': 'a', 5627 'ы': 'm', 5628 'ь': 'a', 5629 'э': 'e', 5630 'ю': 'm', 5631 'я': 'r' 5632}; 5633 5634/** 5635 * This function is a convenience function for looking up information in the 5636 * metricMap table. It takes a character as a string, and a style. 5637 * 5638 * Note: the `width` property may be undefined if fontMetricsData.js wasn't 5639 * built using `Make extended_metrics`. 5640 */ 5641var getCharacterMetrics = function(character, style) { 5642 var ch = character.charCodeAt(0); 5643 if (character[0] in extraCharacterMap) { 5644 ch = extraCharacterMap[character[0]].charCodeAt(0); 5645 } else if (cjkRegex.test(character[0])) { 5646 ch = 'M'.charCodeAt(0); 5647 } 5648 var metrics = metricMap[style][ch]; 5649 if (metrics) { 5650 return { 5651 depth: metrics[0], 5652 height: metrics[1], 5653 italic: metrics[2], 5654 skew: metrics[3], 5655 width: metrics[4] 5656 }; 5657 } 5658}; 5659 5660module.exports = { 5661 metrics: metrics, 5662 sigmas: sigmas, 5663 getCharacterMetrics: getCharacterMetrics 5664}; 5665 5666},{"./Style":9,"./fontMetricsData":18,"./unicodeRegexes":24}],18:[function(require,module,exports){ 5667module.exports = { 5668 "AMS-Regular": { 5669 "65": [0, 0.68889, 0, 0], 5670 "66": [0, 0.68889, 0, 0], 5671 "67": [0, 0.68889, 0, 0], 5672 "68": [0, 0.68889, 0, 0], 5673 "69": [0, 0.68889, 0, 0], 5674 "70": [0, 0.68889, 0, 0], 5675 "71": [0, 0.68889, 0, 0], 5676 "72": [0, 0.68889, 0, 0], 5677 "73": [0, 0.68889, 0, 0], 5678 "74": [0.16667, 0.68889, 0, 0], 5679 "75": [0, 0.68889, 0, 0], 5680 "76": [0, 0.68889, 0, 0], 5681 "77": [0, 0.68889, 0, 0], 5682 "78": [0, 0.68889, 0, 0], 5683 "79": [0.16667, 0.68889, 0, 0], 5684 "80": [0, 0.68889, 0, 0], 5685 "81": [0.16667, 0.68889, 0, 0], 5686 "82": [0, 0.68889, 0, 0], 5687 "83": [0, 0.68889, 0, 0], 5688 "84": [0, 0.68889, 0, 0], 5689 "85": [0, 0.68889, 0, 0], 5690 "86": [0, 0.68889, 0, 0], 5691 "87": [0, 0.68889, 0, 0], 5692 "88": [0, 0.68889, 0, 0], 5693 "89": [0, 0.68889, 0, 0], 5694 "90": [0, 0.68889, 0, 0], 5695 "107": [0, 0.68889, 0, 0], 5696 "165": [0, 0.675, 0.025, 0], 5697 "174": [0.15559, 0.69224, 0, 0], 5698 "240": [0, 0.68889, 0, 0], 5699 "295": [0, 0.68889, 0, 0], 5700 "710": [0, 0.825, 0, 0], 5701 "732": [0, 0.9, 0, 0], 5702 "770": [0, 0.825, 0, 0], 5703 "771": [0, 0.9, 0, 0], 5704 "989": [0.08167, 0.58167, 0, 0], 5705 "1008": [0, 0.43056, 0.04028, 0], 5706 "8245": [0, 0.54986, 0, 0], 5707 "8463": [0, 0.68889, 0, 0], 5708 "8487": [0, 0.68889, 0, 0], 5709 "8498": [0, 0.68889, 0, 0], 5710 "8502": [0, 0.68889, 0, 0], 5711 "8503": [0, 0.68889, 0, 0], 5712 "8504": [0, 0.68889, 0, 0], 5713 "8513": [0, 0.68889, 0, 0], 5714 "8592": [-0.03598, 0.46402, 0, 0], 5715 "8594": [-0.03598, 0.46402, 0, 0], 5716 "8602": [-0.13313, 0.36687, 0, 0], 5717 "8603": [-0.13313, 0.36687, 0, 0], 5718 "8606": [0.01354, 0.52239, 0, 0], 5719 "8608": [0.01354, 0.52239, 0, 0], 5720 "8610": [0.01354, 0.52239, 0, 0], 5721 "8611": [0.01354, 0.52239, 0, 0], 5722 "8619": [0, 0.54986, 0, 0], 5723 "8620": [0, 0.54986, 0, 0], 5724 "8621": [-0.13313, 0.37788, 0, 0], 5725 "8622": [-0.13313, 0.36687, 0, 0], 5726 "8624": [0, 0.69224, 0, 0], 5727 "8625": [0, 0.69224, 0, 0], 5728 "8630": [0, 0.43056, 0, 0], 5729 "8631": [0, 0.43056, 0, 0], 5730 "8634": [0.08198, 0.58198, 0, 0], 5731 "8635": [0.08198, 0.58198, 0, 0], 5732 "8638": [0.19444, 0.69224, 0, 0], 5733 "8639": [0.19444, 0.69224, 0, 0], 5734 "8642": [0.19444, 0.69224, 0, 0], 5735 "8643": [0.19444, 0.69224, 0, 0], 5736 "8644": [0.1808, 0.675, 0, 0], 5737 "8646": [0.1808, 0.675, 0, 0], 5738 "8647": [0.1808, 0.675, 0, 0], 5739 "8648": [0.19444, 0.69224, 0, 0], 5740 "8649": [0.1808, 0.675, 0, 0], 5741 "8650": [0.19444, 0.69224, 0, 0], 5742 "8651": [0.01354, 0.52239, 0, 0], 5743 "8652": [0.01354, 0.52239, 0, 0], 5744 "8653": [-0.13313, 0.36687, 0, 0], 5745 "8654": [-0.13313, 0.36687, 0, 0], 5746 "8655": [-0.13313, 0.36687, 0, 0], 5747 "8666": [0.13667, 0.63667, 0, 0], 5748 "8667": [0.13667, 0.63667, 0, 0], 5749 "8669": [-0.13313, 0.37788, 0, 0], 5750 "8672": [-0.064, 0.437, 0, 0], 5751 "8674": [-0.064, 0.437, 0, 0], 5752 "8705": [0, 0.825, 0, 0], 5753 "8708": [0, 0.68889, 0, 0], 5754 "8709": [0.08167, 0.58167, 0, 0], 5755 "8717": [0, 0.43056, 0, 0], 5756 "8722": [-0.03598, 0.46402, 0, 0], 5757 "8724": [0.08198, 0.69224, 0, 0], 5758 "8726": [0.08167, 0.58167, 0, 0], 5759 "8733": [0, 0.69224, 0, 0], 5760 "8736": [0, 0.69224, 0, 0], 5761 "8737": [0, 0.69224, 0, 0], 5762 "8738": [0.03517, 0.52239, 0, 0], 5763 "8739": [0.08167, 0.58167, 0, 0], 5764 "8740": [0.25142, 0.74111, 0, 0], 5765 "8741": [0.08167, 0.58167, 0, 0], 5766 "8742": [0.25142, 0.74111, 0, 0], 5767 "8756": [0, 0.69224, 0, 0], 5768 "8757": [0, 0.69224, 0, 0], 5769 "8764": [-0.13313, 0.36687, 0, 0], 5770 "8765": [-0.13313, 0.37788, 0, 0], 5771 "8769": [-0.13313, 0.36687, 0, 0], 5772 "8770": [-0.03625, 0.46375, 0, 0], 5773 "8774": [0.30274, 0.79383, 0, 0], 5774 "8776": [-0.01688, 0.48312, 0, 0], 5775 "8778": [0.08167, 0.58167, 0, 0], 5776 "8782": [0.06062, 0.54986, 0, 0], 5777 "8783": [0.06062, 0.54986, 0, 0], 5778 "8785": [0.08198, 0.58198, 0, 0], 5779 "8786": [0.08198, 0.58198, 0, 0], 5780 "8787": [0.08198, 0.58198, 0, 0], 5781 "8790": [0, 0.69224, 0, 0], 5782 "8791": [0.22958, 0.72958, 0, 0], 5783 "8796": [0.08198, 0.91667, 0, 0], 5784 "8806": [0.25583, 0.75583, 0, 0], 5785 "8807": [0.25583, 0.75583, 0, 0], 5786 "8808": [0.25142, 0.75726, 0, 0], 5787 "8809": [0.25142, 0.75726, 0, 0], 5788 "8812": [0.25583, 0.75583, 0, 0], 5789 "8814": [0.20576, 0.70576, 0, 0], 5790 "8815": [0.20576, 0.70576, 0, 0], 5791 "8816": [0.30274, 0.79383, 0, 0], 5792 "8817": [0.30274, 0.79383, 0, 0], 5793 "8818": [0.22958, 0.72958, 0, 0], 5794 "8819": [0.22958, 0.72958, 0, 0], 5795 "8822": [0.1808, 0.675, 0, 0], 5796 "8823": [0.1808, 0.675, 0, 0], 5797 "8828": [0.13667, 0.63667, 0, 0], 5798 "8829": [0.13667, 0.63667, 0, 0], 5799 "8830": [0.22958, 0.72958, 0, 0], 5800 "8831": [0.22958, 0.72958, 0, 0], 5801 "8832": [0.20576, 0.70576, 0, 0], 5802 "8833": [0.20576, 0.70576, 0, 0], 5803 "8840": [0.30274, 0.79383, 0, 0], 5804 "8841": [0.30274, 0.79383, 0, 0], 5805 "8842": [0.13597, 0.63597, 0, 0], 5806 "8843": [0.13597, 0.63597, 0, 0], 5807 "8847": [0.03517, 0.54986, 0, 0], 5808 "8848": [0.03517, 0.54986, 0, 0], 5809 "8858": [0.08198, 0.58198, 0, 0], 5810 "8859": [0.08198, 0.58198, 0, 0], 5811 "8861": [0.08198, 0.58198, 0, 0], 5812 "8862": [0, 0.675, 0, 0], 5813 "8863": [0, 0.675, 0, 0], 5814 "8864": [0, 0.675, 0, 0], 5815 "8865": [0, 0.675, 0, 0], 5816 "8872": [0, 0.69224, 0, 0], 5817 "8873": [0, 0.69224, 0, 0], 5818 "8874": [0, 0.69224, 0, 0], 5819 "8876": [0, 0.68889, 0, 0], 5820 "8877": [0, 0.68889, 0, 0], 5821 "8878": [0, 0.68889, 0, 0], 5822 "8879": [0, 0.68889, 0, 0], 5823 "8882": [0.03517, 0.54986, 0, 0], 5824 "8883": [0.03517, 0.54986, 0, 0], 5825 "8884": [0.13667, 0.63667, 0, 0], 5826 "8885": [0.13667, 0.63667, 0, 0], 5827 "8888": [0, 0.54986, 0, 0], 5828 "8890": [0.19444, 0.43056, 0, 0], 5829 "8891": [0.19444, 0.69224, 0, 0], 5830 "8892": [0.19444, 0.69224, 0, 0], 5831 "8901": [0, 0.54986, 0, 0], 5832 "8903": [0.08167, 0.58167, 0, 0], 5833 "8905": [0.08167, 0.58167, 0, 0], 5834 "8906": [0.08167, 0.58167, 0, 0], 5835 "8907": [0, 0.69224, 0, 0], 5836 "8908": [0, 0.69224, 0, 0], 5837 "8909": [-0.03598, 0.46402, 0, 0], 5838 "8910": [0, 0.54986, 0, 0], 5839 "8911": [0, 0.54986, 0, 0], 5840 "8912": [0.03517, 0.54986, 0, 0], 5841 "8913": [0.03517, 0.54986, 0, 0], 5842 "8914": [0, 0.54986, 0, 0], 5843 "8915": [0, 0.54986, 0, 0], 5844 "8916": [0, 0.69224, 0, 0], 5845 "8918": [0.0391, 0.5391, 0, 0], 5846 "8919": [0.0391, 0.5391, 0, 0], 5847 "8920": [0.03517, 0.54986, 0, 0], 5848 "8921": [0.03517, 0.54986, 0, 0], 5849 "8922": [0.38569, 0.88569, 0, 0], 5850 "8923": [0.38569, 0.88569, 0, 0], 5851 "8926": [0.13667, 0.63667, 0, 0], 5852 "8927": [0.13667, 0.63667, 0, 0], 5853 "8928": [0.30274, 0.79383, 0, 0], 5854 "8929": [0.30274, 0.79383, 0, 0], 5855 "8934": [0.23222, 0.74111, 0, 0], 5856 "8935": [0.23222, 0.74111, 0, 0], 5857 "8936": [0.23222, 0.74111, 0, 0], 5858 "8937": [0.23222, 0.74111, 0, 0], 5859 "8938": [0.20576, 0.70576, 0, 0], 5860 "8939": [0.20576, 0.70576, 0, 0], 5861 "8940": [0.30274, 0.79383, 0, 0], 5862 "8941": [0.30274, 0.79383, 0, 0], 5863 "8994": [0.19444, 0.69224, 0, 0], 5864 "8995": [0.19444, 0.69224, 0, 0], 5865 "9416": [0.15559, 0.69224, 0, 0], 5866 "9484": [0, 0.69224, 0, 0], 5867 "9488": [0, 0.69224, 0, 0], 5868 "9492": [0, 0.37788, 0, 0], 5869 "9496": [0, 0.37788, 0, 0], 5870 "9585": [0.19444, 0.68889, 0, 0], 5871 "9586": [0.19444, 0.74111, 0, 0], 5872 "9632": [0, 0.675, 0, 0], 5873 "9633": [0, 0.675, 0, 0], 5874 "9650": [0, 0.54986, 0, 0], 5875 "9651": [0, 0.54986, 0, 0], 5876 "9654": [0.03517, 0.54986, 0, 0], 5877 "9660": [0, 0.54986, 0, 0], 5878 "9661": [0, 0.54986, 0, 0], 5879 "9664": [0.03517, 0.54986, 0, 0], 5880 "9674": [0.11111, 0.69224, 0, 0], 5881 "9733": [0.19444, 0.69224, 0, 0], 5882 "10003": [0, 0.69224, 0, 0], 5883 "10016": [0, 0.69224, 0, 0], 5884 "10731": [0.11111, 0.69224, 0, 0], 5885 "10846": [0.19444, 0.75583, 0, 0], 5886 "10877": [0.13667, 0.63667, 0, 0], 5887 "10878": [0.13667, 0.63667, 0, 0], 5888 "10885": [0.25583, 0.75583, 0, 0], 5889 "10886": [0.25583, 0.75583, 0, 0], 5890 "10887": [0.13597, 0.63597, 0, 0], 5891 "10888": [0.13597, 0.63597, 0, 0], 5892 "10889": [0.26167, 0.75726, 0, 0], 5893 "10890": [0.26167, 0.75726, 0, 0], 5894 "10891": [0.48256, 0.98256, 0, 0], 5895 "10892": [0.48256, 0.98256, 0, 0], 5896 "10901": [0.13667, 0.63667, 0, 0], 5897 "10902": [0.13667, 0.63667, 0, 0], 5898 "10933": [0.25142, 0.75726, 0, 0], 5899 "10934": [0.25142, 0.75726, 0, 0], 5900 "10935": [0.26167, 0.75726, 0, 0], 5901 "10936": [0.26167, 0.75726, 0, 0], 5902 "10937": [0.26167, 0.75726, 0, 0], 5903 "10938": [0.26167, 0.75726, 0, 0], 5904 "10949": [0.25583, 0.75583, 0, 0], 5905 "10950": [0.25583, 0.75583, 0, 0], 5906 "10955": [0.28481, 0.79383, 0, 0], 5907 "10956": [0.28481, 0.79383, 0, 0], 5908 "57350": [0.08167, 0.58167, 0, 0], 5909 "57351": [0.08167, 0.58167, 0, 0], 5910 "57352": [0.08167, 0.58167, 0, 0], 5911 "57353": [0, 0.43056, 0.04028, 0], 5912 "57356": [0.25142, 0.75726, 0, 0], 5913 "57357": [0.25142, 0.75726, 0, 0], 5914 "57358": [0.41951, 0.91951, 0, 0], 5915 "57359": [0.30274, 0.79383, 0, 0], 5916 "57360": [0.30274, 0.79383, 0, 0], 5917 "57361": [0.41951, 0.91951, 0, 0], 5918 "57366": [0.25142, 0.75726, 0, 0], 5919 "57367": [0.25142, 0.75726, 0, 0], 5920 "57368": [0.25142, 0.75726, 0, 0], 5921 "57369": [0.25142, 0.75726, 0, 0], 5922 "57370": [0.13597, 0.63597, 0, 0], 5923 "57371": [0.13597, 0.63597, 0, 0] 5924 }, 5925 "Caligraphic-Regular": { 5926 "48": [0, 0.43056, 0, 0], 5927 "49": [0, 0.43056, 0, 0], 5928 "50": [0, 0.43056, 0, 0], 5929 "51": [0.19444, 0.43056, 0, 0], 5930 "52": [0.19444, 0.43056, 0, 0], 5931 "53": [0.19444, 0.43056, 0, 0], 5932 "54": [0, 0.64444, 0, 0], 5933 "55": [0.19444, 0.43056, 0, 0], 5934 "56": [0, 0.64444, 0, 0], 5935 "57": [0.19444, 0.43056, 0, 0], 5936 "65": [0, 0.68333, 0, 0.19445], 5937 "66": [0, 0.68333, 0.03041, 0.13889], 5938 "67": [0, 0.68333, 0.05834, 0.13889], 5939 "68": [0, 0.68333, 0.02778, 0.08334], 5940 "69": [0, 0.68333, 0.08944, 0.11111], 5941 "70": [0, 0.68333, 0.09931, 0.11111], 5942 "71": [0.09722, 0.68333, 0.0593, 0.11111], 5943 "72": [0, 0.68333, 0.00965, 0.11111], 5944 "73": [0, 0.68333, 0.07382, 0], 5945 "74": [0.09722, 0.68333, 0.18472, 0.16667], 5946 "75": [0, 0.68333, 0.01445, 0.05556], 5947 "76": [0, 0.68333, 0, 0.13889], 5948 "77": [0, 0.68333, 0, 0.13889], 5949 "78": [0, 0.68333, 0.14736, 0.08334], 5950 "79": [0, 0.68333, 0.02778, 0.11111], 5951 "80": [0, 0.68333, 0.08222, 0.08334], 5952 "81": [0.09722, 0.68333, 0, 0.11111], 5953 "82": [0, 0.68333, 0, 0.08334], 5954 "83": [0, 0.68333, 0.075, 0.13889], 5955 "84": [0, 0.68333, 0.25417, 0], 5956 "85": [0, 0.68333, 0.09931, 0.08334], 5957 "86": [0, 0.68333, 0.08222, 0], 5958 "87": [0, 0.68333, 0.08222, 0.08334], 5959 "88": [0, 0.68333, 0.14643, 0.13889], 5960 "89": [0.09722, 0.68333, 0.08222, 0.08334], 5961 "90": [0, 0.68333, 0.07944, 0.13889] 5962 }, 5963 "Fraktur-Regular": { 5964 "33": [0, 0.69141, 0, 0], 5965 "34": [0, 0.69141, 0, 0], 5966 "38": [0, 0.69141, 0, 0], 5967 "39": [0, 0.69141, 0, 0], 5968 "40": [0.24982, 0.74947, 0, 0], 5969 "41": [0.24982, 0.74947, 0, 0], 5970 "42": [0, 0.62119, 0, 0], 5971 "43": [0.08319, 0.58283, 0, 0], 5972 "44": [0, 0.10803, 0, 0], 5973 "45": [0.08319, 0.58283, 0, 0], 5974 "46": [0, 0.10803, 0, 0], 5975 "47": [0.24982, 0.74947, 0, 0], 5976 "48": [0, 0.47534, 0, 0], 5977 "49": [0, 0.47534, 0, 0], 5978 "50": [0, 0.47534, 0, 0], 5979 "51": [0.18906, 0.47534, 0, 0], 5980 "52": [0.18906, 0.47534, 0, 0], 5981 "53": [0.18906, 0.47534, 0, 0], 5982 "54": [0, 0.69141, 0, 0], 5983 "55": [0.18906, 0.47534, 0, 0], 5984 "56": [0, 0.69141, 0, 0], 5985 "57": [0.18906, 0.47534, 0, 0], 5986 "58": [0, 0.47534, 0, 0], 5987 "59": [0.12604, 0.47534, 0, 0], 5988 "61": [-0.13099, 0.36866, 0, 0], 5989 "63": [0, 0.69141, 0, 0], 5990 "65": [0, 0.69141, 0, 0], 5991 "66": [0, 0.69141, 0, 0], 5992 "67": [0, 0.69141, 0, 0], 5993 "68": [0, 0.69141, 0, 0], 5994 "69": [0, 0.69141, 0, 0], 5995 "70": [0.12604, 0.69141, 0, 0], 5996 "71": [0, 0.69141, 0, 0], 5997 "72": [0.06302, 0.69141, 0, 0], 5998 "73": [0, 0.69141, 0, 0], 5999 "74": [0.12604, 0.69141, 0, 0], 6000 "75": [0, 0.69141, 0, 0], 6001 "76": [0, 0.69141, 0, 0], 6002 "77": [0, 0.69141, 0, 0], 6003 "78": [0, 0.69141, 0, 0], 6004 "79": [0, 0.69141, 0, 0], 6005 "80": [0.18906, 0.69141, 0, 0], 6006 "81": [0.03781, 0.69141, 0, 0], 6007 "82": [0, 0.69141, 0, 0], 6008 "83": [0, 0.69141, 0, 0], 6009 "84": [0, 0.69141, 0, 0], 6010 "85": [0, 0.69141, 0, 0], 6011 "86": [0, 0.69141, 0, 0], 6012 "87": [0, 0.69141, 0, 0], 6013 "88": [0, 0.69141, 0, 0], 6014 "89": [0.18906, 0.69141, 0, 0], 6015 "90": [0.12604, 0.69141, 0, 0], 6016 "91": [0.24982, 0.74947, 0, 0], 6017 "93": [0.24982, 0.74947, 0, 0], 6018 "94": [0, 0.69141, 0, 0], 6019 "97": [0, 0.47534, 0, 0], 6020 "98": [0, 0.69141, 0, 0], 6021 "99": [0, 0.47534, 0, 0], 6022 "100": [0, 0.62119, 0, 0], 6023 "101": [0, 0.47534, 0, 0], 6024 "102": [0.18906, 0.69141, 0, 0], 6025 "103": [0.18906, 0.47534, 0, 0], 6026 "104": [0.18906, 0.69141, 0, 0], 6027 "105": [0, 0.69141, 0, 0], 6028 "106": [0, 0.69141, 0, 0], 6029 "107": [0, 0.69141, 0, 0], 6030 "108": [0, 0.69141, 0, 0], 6031 "109": [0, 0.47534, 0, 0], 6032 "110": [0, 0.47534, 0, 0], 6033 "111": [0, 0.47534, 0, 0], 6034 "112": [0.18906, 0.52396, 0, 0], 6035 "113": [0.18906, 0.47534, 0, 0], 6036 "114": [0, 0.47534, 0, 0], 6037 "115": [0, 0.47534, 0, 0], 6038 "116": [0, 0.62119, 0, 0], 6039 "117": [0, 0.47534, 0, 0], 6040 "118": [0, 0.52396, 0, 0], 6041 "119": [0, 0.52396, 0, 0], 6042 "120": [0.18906, 0.47534, 0, 0], 6043 "121": [0.18906, 0.47534, 0, 0], 6044 "122": [0.18906, 0.47534, 0, 0], 6045 "8216": [0, 0.69141, 0, 0], 6046 "8217": [0, 0.69141, 0, 0], 6047 "58112": [0, 0.62119, 0, 0], 6048 "58113": [0, 0.62119, 0, 0], 6049 "58114": [0.18906, 0.69141, 0, 0], 6050 "58115": [0.18906, 0.69141, 0, 0], 6051 "58116": [0.18906, 0.47534, 0, 0], 6052 "58117": [0, 0.69141, 0, 0], 6053 "58118": [0, 0.62119, 0, 0], 6054 "58119": [0, 0.47534, 0, 0] 6055 }, 6056 "Main-Bold": { 6057 "33": [0, 0.69444, 0, 0], 6058 "34": [0, 0.69444, 0, 0], 6059 "35": [0.19444, 0.69444, 0, 0], 6060 "36": [0.05556, 0.75, 0, 0], 6061 "37": [0.05556, 0.75, 0, 0], 6062 "38": [0, 0.69444, 0, 0], 6063 "39": [0, 0.69444, 0, 0], 6064 "40": [0.25, 0.75, 0, 0], 6065 "41": [0.25, 0.75, 0, 0], 6066 "42": [0, 0.75, 0, 0], 6067 "43": [0.13333, 0.63333, 0, 0], 6068 "44": [0.19444, 0.15556, 0, 0], 6069 "45": [0, 0.44444, 0, 0], 6070 "46": [0, 0.15556, 0, 0], 6071 "47": [0.25, 0.75, 0, 0], 6072 "48": [0, 0.64444, 0, 0], 6073 "49": [0, 0.64444, 0, 0], 6074 "50": [0, 0.64444, 0, 0], 6075 "51": [0, 0.64444, 0, 0], 6076 "52": [0, 0.64444, 0, 0], 6077 "53": [0, 0.64444, 0, 0], 6078 "54": [0, 0.64444, 0, 0], 6079 "55": [0, 0.64444, 0, 0], 6080 "56": [0, 0.64444, 0, 0], 6081 "57": [0, 0.64444, 0, 0], 6082 "58": [0, 0.44444, 0, 0], 6083 "59": [0.19444, 0.44444, 0, 0], 6084 "60": [0.08556, 0.58556, 0, 0], 6085 "61": [-0.10889, 0.39111, 0, 0], 6086 "62": [0.08556, 0.58556, 0, 0], 6087 "63": [0, 0.69444, 0, 0], 6088 "64": [0, 0.69444, 0, 0], 6089 "65": [0, 0.68611, 0, 0], 6090 "66": [0, 0.68611, 0, 0], 6091 "67": [0, 0.68611, 0, 0], 6092 "68": [0, 0.68611, 0, 0], 6093 "69": [0, 0.68611, 0, 0], 6094 "70": [0, 0.68611, 0, 0], 6095 "71": [0, 0.68611, 0, 0], 6096 "72": [0, 0.68611, 0, 0], 6097 "73": [0, 0.68611, 0, 0], 6098 "74": [0, 0.68611, 0, 0], 6099 "75": [0, 0.68611, 0, 0], 6100 "76": [0, 0.68611, 0, 0], 6101 "77": [0, 0.68611, 0, 0], 6102 "78": [0, 0.68611, 0, 0], 6103 "79": [0, 0.68611, 0, 0], 6104 "80": [0, 0.68611, 0, 0], 6105 "81": [0.19444, 0.68611, 0, 0], 6106 "82": [0, 0.68611, 0, 0], 6107 "83": [0, 0.68611, 0, 0], 6108 "84": [0, 0.68611, 0, 0], 6109 "85": [0, 0.68611, 0, 0], 6110 "86": [0, 0.68611, 0.01597, 0], 6111 "87": [0, 0.68611, 0.01597, 0], 6112 "88": [0, 0.68611, 0, 0], 6113 "89": [0, 0.68611, 0.02875, 0], 6114 "90": [0, 0.68611, 0, 0], 6115 "91": [0.25, 0.75, 0, 0], 6116 "92": [0.25, 0.75, 0, 0], 6117 "93": [0.25, 0.75, 0, 0], 6118 "94": [0, 0.69444, 0, 0], 6119 "95": [0.31, 0.13444, 0.03194, 0], 6120 "96": [0, 0.69444, 0, 0], 6121 "97": [0, 0.44444, 0, 0], 6122 "98": [0, 0.69444, 0, 0], 6123 "99": [0, 0.44444, 0, 0], 6124 "100": [0, 0.69444, 0, 0], 6125 "101": [0, 0.44444, 0, 0], 6126 "102": [0, 0.69444, 0.10903, 0], 6127 "103": [0.19444, 0.44444, 0.01597, 0], 6128 "104": [0, 0.69444, 0, 0], 6129 "105": [0, 0.69444, 0, 0], 6130 "106": [0.19444, 0.69444, 0, 0], 6131 "107": [0, 0.69444, 0, 0], 6132 "108": [0, 0.69444, 0, 0], 6133 "109": [0, 0.44444, 0, 0], 6134 "110": [0, 0.44444, 0, 0], 6135 "111": [0, 0.44444, 0, 0], 6136 "112": [0.19444, 0.44444, 0, 0], 6137 "113": [0.19444, 0.44444, 0, 0], 6138 "114": [0, 0.44444, 0, 0], 6139 "115": [0, 0.44444, 0, 0], 6140 "116": [0, 0.63492, 0, 0], 6141 "117": [0, 0.44444, 0, 0], 6142 "118": [0, 0.44444, 0.01597, 0], 6143 "119": [0, 0.44444, 0.01597, 0], 6144 "120": [0, 0.44444, 0, 0], 6145 "121": [0.19444, 0.44444, 0.01597, 0], 6146 "122": [0, 0.44444, 0, 0], 6147 "123": [0.25, 0.75, 0, 0], 6148 "124": [0.25, 0.75, 0, 0], 6149 "125": [0.25, 0.75, 0, 0], 6150 "126": [0.35, 0.34444, 0, 0], 6151 "168": [0, 0.69444, 0, 0], 6152 "172": [0, 0.44444, 0, 0], 6153 "175": [0, 0.59611, 0, 0], 6154 "176": [0, 0.69444, 0, 0], 6155 "177": [0.13333, 0.63333, 0, 0], 6156 "180": [0, 0.69444, 0, 0], 6157 "215": [0.13333, 0.63333, 0, 0], 6158 "247": [0.13333, 0.63333, 0, 0], 6159 "305": [0, 0.44444, 0, 0], 6160 "567": [0.19444, 0.44444, 0, 0], 6161 "710": [0, 0.69444, 0, 0], 6162 "711": [0, 0.63194, 0, 0], 6163 "713": [0, 0.59611, 0, 0], 6164 "714": [0, 0.69444, 0, 0], 6165 "715": [0, 0.69444, 0, 0], 6166 "728": [0, 0.69444, 0, 0], 6167 "729": [0, 0.69444, 0, 0], 6168 "730": [0, 0.69444, 0, 0], 6169 "732": [0, 0.69444, 0, 0], 6170 "768": [0, 0.69444, 0, 0], 6171 "769": [0, 0.69444, 0, 0], 6172 "770": [0, 0.69444, 0, 0], 6173 "771": [0, 0.69444, 0, 0], 6174 "772": [0, 0.59611, 0, 0], 6175 "774": [0, 0.69444, 0, 0], 6176 "775": [0, 0.69444, 0, 0], 6177 "776": [0, 0.69444, 0, 0], 6178 "778": [0, 0.69444, 0, 0], 6179 "779": [0, 0.69444, 0, 0], 6180 "780": [0, 0.63194, 0, 0], 6181 "824": [0.19444, 0.69444, 0, 0], 6182 "915": [0, 0.68611, 0, 0], 6183 "916": [0, 0.68611, 0, 0], 6184 "920": [0, 0.68611, 0, 0], 6185 "923": [0, 0.68611, 0, 0], 6186 "926": [0, 0.68611, 0, 0], 6187 "928": [0, 0.68611, 0, 0], 6188 "931": [0, 0.68611, 0, 0], 6189 "933": [0, 0.68611, 0, 0], 6190 "934": [0, 0.68611, 0, 0], 6191 "936": [0, 0.68611, 0, 0], 6192 "937": [0, 0.68611, 0, 0], 6193 "8211": [0, 0.44444, 0.03194, 0], 6194 "8212": [0, 0.44444, 0.03194, 0], 6195 "8216": [0, 0.69444, 0, 0], 6196 "8217": [0, 0.69444, 0, 0], 6197 "8220": [0, 0.69444, 0, 0], 6198 "8221": [0, 0.69444, 0, 0], 6199 "8224": [0.19444, 0.69444, 0, 0], 6200 "8225": [0.19444, 0.69444, 0, 0], 6201 "8242": [0, 0.55556, 0, 0], 6202 "8407": [0, 0.72444, 0.15486, 0], 6203 "8463": [0, 0.69444, 0, 0], 6204 "8465": [0, 0.69444, 0, 0], 6205 "8467": [0, 0.69444, 0, 0], 6206 "8472": [0.19444, 0.44444, 0, 0], 6207 "8476": [0, 0.69444, 0, 0], 6208 "8501": [0, 0.69444, 0, 0], 6209 "8592": [-0.10889, 0.39111, 0, 0], 6210 "8593": [0.19444, 0.69444, 0, 0], 6211 "8594": [-0.10889, 0.39111, 0, 0], 6212 "8595": [0.19444, 0.69444, 0, 0], 6213 "8596": [-0.10889, 0.39111, 0, 0], 6214 "8597": [0.25, 0.75, 0, 0], 6215 "8598": [0.19444, 0.69444, 0, 0], 6216 "8599": [0.19444, 0.69444, 0, 0], 6217 "8600": [0.19444, 0.69444, 0, 0], 6218 "8601": [0.19444, 0.69444, 0, 0], 6219 "8636": [-0.10889, 0.39111, 0, 0], 6220 "8637": [-0.10889, 0.39111, 0, 0], 6221 "8640": [-0.10889, 0.39111, 0, 0], 6222 "8641": [-0.10889, 0.39111, 0, 0], 6223 "8656": [-0.10889, 0.39111, 0, 0], 6224 "8657": [0.19444, 0.69444, 0, 0], 6225 "8658": [-0.10889, 0.39111, 0, 0], 6226 "8659": [0.19444, 0.69444, 0, 0], 6227 "8660": [-0.10889, 0.39111, 0, 0], 6228 "8661": [0.25, 0.75, 0, 0], 6229 "8704": [0, 0.69444, 0, 0], 6230 "8706": [0, 0.69444, 0.06389, 0], 6231 "8707": [0, 0.69444, 0, 0], 6232 "8709": [0.05556, 0.75, 0, 0], 6233 "8711": [0, 0.68611, 0, 0], 6234 "8712": [0.08556, 0.58556, 0, 0], 6235 "8715": [0.08556, 0.58556, 0, 0], 6236 "8722": [0.13333, 0.63333, 0, 0], 6237 "8723": [0.13333, 0.63333, 0, 0], 6238 "8725": [0.25, 0.75, 0, 0], 6239 "8726": [0.25, 0.75, 0, 0], 6240 "8727": [-0.02778, 0.47222, 0, 0], 6241 "8728": [-0.02639, 0.47361, 0, 0], 6242 "8729": [-0.02639, 0.47361, 0, 0], 6243 "8730": [0.18, 0.82, 0, 0], 6244 "8733": [0, 0.44444, 0, 0], 6245 "8734": [0, 0.44444, 0, 0], 6246 "8736": [0, 0.69224, 0, 0], 6247 "8739": [0.25, 0.75, 0, 0], 6248 "8741": [0.25, 0.75, 0, 0], 6249 "8743": [0, 0.55556, 0, 0], 6250 "8744": [0, 0.55556, 0, 0], 6251 "8745": [0, 0.55556, 0, 0], 6252 "8746": [0, 0.55556, 0, 0], 6253 "8747": [0.19444, 0.69444, 0.12778, 0], 6254 "8764": [-0.10889, 0.39111, 0, 0], 6255 "8768": [0.19444, 0.69444, 0, 0], 6256 "8771": [0.00222, 0.50222, 0, 0], 6257 "8776": [0.02444, 0.52444, 0, 0], 6258 "8781": [0.00222, 0.50222, 0, 0], 6259 "8801": [0.00222, 0.50222, 0, 0], 6260 "8804": [0.19667, 0.69667, 0, 0], 6261 "8805": [0.19667, 0.69667, 0, 0], 6262 "8810": [0.08556, 0.58556, 0, 0], 6263 "8811": [0.08556, 0.58556, 0, 0], 6264 "8826": [0.08556, 0.58556, 0, 0], 6265 "8827": [0.08556, 0.58556, 0, 0], 6266 "8834": [0.08556, 0.58556, 0, 0], 6267 "8835": [0.08556, 0.58556, 0, 0], 6268 "8838": [0.19667, 0.69667, 0, 0], 6269 "8839": [0.19667, 0.69667, 0, 0], 6270 "8846": [0, 0.55556, 0, 0], 6271 "8849": [0.19667, 0.69667, 0, 0], 6272 "8850": [0.19667, 0.69667, 0, 0], 6273 "8851": [0, 0.55556, 0, 0], 6274 "8852": [0, 0.55556, 0, 0], 6275 "8853": [0.13333, 0.63333, 0, 0], 6276 "8854": [0.13333, 0.63333, 0, 0], 6277 "8855": [0.13333, 0.63333, 0, 0], 6278 "8856": [0.13333, 0.63333, 0, 0], 6279 "8857": [0.13333, 0.63333, 0, 0], 6280 "8866": [0, 0.69444, 0, 0], 6281 "8867": [0, 0.69444, 0, 0], 6282 "8868": [0, 0.69444, 0, 0], 6283 "8869": [0, 0.69444, 0, 0], 6284 "8900": [-0.02639, 0.47361, 0, 0], 6285 "8901": [-0.02639, 0.47361, 0, 0], 6286 "8902": [-0.02778, 0.47222, 0, 0], 6287 "8968": [0.25, 0.75, 0, 0], 6288 "8969": [0.25, 0.75, 0, 0], 6289 "8970": [0.25, 0.75, 0, 0], 6290 "8971": [0.25, 0.75, 0, 0], 6291 "8994": [-0.13889, 0.36111, 0, 0], 6292 "8995": [-0.13889, 0.36111, 0, 0], 6293 "9651": [0.19444, 0.69444, 0, 0], 6294 "9657": [-0.02778, 0.47222, 0, 0], 6295 "9661": [0.19444, 0.69444, 0, 0], 6296 "9667": [-0.02778, 0.47222, 0, 0], 6297 "9711": [0.19444, 0.69444, 0, 0], 6298 "9824": [0.12963, 0.69444, 0, 0], 6299 "9825": [0.12963, 0.69444, 0, 0], 6300 "9826": [0.12963, 0.69444, 0, 0], 6301 "9827": [0.12963, 0.69444, 0, 0], 6302 "9837": [0, 0.75, 0, 0], 6303 "9838": [0.19444, 0.69444, 0, 0], 6304 "9839": [0.19444, 0.69444, 0, 0], 6305 "10216": [0.25, 0.75, 0, 0], 6306 "10217": [0.25, 0.75, 0, 0], 6307 "10815": [0, 0.68611, 0, 0], 6308 "10927": [0.19667, 0.69667, 0, 0], 6309 "10928": [0.19667, 0.69667, 0, 0] 6310 }, 6311 "Main-Italic": { 6312 "33": [0, 0.69444, 0.12417, 0], 6313 "34": [0, 0.69444, 0.06961, 0], 6314 "35": [0.19444, 0.69444, 0.06616, 0], 6315 "37": [0.05556, 0.75, 0.13639, 0], 6316 "38": [0, 0.69444, 0.09694, 0], 6317 "39": [0, 0.69444, 0.12417, 0], 6318 "40": [0.25, 0.75, 0.16194, 0], 6319 "41": [0.25, 0.75, 0.03694, 0], 6320 "42": [0, 0.75, 0.14917, 0], 6321 "43": [0.05667, 0.56167, 0.03694, 0], 6322 "44": [0.19444, 0.10556, 0, 0], 6323 "45": [0, 0.43056, 0.02826, 0], 6324 "46": [0, 0.10556, 0, 0], 6325 "47": [0.25, 0.75, 0.16194, 0], 6326 "48": [0, 0.64444, 0.13556, 0], 6327 "49": [0, 0.64444, 0.13556, 0], 6328 "50": [0, 0.64444, 0.13556, 0], 6329 "51": [0, 0.64444, 0.13556, 0], 6330 "52": [0.19444, 0.64444, 0.13556, 0], 6331 "53": [0, 0.64444, 0.13556, 0], 6332 "54": [0, 0.64444, 0.13556, 0], 6333 "55": [0.19444, 0.64444, 0.13556, 0], 6334 "56": [0, 0.64444, 0.13556, 0], 6335 "57": [0, 0.64444, 0.13556, 0], 6336 "58": [0, 0.43056, 0.0582, 0], 6337 "59": [0.19444, 0.43056, 0.0582, 0], 6338 "61": [-0.13313, 0.36687, 0.06616, 0], 6339 "63": [0, 0.69444, 0.1225, 0], 6340 "64": [0, 0.69444, 0.09597, 0], 6341 "65": [0, 0.68333, 0, 0], 6342 "66": [0, 0.68333, 0.10257, 0], 6343 "67": [0, 0.68333, 0.14528, 0], 6344 "68": [0, 0.68333, 0.09403, 0], 6345 "69": [0, 0.68333, 0.12028, 0], 6346 "70": [0, 0.68333, 0.13305, 0], 6347 "71": [0, 0.68333, 0.08722, 0], 6348 "72": [0, 0.68333, 0.16389, 0], 6349 "73": [0, 0.68333, 0.15806, 0], 6350 "74": [0, 0.68333, 0.14028, 0], 6351 "75": [0, 0.68333, 0.14528, 0], 6352 "76": [0, 0.68333, 0, 0], 6353 "77": [0, 0.68333, 0.16389, 0], 6354 "78": [0, 0.68333, 0.16389, 0], 6355 "79": [0, 0.68333, 0.09403, 0], 6356 "80": [0, 0.68333, 0.10257, 0], 6357 "81": [0.19444, 0.68333, 0.09403, 0], 6358 "82": [0, 0.68333, 0.03868, 0], 6359 "83": [0, 0.68333, 0.11972, 0], 6360 "84": [0, 0.68333, 0.13305, 0], 6361 "85": [0, 0.68333, 0.16389, 0], 6362 "86": [0, 0.68333, 0.18361, 0], 6363 "87": [0, 0.68333, 0.18361, 0], 6364 "88": [0, 0.68333, 0.15806, 0], 6365 "89": [0, 0.68333, 0.19383, 0], 6366 "90": [0, 0.68333, 0.14528, 0], 6367 "91": [0.25, 0.75, 0.1875, 0], 6368 "93": [0.25, 0.75, 0.10528, 0], 6369 "94": [0, 0.69444, 0.06646, 0], 6370 "95": [0.31, 0.12056, 0.09208, 0], 6371 "97": [0, 0.43056, 0.07671, 0], 6372 "98": [0, 0.69444, 0.06312, 0], 6373 "99": [0, 0.43056, 0.05653, 0], 6374 "100": [0, 0.69444, 0.10333, 0], 6375 "101": [0, 0.43056, 0.07514, 0], 6376 "102": [0.19444, 0.69444, 0.21194, 0], 6377 "103": [0.19444, 0.43056, 0.08847, 0], 6378 "104": [0, 0.69444, 0.07671, 0], 6379 "105": [0, 0.65536, 0.1019, 0], 6380 "106": [0.19444, 0.65536, 0.14467, 0], 6381 "107": [0, 0.69444, 0.10764, 0], 6382 "108": [0, 0.69444, 0.10333, 0], 6383 "109": [0, 0.43056, 0.07671, 0], 6384 "110": [0, 0.43056, 0.07671, 0], 6385 "111": [0, 0.43056, 0.06312, 0], 6386 "112": [0.19444, 0.43056, 0.06312, 0], 6387 "113": [0.19444, 0.43056, 0.08847, 0], 6388 "114": [0, 0.43056, 0.10764, 0], 6389 "115": [0, 0.43056, 0.08208, 0], 6390 "116": [0, 0.61508, 0.09486, 0], 6391 "117": [0, 0.43056, 0.07671, 0], 6392 "118": [0, 0.43056, 0.10764, 0], 6393 "119": [0, 0.43056, 0.10764, 0], 6394 "120": [0, 0.43056, 0.12042, 0], 6395 "121": [0.19444, 0.43056, 0.08847, 0], 6396 "122": [0, 0.43056, 0.12292, 0], 6397 "126": [0.35, 0.31786, 0.11585, 0], 6398 "163": [0, 0.69444, 0, 0], 6399 "305": [0, 0.43056, 0, 0.02778], 6400 "567": [0.19444, 0.43056, 0, 0.08334], 6401 "768": [0, 0.69444, 0, 0], 6402 "769": [0, 0.69444, 0.09694, 0], 6403 "770": [0, 0.69444, 0.06646, 0], 6404 "771": [0, 0.66786, 0.11585, 0], 6405 "772": [0, 0.56167, 0.10333, 0], 6406 "774": [0, 0.69444, 0.10806, 0], 6407 "775": [0, 0.66786, 0.11752, 0], 6408 "776": [0, 0.66786, 0.10474, 0], 6409 "778": [0, 0.69444, 0, 0], 6410 "779": [0, 0.69444, 0.1225, 0], 6411 "780": [0, 0.62847, 0.08295, 0], 6412 "915": [0, 0.68333, 0.13305, 0], 6413 "916": [0, 0.68333, 0, 0], 6414 "920": [0, 0.68333, 0.09403, 0], 6415 "923": [0, 0.68333, 0, 0], 6416 "926": [0, 0.68333, 0.15294, 0], 6417 "928": [0, 0.68333, 0.16389, 0], 6418 "931": [0, 0.68333, 0.12028, 0], 6419 "933": [0, 0.68333, 0.11111, 0], 6420 "934": [0, 0.68333, 0.05986, 0], 6421 "936": [0, 0.68333, 0.11111, 0], 6422 "937": [0, 0.68333, 0.10257, 0], 6423 "8211": [0, 0.43056, 0.09208, 0], 6424 "8212": [0, 0.43056, 0.09208, 0], 6425 "8216": [0, 0.69444, 0.12417, 0], 6426 "8217": [0, 0.69444, 0.12417, 0], 6427 "8220": [0, 0.69444, 0.1685, 0], 6428 "8221": [0, 0.69444, 0.06961, 0], 6429 "8463": [0, 0.68889, 0, 0] 6430 }, 6431 "Main-Regular": { 6432 "32": [0, 0, 0, 0], 6433 "33": [0, 0.69444, 0, 0], 6434 "34": [0, 0.69444, 0, 0], 6435 "35": [0.19444, 0.69444, 0, 0], 6436 "36": [0.05556, 0.75, 0, 0], 6437 "37": [0.05556, 0.75, 0, 0], 6438 "38": [0, 0.69444, 0, 0], 6439 "39": [0, 0.69444, 0, 0], 6440 "40": [0.25, 0.75, 0, 0], 6441 "41": [0.25, 0.75, 0, 0], 6442 "42": [0, 0.75, 0, 0], 6443 "43": [0.08333, 0.58333, 0, 0], 6444 "44": [0.19444, 0.10556, 0, 0], 6445 "45": [0, 0.43056, 0, 0], 6446 "46": [0, 0.10556, 0, 0], 6447 "47": [0.25, 0.75, 0, 0], 6448 "48": [0, 0.64444, 0, 0], 6449 "49": [0, 0.64444, 0, 0], 6450 "50": [0, 0.64444, 0, 0], 6451 "51": [0, 0.64444, 0, 0], 6452 "52": [0, 0.64444, 0, 0], 6453 "53": [0, 0.64444, 0, 0], 6454 "54": [0, 0.64444, 0, 0], 6455 "55": [0, 0.64444, 0, 0], 6456 "56": [0, 0.64444, 0, 0], 6457 "57": [0, 0.64444, 0, 0], 6458 "58": [0, 0.43056, 0, 0], 6459 "59": [0.19444, 0.43056, 0, 0], 6460 "60": [0.0391, 0.5391, 0, 0], 6461 "61": [-0.13313, 0.36687, 0, 0], 6462 "62": [0.0391, 0.5391, 0, 0], 6463 "63": [0, 0.69444, 0, 0], 6464 "64": [0, 0.69444, 0, 0], 6465 "65": [0, 0.68333, 0, 0], 6466 "66": [0, 0.68333, 0, 0], 6467 "67": [0, 0.68333, 0, 0], 6468 "68": [0, 0.68333, 0, 0], 6469 "69": [0, 0.68333, 0, 0], 6470 "70": [0, 0.68333, 0, 0], 6471 "71": [0, 0.68333, 0, 0], 6472 "72": [0, 0.68333, 0, 0], 6473 "73": [0, 0.68333, 0, 0], 6474 "74": [0, 0.68333, 0, 0], 6475 "75": [0, 0.68333, 0, 0], 6476 "76": [0, 0.68333, 0, 0], 6477 "77": [0, 0.68333, 0, 0], 6478 "78": [0, 0.68333, 0, 0], 6479 "79": [0, 0.68333, 0, 0], 6480 "80": [0, 0.68333, 0, 0], 6481 "81": [0.19444, 0.68333, 0, 0], 6482 "82": [0, 0.68333, 0, 0], 6483 "83": [0, 0.68333, 0, 0], 6484 "84": [0, 0.68333, 0, 0], 6485 "85": [0, 0.68333, 0, 0], 6486 "86": [0, 0.68333, 0.01389, 0], 6487 "87": [0, 0.68333, 0.01389, 0], 6488 "88": [0, 0.68333, 0, 0], 6489 "89": [0, 0.68333, 0.025, 0], 6490 "90": [0, 0.68333, 0, 0], 6491 "91": [0.25, 0.75, 0, 0], 6492 "92": [0.25, 0.75, 0, 0], 6493 "93": [0.25, 0.75, 0, 0], 6494 "94": [0, 0.69444, 0, 0], 6495 "95": [0.31, 0.12056, 0.02778, 0], 6496 "96": [0, 0.69444, 0, 0], 6497 "97": [0, 0.43056, 0, 0], 6498 "98": [0, 0.69444, 0, 0], 6499 "99": [0, 0.43056, 0, 0], 6500 "100": [0, 0.69444, 0, 0], 6501 "101": [0, 0.43056, 0, 0], 6502 "102": [0, 0.69444, 0.07778, 0], 6503 "103": [0.19444, 0.43056, 0.01389, 0], 6504 "104": [0, 0.69444, 0, 0], 6505 "105": [0, 0.66786, 0, 0], 6506 "106": [0.19444, 0.66786, 0, 0], 6507 "107": [0, 0.69444, 0, 0], 6508 "108": [0, 0.69444, 0, 0], 6509 "109": [0, 0.43056, 0, 0], 6510 "110": [0, 0.43056, 0, 0], 6511 "111": [0, 0.43056, 0, 0], 6512 "112": [0.19444, 0.43056, 0, 0], 6513 "113": [0.19444, 0.43056, 0, 0], 6514 "114": [0, 0.43056, 0, 0], 6515 "115": [0, 0.43056, 0, 0], 6516 "116": [0, 0.61508, 0, 0], 6517 "117": [0, 0.43056, 0, 0], 6518 "118": [0, 0.43056, 0.01389, 0], 6519 "119": [0, 0.43056, 0.01389, 0], 6520 "120": [0, 0.43056, 0, 0], 6521 "121": [0.19444, 0.43056, 0.01389, 0], 6522 "122": [0, 0.43056, 0, 0], 6523 "123": [0.25, 0.75, 0, 0], 6524 "124": [0.25, 0.75, 0, 0], 6525 "125": [0.25, 0.75, 0, 0], 6526 "126": [0.35, 0.31786, 0, 0], 6527 "160": [0, 0, 0, 0], 6528 "168": [0, 0.66786, 0, 0], 6529 "172": [0, 0.43056, 0, 0], 6530 "175": [0, 0.56778, 0, 0], 6531 "176": [0, 0.69444, 0, 0], 6532 "177": [0.08333, 0.58333, 0, 0], 6533 "180": [0, 0.69444, 0, 0], 6534 "215": [0.08333, 0.58333, 0, 0], 6535 "247": [0.08333, 0.58333, 0, 0], 6536 "305": [0, 0.43056, 0, 0], 6537 "567": [0.19444, 0.43056, 0, 0], 6538 "710": [0, 0.69444, 0, 0], 6539 "711": [0, 0.62847, 0, 0], 6540 "713": [0, 0.56778, 0, 0], 6541 "714": [0, 0.69444, 0, 0], 6542 "715": [0, 0.69444, 0, 0], 6543 "728": [0, 0.69444, 0, 0], 6544 "729": [0, 0.66786, 0, 0], 6545 "730": [0, 0.69444, 0, 0], 6546 "732": [0, 0.66786, 0, 0], 6547 "768": [0, 0.69444, 0, 0], 6548 "769": [0, 0.69444, 0, 0], 6549 "770": [0, 0.69444, 0, 0], 6550 "771": [0, 0.66786, 0, 0], 6551 "772": [0, 0.56778, 0, 0], 6552 "774": [0, 0.69444, 0, 0], 6553 "775": [0, 0.66786, 0, 0], 6554 "776": [0, 0.66786, 0, 0], 6555 "778": [0, 0.69444, 0, 0], 6556 "779": [0, 0.69444, 0, 0], 6557 "780": [0, 0.62847, 0, 0], 6558 "824": [0.19444, 0.69444, 0, 0], 6559 "915": [0, 0.68333, 0, 0], 6560 "916": [0, 0.68333, 0, 0], 6561 "920": [0, 0.68333, 0, 0], 6562 "923": [0, 0.68333, 0, 0], 6563 "926": [0, 0.68333, 0, 0], 6564 "928": [0, 0.68333, 0, 0], 6565 "931": [0, 0.68333, 0, 0], 6566 "933": [0, 0.68333, 0, 0], 6567 "934": [0, 0.68333, 0, 0], 6568 "936": [0, 0.68333, 0, 0], 6569 "937": [0, 0.68333, 0, 0], 6570 "8211": [0, 0.43056, 0.02778, 0], 6571 "8212": [0, 0.43056, 0.02778, 0], 6572 "8216": [0, 0.69444, 0, 0], 6573 "8217": [0, 0.69444, 0, 0], 6574 "8220": [0, 0.69444, 0, 0], 6575 "8221": [0, 0.69444, 0, 0], 6576 "8224": [0.19444, 0.69444, 0, 0], 6577 "8225": [0.19444, 0.69444, 0, 0], 6578 "8230": [0, 0.12, 0, 0], 6579 "8242": [0, 0.55556, 0, 0], 6580 "8407": [0, 0.71444, 0.15382, 0], 6581 "8463": [0, 0.68889, 0, 0], 6582 "8465": [0, 0.69444, 0, 0], 6583 "8467": [0, 0.69444, 0, 0.11111], 6584 "8472": [0.19444, 0.43056, 0, 0.11111], 6585 "8476": [0, 0.69444, 0, 0], 6586 "8501": [0, 0.69444, 0, 0], 6587 "8592": [-0.13313, 0.36687, 0, 0], 6588 "8593": [0.19444, 0.69444, 0, 0], 6589 "8594": [-0.13313, 0.36687, 0, 0], 6590 "8595": [0.19444, 0.69444, 0, 0], 6591 "8596": [-0.13313, 0.36687, 0, 0], 6592 "8597": [0.25, 0.75, 0, 0], 6593 "8598": [0.19444, 0.69444, 0, 0], 6594 "8599": [0.19444, 0.69444, 0, 0], 6595 "8600": [0.19444, 0.69444, 0, 0], 6596 "8601": [0.19444, 0.69444, 0, 0], 6597 "8614": [0.011, 0.511, 0, 0], 6598 "8617": [0.011, 0.511, 0, 0], 6599 "8618": [0.011, 0.511, 0, 0], 6600 "8636": [-0.13313, 0.36687, 0, 0], 6601 "8637": [-0.13313, 0.36687, 0, 0], 6602 "8640": [-0.13313, 0.36687, 0, 0], 6603 "8641": [-0.13313, 0.36687, 0, 0], 6604 "8652": [0.011, 0.671, 0, 0], 6605 "8656": [-0.13313, 0.36687, 0, 0], 6606 "8657": [0.19444, 0.69444, 0, 0], 6607 "8658": [-0.13313, 0.36687, 0, 0], 6608 "8659": [0.19444, 0.69444, 0, 0], 6609 "8660": [-0.13313, 0.36687, 0, 0], 6610 "8661": [0.25, 0.75, 0, 0], 6611 "8704": [0, 0.69444, 0, 0], 6612 "8706": [0, 0.69444, 0.05556, 0.08334], 6613 "8707": [0, 0.69444, 0, 0], 6614 "8709": [0.05556, 0.75, 0, 0], 6615 "8711": [0, 0.68333, 0, 0], 6616 "8712": [0.0391, 0.5391, 0, 0], 6617 "8715": [0.0391, 0.5391, 0, 0], 6618 "8722": [0.08333, 0.58333, 0, 0], 6619 "8723": [0.08333, 0.58333, 0, 0], 6620 "8725": [0.25, 0.75, 0, 0], 6621 "8726": [0.25, 0.75, 0, 0], 6622 "8727": [-0.03472, 0.46528, 0, 0], 6623 "8728": [-0.05555, 0.44445, 0, 0], 6624 "8729": [-0.05555, 0.44445, 0, 0], 6625 "8730": [0.2, 0.8, 0, 0], 6626 "8733": [0, 0.43056, 0, 0], 6627 "8734": [0, 0.43056, 0, 0], 6628 "8736": [0, 0.69224, 0, 0], 6629 "8739": [0.25, 0.75, 0, 0], 6630 "8741": [0.25, 0.75, 0, 0], 6631 "8743": [0, 0.55556, 0, 0], 6632 "8744": [0, 0.55556, 0, 0], 6633 "8745": [0, 0.55556, 0, 0], 6634 "8746": [0, 0.55556, 0, 0], 6635 "8747": [0.19444, 0.69444, 0.11111, 0], 6636 "8764": [-0.13313, 0.36687, 0, 0], 6637 "8768": [0.19444, 0.69444, 0, 0], 6638 "8771": [-0.03625, 0.46375, 0, 0], 6639 "8773": [-0.022, 0.589, 0, 0], 6640 "8776": [-0.01688, 0.48312, 0, 0], 6641 "8781": [-0.03625, 0.46375, 0, 0], 6642 "8784": [-0.133, 0.67, 0, 0], 6643 "8800": [0.215, 0.716, 0, 0], 6644 "8801": [-0.03625, 0.46375, 0, 0], 6645 "8804": [0.13597, 0.63597, 0, 0], 6646 "8805": [0.13597, 0.63597, 0, 0], 6647 "8810": [0.0391, 0.5391, 0, 0], 6648 "8811": [0.0391, 0.5391, 0, 0], 6649 "8826": [0.0391, 0.5391, 0, 0], 6650 "8827": [0.0391, 0.5391, 0, 0], 6651 "8834": [0.0391, 0.5391, 0, 0], 6652 "8835": [0.0391, 0.5391, 0, 0], 6653 "8838": [0.13597, 0.63597, 0, 0], 6654 "8839": [0.13597, 0.63597, 0, 0], 6655 "8846": [0, 0.55556, 0, 0], 6656 "8849": [0.13597, 0.63597, 0, 0], 6657 "8850": [0.13597, 0.63597, 0, 0], 6658 "8851": [0, 0.55556, 0, 0], 6659 "8852": [0, 0.55556, 0, 0], 6660 "8853": [0.08333, 0.58333, 0, 0], 6661 "8854": [0.08333, 0.58333, 0, 0], 6662 "8855": [0.08333, 0.58333, 0, 0], 6663 "8856": [0.08333, 0.58333, 0, 0], 6664 "8857": [0.08333, 0.58333, 0, 0], 6665 "8866": [0, 0.69444, 0, 0], 6666 "8867": [0, 0.69444, 0, 0], 6667 "8868": [0, 0.69444, 0, 0], 6668 "8869": [0, 0.69444, 0, 0], 6669 "8872": [0.249, 0.75, 0, 0], 6670 "8900": [-0.05555, 0.44445, 0, 0], 6671 "8901": [-0.05555, 0.44445, 0, 0], 6672 "8902": [-0.03472, 0.46528, 0, 0], 6673 "8904": [0.005, 0.505, 0, 0], 6674 "8942": [0.03, 0.9, 0, 0], 6675 "8943": [-0.19, 0.31, 0, 0], 6676 "8945": [-0.1, 0.82, 0, 0], 6677 "8968": [0.25, 0.75, 0, 0], 6678 "8969": [0.25, 0.75, 0, 0], 6679 "8970": [0.25, 0.75, 0, 0], 6680 "8971": [0.25, 0.75, 0, 0], 6681 "8994": [-0.14236, 0.35764, 0, 0], 6682 "8995": [-0.14236, 0.35764, 0, 0], 6683 "9136": [0.244, 0.744, 0, 0], 6684 "9137": [0.244, 0.744, 0, 0], 6685 "9651": [0.19444, 0.69444, 0, 0], 6686 "9657": [-0.03472, 0.46528, 0, 0], 6687 "9661": [0.19444, 0.69444, 0, 0], 6688 "9667": [-0.03472, 0.46528, 0, 0], 6689 "9711": [0.19444, 0.69444, 0, 0], 6690 "9824": [0.12963, 0.69444, 0, 0], 6691 "9825": [0.12963, 0.69444, 0, 0], 6692 "9826": [0.12963, 0.69444, 0, 0], 6693 "9827": [0.12963, 0.69444, 0, 0], 6694 "9837": [0, 0.75, 0, 0], 6695 "9838": [0.19444, 0.69444, 0, 0], 6696 "9839": [0.19444, 0.69444, 0, 0], 6697 "10216": [0.25, 0.75, 0, 0], 6698 "10217": [0.25, 0.75, 0, 0], 6699 "10222": [0.244, 0.744, 0, 0], 6700 "10223": [0.244, 0.744, 0, 0], 6701 "10229": [0.011, 0.511, 0, 0], 6702 "10230": [0.011, 0.511, 0, 0], 6703 "10231": [0.011, 0.511, 0, 0], 6704 "10232": [0.024, 0.525, 0, 0], 6705 "10233": [0.024, 0.525, 0, 0], 6706 "10234": [0.024, 0.525, 0, 0], 6707 "10236": [0.011, 0.511, 0, 0], 6708 "10815": [0, 0.68333, 0, 0], 6709 "10927": [0.13597, 0.63597, 0, 0], 6710 "10928": [0.13597, 0.63597, 0, 0] 6711 }, 6712 "Math-BoldItalic": { 6713 "47": [0.19444, 0.69444, 0, 0], 6714 "65": [0, 0.68611, 0, 0], 6715 "66": [0, 0.68611, 0.04835, 0], 6716 "67": [0, 0.68611, 0.06979, 0], 6717 "68": [0, 0.68611, 0.03194, 0], 6718 "69": [0, 0.68611, 0.05451, 0], 6719 "70": [0, 0.68611, 0.15972, 0], 6720 "71": [0, 0.68611, 0, 0], 6721 "72": [0, 0.68611, 0.08229, 0], 6722 "73": [0, 0.68611, 0.07778, 0], 6723 "74": [0, 0.68611, 0.10069, 0], 6724 "75": [0, 0.68611, 0.06979, 0], 6725 "76": [0, 0.68611, 0, 0], 6726 "77": [0, 0.68611, 0.11424, 0], 6727 "78": [0, 0.68611, 0.11424, 0], 6728 "79": [0, 0.68611, 0.03194, 0], 6729 "80": [0, 0.68611, 0.15972, 0], 6730 "81": [0.19444, 0.68611, 0, 0], 6731 "82": [0, 0.68611, 0.00421, 0], 6732 "83": [0, 0.68611, 0.05382, 0], 6733 "84": [0, 0.68611, 0.15972, 0], 6734 "85": [0, 0.68611, 0.11424, 0], 6735 "86": [0, 0.68611, 0.25555, 0], 6736 "87": [0, 0.68611, 0.15972, 0], 6737 "88": [0, 0.68611, 0.07778, 0], 6738 "89": [0, 0.68611, 0.25555, 0], 6739 "90": [0, 0.68611, 0.06979, 0], 6740 "97": [0, 0.44444, 0, 0], 6741 "98": [0, 0.69444, 0, 0], 6742 "99": [0, 0.44444, 0, 0], 6743 "100": [0, 0.69444, 0, 0], 6744 "101": [0, 0.44444, 0, 0], 6745 "102": [0.19444, 0.69444, 0.11042, 0], 6746 "103": [0.19444, 0.44444, 0.03704, 0], 6747 "104": [0, 0.69444, 0, 0], 6748 "105": [0, 0.69326, 0, 0], 6749 "106": [0.19444, 0.69326, 0.0622, 0], 6750 "107": [0, 0.69444, 0.01852, 0], 6751 "108": [0, 0.69444, 0.0088, 0], 6752 "109": [0, 0.44444, 0, 0], 6753 "110": [0, 0.44444, 0, 0], 6754 "111": [0, 0.44444, 0, 0], 6755 "112": [0.19444, 0.44444, 0, 0], 6756 "113": [0.19444, 0.44444, 0.03704, 0], 6757 "114": [0, 0.44444, 0.03194, 0], 6758 "115": [0, 0.44444, 0, 0], 6759 "116": [0, 0.63492, 0, 0], 6760 "117": [0, 0.44444, 0, 0], 6761 "118": [0, 0.44444, 0.03704, 0], 6762 "119": [0, 0.44444, 0.02778, 0], 6763 "120": [0, 0.44444, 0, 0], 6764 "121": [0.19444, 0.44444, 0.03704, 0], 6765 "122": [0, 0.44444, 0.04213, 0], 6766 "915": [0, 0.68611, 0.15972, 0], 6767 "916": [0, 0.68611, 0, 0], 6768 "920": [0, 0.68611, 0.03194, 0], 6769 "923": [0, 0.68611, 0, 0], 6770 "926": [0, 0.68611, 0.07458, 0], 6771 "928": [0, 0.68611, 0.08229, 0], 6772 "931": [0, 0.68611, 0.05451, 0], 6773 "933": [0, 0.68611, 0.15972, 0], 6774 "934": [0, 0.68611, 0, 0], 6775 "936": [0, 0.68611, 0.11653, 0], 6776 "937": [0, 0.68611, 0.04835, 0], 6777 "945": [0, 0.44444, 0, 0], 6778 "946": [0.19444, 0.69444, 0.03403, 0], 6779 "947": [0.19444, 0.44444, 0.06389, 0], 6780 "948": [0, 0.69444, 0.03819, 0], 6781 "949": [0, 0.44444, 0, 0], 6782 "950": [0.19444, 0.69444, 0.06215, 0], 6783 "951": [0.19444, 0.44444, 0.03704, 0], 6784 "952": [0, 0.69444, 0.03194, 0], 6785 "953": [0, 0.44444, 0, 0], 6786 "954": [0, 0.44444, 0, 0], 6787 "955": [0, 0.69444, 0, 0], 6788 "956": [0.19444, 0.44444, 0, 0], 6789 "957": [0, 0.44444, 0.06898, 0], 6790 "958": [0.19444, 0.69444, 0.03021, 0], 6791 "959": [0, 0.44444, 0, 0], 6792 "960": [0, 0.44444, 0.03704, 0], 6793 "961": [0.19444, 0.44444, 0, 0], 6794 "962": [0.09722, 0.44444, 0.07917, 0], 6795 "963": [0, 0.44444, 0.03704, 0], 6796 "964": [0, 0.44444, 0.13472, 0], 6797 "965": [0, 0.44444, 0.03704, 0], 6798 "966": [0.19444, 0.44444, 0, 0], 6799 "967": [0.19444, 0.44444, 0, 0], 6800 "968": [0.19444, 0.69444, 0.03704, 0], 6801 "969": [0, 0.44444, 0.03704, 0], 6802 "977": [0, 0.69444, 0, 0], 6803 "981": [0.19444, 0.69444, 0, 0], 6804 "982": [0, 0.44444, 0.03194, 0], 6805 "1009": [0.19444, 0.44444, 0, 0], 6806 "1013": [0, 0.44444, 0, 0] 6807 }, 6808 "Math-Italic": { 6809 "47": [0.19444, 0.69444, 0, 0], 6810 "65": [0, 0.68333, 0, 0.13889], 6811 "66": [0, 0.68333, 0.05017, 0.08334], 6812 "67": [0, 0.68333, 0.07153, 0.08334], 6813 "68": [0, 0.68333, 0.02778, 0.05556], 6814 "69": [0, 0.68333, 0.05764, 0.08334], 6815 "70": [0, 0.68333, 0.13889, 0.08334], 6816 "71": [0, 0.68333, 0, 0.08334], 6817 "72": [0, 0.68333, 0.08125, 0.05556], 6818 "73": [0, 0.68333, 0.07847, 0.11111], 6819 "74": [0, 0.68333, 0.09618, 0.16667], 6820 "75": [0, 0.68333, 0.07153, 0.05556], 6821 "76": [0, 0.68333, 0, 0.02778], 6822 "77": [0, 0.68333, 0.10903, 0.08334], 6823 "78": [0, 0.68333, 0.10903, 0.08334], 6824 "79": [0, 0.68333, 0.02778, 0.08334], 6825 "80": [0, 0.68333, 0.13889, 0.08334], 6826 "81": [0.19444, 0.68333, 0, 0.08334], 6827 "82": [0, 0.68333, 0.00773, 0.08334], 6828 "83": [0, 0.68333, 0.05764, 0.08334], 6829 "84": [0, 0.68333, 0.13889, 0.08334], 6830 "85": [0, 0.68333, 0.10903, 0.02778], 6831 "86": [0, 0.68333, 0.22222, 0], 6832 "87": [0, 0.68333, 0.13889, 0], 6833 "88": [0, 0.68333, 0.07847, 0.08334], 6834 "89": [0, 0.68333, 0.22222, 0], 6835 "90": [0, 0.68333, 0.07153, 0.08334], 6836 "97": [0, 0.43056, 0, 0], 6837 "98": [0, 0.69444, 0, 0], 6838 "99": [0, 0.43056, 0, 0.05556], 6839 "100": [0, 0.69444, 0, 0.16667], 6840 "101": [0, 0.43056, 0, 0.05556], 6841 "102": [0.19444, 0.69444, 0.10764, 0.16667], 6842 "103": [0.19444, 0.43056, 0.03588, 0.02778], 6843 "104": [0, 0.69444, 0, 0], 6844 "105": [0, 0.65952, 0, 0], 6845 "106": [0.19444, 0.65952, 0.05724, 0], 6846 "107": [0, 0.69444, 0.03148, 0], 6847 "108": [0, 0.69444, 0.01968, 0.08334], 6848 "109": [0, 0.43056, 0, 0], 6849 "110": [0, 0.43056, 0, 0], 6850 "111": [0, 0.43056, 0, 0.05556], 6851 "112": [0.19444, 0.43056, 0, 0.08334], 6852 "113": [0.19444, 0.43056, 0.03588, 0.08334], 6853 "114": [0, 0.43056, 0.02778, 0.05556], 6854 "115": [0, 0.43056, 0, 0.05556], 6855 "116": [0, 0.61508, 0, 0.08334], 6856 "117": [0, 0.43056, 0, 0.02778], 6857 "118": [0, 0.43056, 0.03588, 0.02778], 6858 "119": [0, 0.43056, 0.02691, 0.08334], 6859 "120": [0, 0.43056, 0, 0.02778], 6860 "121": [0.19444, 0.43056, 0.03588, 0.05556], 6861 "122": [0, 0.43056, 0.04398, 0.05556], 6862 "915": [0, 0.68333, 0.13889, 0.08334], 6863 "916": [0, 0.68333, 0, 0.16667], 6864 "920": [0, 0.68333, 0.02778, 0.08334], 6865 "923": [0, 0.68333, 0, 0.16667], 6866 "926": [0, 0.68333, 0.07569, 0.08334], 6867 "928": [0, 0.68333, 0.08125, 0.05556], 6868 "931": [0, 0.68333, 0.05764, 0.08334], 6869 "933": [0, 0.68333, 0.13889, 0.05556], 6870 "934": [0, 0.68333, 0, 0.08334], 6871 "936": [0, 0.68333, 0.11, 0.05556], 6872 "937": [0, 0.68333, 0.05017, 0.08334], 6873 "945": [0, 0.43056, 0.0037, 0.02778], 6874 "946": [0.19444, 0.69444, 0.05278, 0.08334], 6875 "947": [0.19444, 0.43056, 0.05556, 0], 6876 "948": [0, 0.69444, 0.03785, 0.05556], 6877 "949": [0, 0.43056, 0, 0.08334], 6878 "950": [0.19444, 0.69444, 0.07378, 0.08334], 6879 "951": [0.19444, 0.43056, 0.03588, 0.05556], 6880 "952": [0, 0.69444, 0.02778, 0.08334], 6881 "953": [0, 0.43056, 0, 0.05556], 6882 "954": [0, 0.43056, 0, 0], 6883 "955": [0, 0.69444, 0, 0], 6884 "956": [0.19444, 0.43056, 0, 0.02778], 6885 "957": [0, 0.43056, 0.06366, 0.02778], 6886 "958": [0.19444, 0.69444, 0.04601, 0.11111], 6887 "959": [0, 0.43056, 0, 0.05556], 6888 "960": [0, 0.43056, 0.03588, 0], 6889 "961": [0.19444, 0.43056, 0, 0.08334], 6890 "962": [0.09722, 0.43056, 0.07986, 0.08334], 6891 "963": [0, 0.43056, 0.03588, 0], 6892 "964": [0, 0.43056, 0.1132, 0.02778], 6893 "965": [0, 0.43056, 0.03588, 0.02778], 6894 "966": [0.19444, 0.43056, 0, 0.08334], 6895 "967": [0.19444, 0.43056, 0, 0.05556], 6896 "968": [0.19444, 0.69444, 0.03588, 0.11111], 6897 "969": [0, 0.43056, 0.03588, 0], 6898 "977": [0, 0.69444, 0, 0.08334], 6899 "981": [0.19444, 0.69444, 0, 0.08334], 6900 "982": [0, 0.43056, 0.02778, 0], 6901 "1009": [0.19444, 0.43056, 0, 0.08334], 6902 "1013": [0, 0.43056, 0, 0.05556] 6903 }, 6904 "Math-Regular": { 6905 "65": [0, 0.68333, 0, 0.13889], 6906 "66": [0, 0.68333, 0.05017, 0.08334], 6907 "67": [0, 0.68333, 0.07153, 0.08334], 6908 "68": [0, 0.68333, 0.02778, 0.05556], 6909 "69": [0, 0.68333, 0.05764, 0.08334], 6910 "70": [0, 0.68333, 0.13889, 0.08334], 6911 "71": [0, 0.68333, 0, 0.08334], 6912 "72": [0, 0.68333, 0.08125, 0.05556], 6913 "73": [0, 0.68333, 0.07847, 0.11111], 6914 "74": [0, 0.68333, 0.09618, 0.16667], 6915 "75": [0, 0.68333, 0.07153, 0.05556], 6916 "76": [0, 0.68333, 0, 0.02778], 6917 "77": [0, 0.68333, 0.10903, 0.08334], 6918 "78": [0, 0.68333, 0.10903, 0.08334], 6919 "79": [0, 0.68333, 0.02778, 0.08334], 6920 "80": [0, 0.68333, 0.13889, 0.08334], 6921 "81": [0.19444, 0.68333, 0, 0.08334], 6922 "82": [0, 0.68333, 0.00773, 0.08334], 6923 "83": [0, 0.68333, 0.05764, 0.08334], 6924 "84": [0, 0.68333, 0.13889, 0.08334], 6925 "85": [0, 0.68333, 0.10903, 0.02778], 6926 "86": [0, 0.68333, 0.22222, 0], 6927 "87": [0, 0.68333, 0.13889, 0], 6928 "88": [0, 0.68333, 0.07847, 0.08334], 6929 "89": [0, 0.68333, 0.22222, 0], 6930 "90": [0, 0.68333, 0.07153, 0.08334], 6931 "97": [0, 0.43056, 0, 0], 6932 "98": [0, 0.69444, 0, 0], 6933 "99": [0, 0.43056, 0, 0.05556], 6934 "100": [0, 0.69444, 0, 0.16667], 6935 "101": [0, 0.43056, 0, 0.05556], 6936 "102": [0.19444, 0.69444, 0.10764, 0.16667], 6937 "103": [0.19444, 0.43056, 0.03588, 0.02778], 6938 "104": [0, 0.69444, 0, 0], 6939 "105": [0, 0.65952, 0, 0], 6940 "106": [0.19444, 0.65952, 0.05724, 0], 6941 "107": [0, 0.69444, 0.03148, 0], 6942 "108": [0, 0.69444, 0.01968, 0.08334], 6943 "109": [0, 0.43056, 0, 0], 6944 "110": [0, 0.43056, 0, 0], 6945 "111": [0, 0.43056, 0, 0.05556], 6946 "112": [0.19444, 0.43056, 0, 0.08334], 6947 "113": [0.19444, 0.43056, 0.03588, 0.08334], 6948 "114": [0, 0.43056, 0.02778, 0.05556], 6949 "115": [0, 0.43056, 0, 0.05556], 6950 "116": [0, 0.61508, 0, 0.08334], 6951 "117": [0, 0.43056, 0, 0.02778], 6952 "118": [0, 0.43056, 0.03588, 0.02778], 6953 "119": [0, 0.43056, 0.02691, 0.08334], 6954 "120": [0, 0.43056, 0, 0.02778], 6955 "121": [0.19444, 0.43056, 0.03588, 0.05556], 6956 "122": [0, 0.43056, 0.04398, 0.05556], 6957 "915": [0, 0.68333, 0.13889, 0.08334], 6958 "916": [0, 0.68333, 0, 0.16667], 6959 "920": [0, 0.68333, 0.02778, 0.08334], 6960 "923": [0, 0.68333, 0, 0.16667], 6961 "926": [0, 0.68333, 0.07569, 0.08334], 6962 "928": [0, 0.68333, 0.08125, 0.05556], 6963 "931": [0, 0.68333, 0.05764, 0.08334], 6964 "933": [0, 0.68333, 0.13889, 0.05556], 6965 "934": [0, 0.68333, 0, 0.08334], 6966 "936": [0, 0.68333, 0.11, 0.05556], 6967 "937": [0, 0.68333, 0.05017, 0.08334], 6968 "945": [0, 0.43056, 0.0037, 0.02778], 6969 "946": [0.19444, 0.69444, 0.05278, 0.08334], 6970 "947": [0.19444, 0.43056, 0.05556, 0], 6971 "948": [0, 0.69444, 0.03785, 0.05556], 6972 "949": [0, 0.43056, 0, 0.08334], 6973 "950": [0.19444, 0.69444, 0.07378, 0.08334], 6974 "951": [0.19444, 0.43056, 0.03588, 0.05556], 6975 "952": [0, 0.69444, 0.02778, 0.08334], 6976 "953": [0, 0.43056, 0, 0.05556], 6977 "954": [0, 0.43056, 0, 0], 6978 "955": [0, 0.69444, 0, 0], 6979 "956": [0.19444, 0.43056, 0, 0.02778], 6980 "957": [0, 0.43056, 0.06366, 0.02778], 6981 "958": [0.19444, 0.69444, 0.04601, 0.11111], 6982 "959": [0, 0.43056, 0, 0.05556], 6983 "960": [0, 0.43056, 0.03588, 0], 6984 "961": [0.19444, 0.43056, 0, 0.08334], 6985 "962": [0.09722, 0.43056, 0.07986, 0.08334], 6986 "963": [0, 0.43056, 0.03588, 0], 6987 "964": [0, 0.43056, 0.1132, 0.02778], 6988 "965": [0, 0.43056, 0.03588, 0.02778], 6989 "966": [0.19444, 0.43056, 0, 0.08334], 6990 "967": [0.19444, 0.43056, 0, 0.05556], 6991 "968": [0.19444, 0.69444, 0.03588, 0.11111], 6992 "969": [0, 0.43056, 0.03588, 0], 6993 "977": [0, 0.69444, 0, 0.08334], 6994 "981": [0.19444, 0.69444, 0, 0.08334], 6995 "982": [0, 0.43056, 0.02778, 0], 6996 "1009": [0.19444, 0.43056, 0, 0.08334], 6997 "1013": [0, 0.43056, 0, 0.05556] 6998 }, 6999 "SansSerif-Regular": { 7000 "33": [0, 0.69444, 0, 0], 7001 "34": [0, 0.69444, 0, 0], 7002 "35": [0.19444, 0.69444, 0, 0], 7003 "36": [0.05556, 0.75, 0, 0], 7004 "37": [0.05556, 0.75, 0, 0], 7005 "38": [0, 0.69444, 0, 0], 7006 "39": [0, 0.69444, 0, 0], 7007 "40": [0.25, 0.75, 0, 0], 7008 "41": [0.25, 0.75, 0, 0], 7009 "42": [0, 0.75, 0, 0], 7010 "43": [0.08333, 0.58333, 0, 0], 7011 "44": [0.125, 0.08333, 0, 0], 7012 "45": [0, 0.44444, 0, 0], 7013 "46": [0, 0.08333, 0, 0], 7014 "47": [0.25, 0.75, 0, 0], 7015 "48": [0, 0.65556, 0, 0], 7016 "49": [0, 0.65556, 0, 0], 7017 "50": [0, 0.65556, 0, 0], 7018 "51": [0, 0.65556, 0, 0], 7019 "52": [0, 0.65556, 0, 0], 7020 "53": [0, 0.65556, 0, 0], 7021 "54": [0, 0.65556, 0, 0], 7022 "55": [0, 0.65556, 0, 0], 7023 "56": [0, 0.65556, 0, 0], 7024 "57": [0, 0.65556, 0, 0], 7025 "58": [0, 0.44444, 0, 0], 7026 "59": [0.125, 0.44444, 0, 0], 7027 "61": [-0.13, 0.37, 0, 0], 7028 "63": [0, 0.69444, 0, 0], 7029 "64": [0, 0.69444, 0, 0], 7030 "65": [0, 0.69444, 0, 0], 7031 "66": [0, 0.69444, 0, 0], 7032 "67": [0, 0.69444, 0, 0], 7033 "68": [0, 0.69444, 0, 0], 7034 "69": [0, 0.69444, 0, 0], 7035 "70": [0, 0.69444, 0, 0], 7036 "71": [0, 0.69444, 0, 0], 7037 "72": [0, 0.69444, 0, 0], 7038 "73": [0, 0.69444, 0, 0], 7039 "74": [0, 0.69444, 0, 0], 7040 "75": [0, 0.69444, 0, 0], 7041 "76": [0, 0.69444, 0, 0], 7042 "77": [0, 0.69444, 0, 0], 7043 "78": [0, 0.69444, 0, 0], 7044 "79": [0, 0.69444, 0, 0], 7045 "80": [0, 0.69444, 0, 0], 7046 "81": [0.125, 0.69444, 0, 0], 7047 "82": [0, 0.69444, 0, 0], 7048 "83": [0, 0.69444, 0, 0], 7049 "84": [0, 0.69444, 0, 0], 7050 "85": [0, 0.69444, 0, 0], 7051 "86": [0, 0.69444, 0.01389, 0], 7052 "87": [0, 0.69444, 0.01389, 0], 7053 "88": [0, 0.69444, 0, 0], 7054 "89": [0, 0.69444, 0.025, 0], 7055 "90": [0, 0.69444, 0, 0], 7056 "91": [0.25, 0.75, 0, 0], 7057 "93": [0.25, 0.75, 0, 0], 7058 "94": [0, 0.69444, 0, 0], 7059 "95": [0.35, 0.09444, 0.02778, 0], 7060 "97": [0, 0.44444, 0, 0], 7061 "98": [0, 0.69444, 0, 0], 7062 "99": [0, 0.44444, 0, 0], 7063 "100": [0, 0.69444, 0, 0], 7064 "101": [0, 0.44444, 0, 0], 7065 "102": [0, 0.69444, 0.06944, 0], 7066 "103": [0.19444, 0.44444, 0.01389, 0], 7067 "104": [0, 0.69444, 0, 0], 7068 "105": [0, 0.67937, 0, 0], 7069 "106": [0.19444, 0.67937, 0, 0], 7070 "107": [0, 0.69444, 0, 0], 7071 "108": [0, 0.69444, 0, 0], 7072 "109": [0, 0.44444, 0, 0], 7073 "110": [0, 0.44444, 0, 0], 7074 "111": [0, 0.44444, 0, 0], 7075 "112": [0.19444, 0.44444, 0, 0], 7076 "113": [0.19444, 0.44444, 0, 0], 7077 "114": [0, 0.44444, 0.01389, 0], 7078 "115": [0, 0.44444, 0, 0], 7079 "116": [0, 0.57143, 0, 0], 7080 "117": [0, 0.44444, 0, 0], 7081 "118": [0, 0.44444, 0.01389, 0], 7082 "119": [0, 0.44444, 0.01389, 0], 7083 "120": [0, 0.44444, 0, 0], 7084 "121": [0.19444, 0.44444, 0.01389, 0], 7085 "122": [0, 0.44444, 0, 0], 7086 "126": [0.35, 0.32659, 0, 0], 7087 "305": [0, 0.44444, 0, 0], 7088 "567": [0.19444, 0.44444, 0, 0], 7089 "768": [0, 0.69444, 0, 0], 7090 "769": [0, 0.69444, 0, 0], 7091 "770": [0, 0.69444, 0, 0], 7092 "771": [0, 0.67659, 0, 0], 7093 "772": [0, 0.60889, 0, 0], 7094 "774": [0, 0.69444, 0, 0], 7095 "775": [0, 0.67937, 0, 0], 7096 "776": [0, 0.67937, 0, 0], 7097 "778": [0, 0.69444, 0, 0], 7098 "779": [0, 0.69444, 0, 0], 7099 "780": [0, 0.63194, 0, 0], 7100 "915": [0, 0.69444, 0, 0], 7101 "916": [0, 0.69444, 0, 0], 7102 "920": [0, 0.69444, 0, 0], 7103 "923": [0, 0.69444, 0, 0], 7104 "926": [0, 0.69444, 0, 0], 7105 "928": [0, 0.69444, 0, 0], 7106 "931": [0, 0.69444, 0, 0], 7107 "933": [0, 0.69444, 0, 0], 7108 "934": [0, 0.69444, 0, 0], 7109 "936": [0, 0.69444, 0, 0], 7110 "937": [0, 0.69444, 0, 0], 7111 "8211": [0, 0.44444, 0.02778, 0], 7112 "8212": [0, 0.44444, 0.02778, 0], 7113 "8216": [0, 0.69444, 0, 0], 7114 "8217": [0, 0.69444, 0, 0], 7115 "8220": [0, 0.69444, 0, 0], 7116 "8221": [0, 0.69444, 0, 0] 7117 }, 7118 "Script-Regular": { 7119 "65": [0, 0.7, 0.22925, 0], 7120 "66": [0, 0.7, 0.04087, 0], 7121 "67": [0, 0.7, 0.1689, 0], 7122 "68": [0, 0.7, 0.09371, 0], 7123 "69": [0, 0.7, 0.18583, 0], 7124 "70": [0, 0.7, 0.13634, 0], 7125 "71": [0, 0.7, 0.17322, 0], 7126 "72": [0, 0.7, 0.29694, 0], 7127 "73": [0, 0.7, 0.19189, 0], 7128 "74": [0.27778, 0.7, 0.19189, 0], 7129 "75": [0, 0.7, 0.31259, 0], 7130 "76": [0, 0.7, 0.19189, 0], 7131 "77": [0, 0.7, 0.15981, 0], 7132 "78": [0, 0.7, 0.3525, 0], 7133 "79": [0, 0.7, 0.08078, 0], 7134 "80": [0, 0.7, 0.08078, 0], 7135 "81": [0, 0.7, 0.03305, 0], 7136 "82": [0, 0.7, 0.06259, 0], 7137 "83": [0, 0.7, 0.19189, 0], 7138 "84": [0, 0.7, 0.29087, 0], 7139 "85": [0, 0.7, 0.25815, 0], 7140 "86": [0, 0.7, 0.27523, 0], 7141 "87": [0, 0.7, 0.27523, 0], 7142 "88": [0, 0.7, 0.26006, 0], 7143 "89": [0, 0.7, 0.2939, 0], 7144 "90": [0, 0.7, 0.24037, 0] 7145 }, 7146 "Size1-Regular": { 7147 "40": [0.35001, 0.85, 0, 0], 7148 "41": [0.35001, 0.85, 0, 0], 7149 "47": [0.35001, 0.85, 0, 0], 7150 "91": [0.35001, 0.85, 0, 0], 7151 "92": [0.35001, 0.85, 0, 0], 7152 "93": [0.35001, 0.85, 0, 0], 7153 "123": [0.35001, 0.85, 0, 0], 7154 "125": [0.35001, 0.85, 0, 0], 7155 "710": [0, 0.72222, 0, 0], 7156 "732": [0, 0.72222, 0, 0], 7157 "770": [0, 0.72222, 0, 0], 7158 "771": [0, 0.72222, 0, 0], 7159 "8214": [-0.00099, 0.601, 0, 0], 7160 "8593": [1e-05, 0.6, 0, 0], 7161 "8595": [1e-05, 0.6, 0, 0], 7162 "8657": [1e-05, 0.6, 0, 0], 7163 "8659": [1e-05, 0.6, 0, 0], 7164 "8719": [0.25001, 0.75, 0, 0], 7165 "8720": [0.25001, 0.75, 0, 0], 7166 "8721": [0.25001, 0.75, 0, 0], 7167 "8730": [0.35001, 0.85, 0, 0], 7168 "8739": [-0.00599, 0.606, 0, 0], 7169 "8741": [-0.00599, 0.606, 0, 0], 7170 "8747": [0.30612, 0.805, 0.19445, 0], 7171 "8748": [0.306, 0.805, 0.19445, 0], 7172 "8749": [0.306, 0.805, 0.19445, 0], 7173 "8750": [0.30612, 0.805, 0.19445, 0], 7174 "8896": [0.25001, 0.75, 0, 0], 7175 "8897": [0.25001, 0.75, 0, 0], 7176 "8898": [0.25001, 0.75, 0, 0], 7177 "8899": [0.25001, 0.75, 0, 0], 7178 "8968": [0.35001, 0.85, 0, 0], 7179 "8969": [0.35001, 0.85, 0, 0], 7180 "8970": [0.35001, 0.85, 0, 0], 7181 "8971": [0.35001, 0.85, 0, 0], 7182 "9168": [-0.00099, 0.601, 0, 0], 7183 "10216": [0.35001, 0.85, 0, 0], 7184 "10217": [0.35001, 0.85, 0, 0], 7185 "10752": [0.25001, 0.75, 0, 0], 7186 "10753": [0.25001, 0.75, 0, 0], 7187 "10754": [0.25001, 0.75, 0, 0], 7188 "10756": [0.25001, 0.75, 0, 0], 7189 "10758": [0.25001, 0.75, 0, 0] 7190 }, 7191 "Size2-Regular": { 7192 "40": [0.65002, 1.15, 0, 0], 7193 "41": [0.65002, 1.15, 0, 0], 7194 "47": [0.65002, 1.15, 0, 0], 7195 "91": [0.65002, 1.15, 0, 0], 7196 "92": [0.65002, 1.15, 0, 0], 7197 "93": [0.65002, 1.15, 0, 0], 7198 "123": [0.65002, 1.15, 0, 0], 7199 "125": [0.65002, 1.15, 0, 0], 7200 "710": [0, 0.75, 0, 0], 7201 "732": [0, 0.75, 0, 0], 7202 "770": [0, 0.75, 0, 0], 7203 "771": [0, 0.75, 0, 0], 7204 "8719": [0.55001, 1.05, 0, 0], 7205 "8720": [0.55001, 1.05, 0, 0], 7206 "8721": [0.55001, 1.05, 0, 0], 7207 "8730": [0.65002, 1.15, 0, 0], 7208 "8747": [0.86225, 1.36, 0.44445, 0], 7209 "8748": [0.862, 1.36, 0.44445, 0], 7210 "8749": [0.862, 1.36, 0.44445, 0], 7211 "8750": [0.86225, 1.36, 0.44445, 0], 7212 "8896": [0.55001, 1.05, 0, 0], 7213 "8897": [0.55001, 1.05, 0, 0], 7214 "8898": [0.55001, 1.05, 0, 0], 7215 "8899": [0.55001, 1.05, 0, 0], 7216 "8968": [0.65002, 1.15, 0, 0], 7217 "8969": [0.65002, 1.15, 0, 0], 7218 "8970": [0.65002, 1.15, 0, 0], 7219 "8971": [0.65002, 1.15, 0, 0], 7220 "10216": [0.65002, 1.15, 0, 0], 7221 "10217": [0.65002, 1.15, 0, 0], 7222 "10752": [0.55001, 1.05, 0, 0], 7223 "10753": [0.55001, 1.05, 0, 0], 7224 "10754": [0.55001, 1.05, 0, 0], 7225 "10756": [0.55001, 1.05, 0, 0], 7226 "10758": [0.55001, 1.05, 0, 0] 7227 }, 7228 "Size3-Regular": { 7229 "40": [0.95003, 1.45, 0, 0], 7230 "41": [0.95003, 1.45, 0, 0], 7231 "47": [0.95003, 1.45, 0, 0], 7232 "91": [0.95003, 1.45, 0, 0], 7233 "92": [0.95003, 1.45, 0, 0], 7234 "93": [0.95003, 1.45, 0, 0], 7235 "123": [0.95003, 1.45, 0, 0], 7236 "125": [0.95003, 1.45, 0, 0], 7237 "710": [0, 0.75, 0, 0], 7238 "732": [0, 0.75, 0, 0], 7239 "770": [0, 0.75, 0, 0], 7240 "771": [0, 0.75, 0, 0], 7241 "8730": [0.95003, 1.45, 0, 0], 7242 "8968": [0.95003, 1.45, 0, 0], 7243 "8969": [0.95003, 1.45, 0, 0], 7244 "8970": [0.95003, 1.45, 0, 0], 7245 "8971": [0.95003, 1.45, 0, 0], 7246 "10216": [0.95003, 1.45, 0, 0], 7247 "10217": [0.95003, 1.45, 0, 0] 7248 }, 7249 "Size4-Regular": { 7250 "40": [1.25003, 1.75, 0, 0], 7251 "41": [1.25003, 1.75, 0, 0], 7252 "47": [1.25003, 1.75, 0, 0], 7253 "91": [1.25003, 1.75, 0, 0], 7254 "92": [1.25003, 1.75, 0, 0], 7255 "93": [1.25003, 1.75, 0, 0], 7256 "123": [1.25003, 1.75, 0, 0], 7257 "125": [1.25003, 1.75, 0, 0], 7258 "710": [0, 0.825, 0, 0], 7259 "732": [0, 0.825, 0, 0], 7260 "770": [0, 0.825, 0, 0], 7261 "771": [0, 0.825, 0, 0], 7262 "8730": [1.25003, 1.75, 0, 0], 7263 "8968": [1.25003, 1.75, 0, 0], 7264 "8969": [1.25003, 1.75, 0, 0], 7265 "8970": [1.25003, 1.75, 0, 0], 7266 "8971": [1.25003, 1.75, 0, 0], 7267 "9115": [0.64502, 1.155, 0, 0], 7268 "9116": [1e-05, 0.6, 0, 0], 7269 "9117": [0.64502, 1.155, 0, 0], 7270 "9118": [0.64502, 1.155, 0, 0], 7271 "9119": [1e-05, 0.6, 0, 0], 7272 "9120": [0.64502, 1.155, 0, 0], 7273 "9121": [0.64502, 1.155, 0, 0], 7274 "9122": [-0.00099, 0.601, 0, 0], 7275 "9123": [0.64502, 1.155, 0, 0], 7276 "9124": [0.64502, 1.155, 0, 0], 7277 "9125": [-0.00099, 0.601, 0, 0], 7278 "9126": [0.64502, 1.155, 0, 0], 7279 "9127": [1e-05, 0.9, 0, 0], 7280 "9128": [0.65002, 1.15, 0, 0], 7281 "9129": [0.90001, 0, 0, 0], 7282 "9130": [0, 0.3, 0, 0], 7283 "9131": [1e-05, 0.9, 0, 0], 7284 "9132": [0.65002, 1.15, 0, 0], 7285 "9133": [0.90001, 0, 0, 0], 7286 "9143": [0.88502, 0.915, 0, 0], 7287 "10216": [1.25003, 1.75, 0, 0], 7288 "10217": [1.25003, 1.75, 0, 0], 7289 "57344": [-0.00499, 0.605, 0, 0], 7290 "57345": [-0.00499, 0.605, 0, 0], 7291 "57680": [0, 0.12, 0, 0], 7292 "57681": [0, 0.12, 0, 0], 7293 "57682": [0, 0.12, 0, 0], 7294 "57683": [0, 0.12, 0, 0] 7295 }, 7296 "Typewriter-Regular": { 7297 "33": [0, 0.61111, 0, 0], 7298 "34": [0, 0.61111, 0, 0], 7299 "35": [0, 0.61111, 0, 0], 7300 "36": [0.08333, 0.69444, 0, 0], 7301 "37": [0.08333, 0.69444, 0, 0], 7302 "38": [0, 0.61111, 0, 0], 7303 "39": [0, 0.61111, 0, 0], 7304 "40": [0.08333, 0.69444, 0, 0], 7305 "41": [0.08333, 0.69444, 0, 0], 7306 "42": [0, 0.52083, 0, 0], 7307 "43": [-0.08056, 0.53055, 0, 0], 7308 "44": [0.13889, 0.125, 0, 0], 7309 "45": [-0.08056, 0.53055, 0, 0], 7310 "46": [0, 0.125, 0, 0], 7311 "47": [0.08333, 0.69444, 0, 0], 7312 "48": [0, 0.61111, 0, 0], 7313 "49": [0, 0.61111, 0, 0], 7314 "50": [0, 0.61111, 0, 0], 7315 "51": [0, 0.61111, 0, 0], 7316 "52": [0, 0.61111, 0, 0], 7317 "53": [0, 0.61111, 0, 0], 7318 "54": [0, 0.61111, 0, 0], 7319 "55": [0, 0.61111, 0, 0], 7320 "56": [0, 0.61111, 0, 0], 7321 "57": [0, 0.61111, 0, 0], 7322 "58": [0, 0.43056, 0, 0], 7323 "59": [0.13889, 0.43056, 0, 0], 7324 "60": [-0.05556, 0.55556, 0, 0], 7325 "61": [-0.19549, 0.41562, 0, 0], 7326 "62": [-0.05556, 0.55556, 0, 0], 7327 "63": [0, 0.61111, 0, 0], 7328 "64": [0, 0.61111, 0, 0], 7329 "65": [0, 0.61111, 0, 0], 7330 "66": [0, 0.61111, 0, 0], 7331 "67": [0, 0.61111, 0, 0], 7332 "68": [0, 0.61111, 0, 0], 7333 "69": [0, 0.61111, 0, 0], 7334 "70": [0, 0.61111, 0, 0], 7335 "71": [0, 0.61111, 0, 0], 7336 "72": [0, 0.61111, 0, 0], 7337 "73": [0, 0.61111, 0, 0], 7338 "74": [0, 0.61111, 0, 0], 7339 "75": [0, 0.61111, 0, 0], 7340 "76": [0, 0.61111, 0, 0], 7341 "77": [0, 0.61111, 0, 0], 7342 "78": [0, 0.61111, 0, 0], 7343 "79": [0, 0.61111, 0, 0], 7344 "80": [0, 0.61111, 0, 0], 7345 "81": [0.13889, 0.61111, 0, 0], 7346 "82": [0, 0.61111, 0, 0], 7347 "83": [0, 0.61111, 0, 0], 7348 "84": [0, 0.61111, 0, 0], 7349 "85": [0, 0.61111, 0, 0], 7350 "86": [0, 0.61111, 0, 0], 7351 "87": [0, 0.61111, 0, 0], 7352 "88": [0, 0.61111, 0, 0], 7353 "89": [0, 0.61111, 0, 0], 7354 "90": [0, 0.61111, 0, 0], 7355 "91": [0.08333, 0.69444, 0, 0], 7356 "92": [0.08333, 0.69444, 0, 0], 7357 "93": [0.08333, 0.69444, 0, 0], 7358 "94": [0, 0.61111, 0, 0], 7359 "95": [0.09514, 0, 0, 0], 7360 "96": [0, 0.61111, 0, 0], 7361 "97": [0, 0.43056, 0, 0], 7362 "98": [0, 0.61111, 0, 0], 7363 "99": [0, 0.43056, 0, 0], 7364 "100": [0, 0.61111, 0, 0], 7365 "101": [0, 0.43056, 0, 0], 7366 "102": [0, 0.61111, 0, 0], 7367 "103": [0.22222, 0.43056, 0, 0], 7368 "104": [0, 0.61111, 0, 0], 7369 "105": [0, 0.61111, 0, 0], 7370 "106": [0.22222, 0.61111, 0, 0], 7371 "107": [0, 0.61111, 0, 0], 7372 "108": [0, 0.61111, 0, 0], 7373 "109": [0, 0.43056, 0, 0], 7374 "110": [0, 0.43056, 0, 0], 7375 "111": [0, 0.43056, 0, 0], 7376 "112": [0.22222, 0.43056, 0, 0], 7377 "113": [0.22222, 0.43056, 0, 0], 7378 "114": [0, 0.43056, 0, 0], 7379 "115": [0, 0.43056, 0, 0], 7380 "116": [0, 0.55358, 0, 0], 7381 "117": [0, 0.43056, 0, 0], 7382 "118": [0, 0.43056, 0, 0], 7383 "119": [0, 0.43056, 0, 0], 7384 "120": [0, 0.43056, 0, 0], 7385 "121": [0.22222, 0.43056, 0, 0], 7386 "122": [0, 0.43056, 0, 0], 7387 "123": [0.08333, 0.69444, 0, 0], 7388 "124": [0.08333, 0.69444, 0, 0], 7389 "125": [0.08333, 0.69444, 0, 0], 7390 "126": [0, 0.61111, 0, 0], 7391 "127": [0, 0.61111, 0, 0], 7392 "305": [0, 0.43056, 0, 0], 7393 "567": [0.22222, 0.43056, 0, 0], 7394 "768": [0, 0.61111, 0, 0], 7395 "769": [0, 0.61111, 0, 0], 7396 "770": [0, 0.61111, 0, 0], 7397 "771": [0, 0.61111, 0, 0], 7398 "772": [0, 0.56555, 0, 0], 7399 "774": [0, 0.61111, 0, 0], 7400 "776": [0, 0.61111, 0, 0], 7401 "778": [0, 0.61111, 0, 0], 7402 "780": [0, 0.56597, 0, 0], 7403 "915": [0, 0.61111, 0, 0], 7404 "916": [0, 0.61111, 0, 0], 7405 "920": [0, 0.61111, 0, 0], 7406 "923": [0, 0.61111, 0, 0], 7407 "926": [0, 0.61111, 0, 0], 7408 "928": [0, 0.61111, 0, 0], 7409 "931": [0, 0.61111, 0, 0], 7410 "933": [0, 0.61111, 0, 0], 7411 "934": [0, 0.61111, 0, 0], 7412 "936": [0, 0.61111, 0, 0], 7413 "937": [0, 0.61111, 0, 0], 7414 "2018": [0, 0.61111, 0, 0], 7415 "2019": [0, 0.61111, 0, 0], 7416 "8242": [0, 0.61111, 0, 0] 7417 } 7418}; 7419 7420},{}],19:[function(require,module,exports){ 7421var utils = require("./utils"); 7422var ParseError = require("./ParseError"); 7423var parseData = require("./parseData"); 7424var ParseNode = parseData.ParseNode; 7425 7426/* This file contains a list of functions that we parse, identified by 7427 * the calls to defineFunction. 7428 * 7429 * The first argument to defineFunction is a single name or a list of names. 7430 * All functions named in such a list will share a single implementation. 7431 * 7432 * Each declared function can have associated properties, which 7433 * include the following: 7434 * 7435 * - numArgs: The number of arguments the function takes. 7436 * If this is the only property, it can be passed as a number 7437 * instead of an element of a properties object. 7438 * - argTypes: (optional) An array corresponding to each argument of the 7439 * function, giving the type of argument that should be parsed. Its 7440 * length should be equal to `numArgs + numOptionalArgs`. Valid 7441 * types: 7442 * - "size": A size-like thing, such as "1em" or "5ex" 7443 * - "color": An html color, like "#abc" or "blue" 7444 * - "original": The same type as the environment that the 7445 * function being parsed is in (e.g. used for the 7446 * bodies of functions like \color where the first 7447 * argument is special and the second argument is 7448 * parsed normally) 7449 * Other possible types (probably shouldn't be used) 7450 * - "text": Text-like (e.g. \text) 7451 * - "math": Normal math 7452 * If undefined, this will be treated as an appropriate length 7453 * array of "original" strings 7454 * - greediness: (optional) The greediness of the function to use ungrouped 7455 * arguments. 7456 * 7457 * E.g. if you have an expression 7458 * \sqrt \frac 1 2 7459 * since \frac has greediness=2 vs \sqrt's greediness=1, \frac 7460 * will use the two arguments '1' and '2' as its two arguments, 7461 * then that whole function will be used as the argument to 7462 * \sqrt. On the other hand, the expressions 7463 * \frac \frac 1 2 3 7464 * and 7465 * \frac \sqrt 1 2 7466 * will fail because \frac and \frac have equal greediness 7467 * and \sqrt has a lower greediness than \frac respectively. To 7468 * make these parse, we would have to change them to: 7469 * \frac {\frac 1 2} 3 7470 * and 7471 * \frac {\sqrt 1} 2 7472 * 7473 * The default value is `1` 7474 * - allowedInText: (optional) Whether or not the function is allowed inside 7475 * text mode (default false) 7476 * - numOptionalArgs: (optional) The number of optional arguments the function 7477 * should parse. If the optional arguments aren't found, 7478 * `null` will be passed to the handler in their place. 7479 * (default 0) 7480 * - infix: (optional) Must be true if the function is an infix operator. 7481 * 7482 * The last argument is that implementation, the handler for the function(s). 7483 * It is called to handle these functions and their arguments. 7484 * It receives two arguments: 7485 * - context contains information and references provided by the parser 7486 * - args is an array of arguments obtained from TeX input 7487 * The context contains the following properties: 7488 * - funcName: the text (i.e. name) of the function, including \ 7489 * - parser: the parser object 7490 * - lexer: the lexer object 7491 * - positions: the positions in the overall string of the function 7492 * and the arguments. 7493 * The latter three should only be used to produce error messages. 7494 * 7495 * The function should return an object with the following keys: 7496 * - type: The type of element that this is. This is then used in 7497 * buildHTML/buildMathML to determine which function 7498 * should be called to build this node into a DOM node 7499 * Any other data can be added to the object, which will be passed 7500 * in to the function in buildHTML/buildMathML as `group.value`. 7501 */ 7502 7503function defineFunction(names, props, handler) { 7504 if (typeof names === "string") { 7505 names = [names]; 7506 } 7507 if (typeof props === "number") { 7508 props = { numArgs: props }; 7509 } 7510 // Set default values of functions 7511 var data = { 7512 numArgs: props.numArgs, 7513 argTypes: props.argTypes, 7514 greediness: (props.greediness === undefined) ? 1 : props.greediness, 7515 allowedInText: !!props.allowedInText, 7516 numOptionalArgs: props.numOptionalArgs || 0, 7517 infix: !!props.infix, 7518 handler: handler 7519 }; 7520 for (var i = 0; i < names.length; ++i) { 7521 module.exports[names[i]] = data; 7522 } 7523} 7524 7525// Since the corresponding buildHTML/buildMathML function expects a 7526// list of elements, we normalize for different kinds of arguments 7527var ordargument = function(arg) { 7528 if (arg.type === "ordgroup") { 7529 return arg.value; 7530 } else { 7531 return [arg]; 7532 } 7533}; 7534 7535// A normal square root 7536defineFunction("\\sqrt", { 7537 numArgs: 1, 7538 numOptionalArgs: 1 7539}, function(context, args) { 7540 var index = args[0]; 7541 var body = args[1]; 7542 return { 7543 type: "sqrt", 7544 body: body, 7545 index: index 7546 }; 7547}); 7548 7549// Non-mathy text, possibly in a font 7550var textFunctionStyles = { 7551 "\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf", 7552 "\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf", 7553 "\\textit": "textit" 7554}; 7555 7556defineFunction([ 7557 "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", 7558 "\\textbf", "\\textit" 7559], { 7560 numArgs: 1, 7561 argTypes: ["text"], 7562 greediness: 2, 7563 allowedInText: true 7564}, function(context, args) { 7565 var body = args[0]; 7566 return { 7567 type: "text", 7568 body: ordargument(body), 7569 style: textFunctionStyles[context.funcName] 7570 }; 7571}); 7572 7573// A two-argument custom color 7574defineFunction("\\color", { 7575 numArgs: 2, 7576 allowedInText: true, 7577 greediness: 3, 7578 argTypes: ["color", "original"] 7579}, function(context, args) { 7580 var color = args[0]; 7581 var body = args[1]; 7582 return { 7583 type: "color", 7584 color: color.value, 7585 value: ordargument(body) 7586 }; 7587}); 7588 7589// An overline 7590defineFunction("\\overline", { 7591 numArgs: 1 7592}, function(context, args) { 7593 var body = args[0]; 7594 return { 7595 type: "overline", 7596 body: body 7597 }; 7598}); 7599 7600// An underline 7601defineFunction("\\underline", { 7602 numArgs: 1 7603}, function(context, args) { 7604 var body = args[0]; 7605 return { 7606 type: "underline", 7607 body: body 7608 }; 7609}); 7610 7611// A box of the width and height 7612defineFunction("\\rule", { 7613 numArgs: 2, 7614 numOptionalArgs: 1, 7615 argTypes: ["size", "size", "size"] 7616}, function(context, args) { 7617 var shift = args[0]; 7618 var width = args[1]; 7619 var height = args[2]; 7620 return { 7621 type: "rule", 7622 shift: shift && shift.value, 7623 width: width.value, 7624 height: height.value 7625 }; 7626}); 7627 7628// TODO: In TeX, \mkern only accepts mu-units, and \kern does not accept 7629// mu-units. In current KaTeX we relax this; both commands accept any unit. 7630defineFunction(["\\kern", "\\mkern"], { 7631 numArgs: 1, 7632 argTypes: ["size"] 7633}, function(context, args) { 7634 return { 7635 type: "kern", 7636 dimension: args[0].value 7637 }; 7638}); 7639 7640// A KaTeX logo 7641defineFunction("\\KaTeX", { 7642 numArgs: 0 7643}, function(context) { 7644 return { 7645 type: "katex" 7646 }; 7647}); 7648 7649defineFunction("\\phantom", { 7650 numArgs: 1 7651}, function(context, args) { 7652 var body = args[0]; 7653 return { 7654 type: "phantom", 7655 value: ordargument(body) 7656 }; 7657}); 7658 7659// Math class commands except \mathop 7660defineFunction([ 7661 "\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", 7662 "\\mathclose", "\\mathpunct", "\\mathinner" 7663], { 7664 numArgs: 1 7665}, function(context, args) { 7666 var body = args[0]; 7667 return { 7668 type: "mclass", 7669 mclass: "m" + context.funcName.substr(5), 7670 value: ordargument(body) 7671 }; 7672}); 7673 7674// Build a relation by placing one symbol on top of another 7675defineFunction("\\stackrel", { 7676 numArgs: 2 7677}, function(context, args) { 7678 var top = args[0]; 7679 var bottom = args[1]; 7680 7681 var bottomop = new ParseNode("op", { 7682 type: "op", 7683 limits: true, 7684 alwaysHandleSupSub: true, 7685 symbol: false, 7686 value: ordargument(bottom) 7687 }, bottom.mode); 7688 7689 var supsub = new ParseNode("supsub", { 7690 base: bottomop, 7691 sup: top, 7692 sub: null 7693 }, top.mode); 7694 7695 return { 7696 type: "mclass", 7697 mclass: "mrel", 7698 value: [supsub] 7699 }; 7700}); 7701 7702// \mod-type functions 7703defineFunction("\\bmod", { 7704 numArgs: 0 7705}, function(context, args) { 7706 return { 7707 type: "mod", 7708 modType: "bmod", 7709 value: null 7710 }; 7711}); 7712 7713defineFunction(["\\pod", "\\pmod", "\\mod"], { 7714 numArgs: 1 7715}, function(context, args) { 7716 var body = args[0]; 7717 return { 7718 type: "mod", 7719 modType: context.funcName.substr(1), 7720 value: ordargument(body) 7721 }; 7722}); 7723 7724// Extra data needed for the delimiter handler down below 7725var delimiterSizes = { 7726 "\\bigl" : {mclass: "mopen", size: 1}, 7727 "\\Bigl" : {mclass: "mopen", size: 2}, 7728 "\\biggl": {mclass: "mopen", size: 3}, 7729 "\\Biggl": {mclass: "mopen", size: 4}, 7730 "\\bigr" : {mclass: "mclose", size: 1}, 7731 "\\Bigr" : {mclass: "mclose", size: 2}, 7732 "\\biggr": {mclass: "mclose", size: 3}, 7733 "\\Biggr": {mclass: "mclose", size: 4}, 7734 "\\bigm" : {mclass: "mrel", size: 1}, 7735 "\\Bigm" : {mclass: "mrel", size: 2}, 7736 "\\biggm": {mclass: "mrel", size: 3}, 7737 "\\Biggm": {mclass: "mrel", size: 4}, 7738 "\\big" : {mclass: "mord", size: 1}, 7739 "\\Big" : {mclass: "mord", size: 2}, 7740 "\\bigg" : {mclass: "mord", size: 3}, 7741 "\\Bigg" : {mclass: "mord", size: 4} 7742}; 7743 7744var delimiters = [ 7745 "(", ")", "[", "\\lbrack", "]", "\\rbrack", 7746 "\\{", "\\lbrace", "\\}", "\\rbrace", 7747 "\\lfloor", "\\rfloor", "\\lceil", "\\rceil", 7748 "<", ">", "\\langle", "\\rangle", "\\lt", "\\gt", 7749 "\\lvert", "\\rvert", "\\lVert", "\\rVert", 7750 "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache", 7751 "/", "\\backslash", 7752 "|", "\\vert", "\\|", "\\Vert", 7753 "\\uparrow", "\\Uparrow", 7754 "\\downarrow", "\\Downarrow", 7755 "\\updownarrow", "\\Updownarrow", 7756 "." 7757]; 7758 7759var fontAliases = { 7760 "\\Bbb": "\\mathbb", 7761 "\\bold": "\\mathbf", 7762 "\\frak": "\\mathfrak" 7763}; 7764 7765// Single-argument color functions 7766defineFunction([ 7767 "\\blue", "\\orange", "\\pink", "\\red", 7768 "\\green", "\\gray", "\\purple", 7769 "\\blueA", "\\blueB", "\\blueC", "\\blueD", "\\blueE", 7770 "\\tealA", "\\tealB", "\\tealC", "\\tealD", "\\tealE", 7771 "\\greenA", "\\greenB", "\\greenC", "\\greenD", "\\greenE", 7772 "\\goldA", "\\goldB", "\\goldC", "\\goldD", "\\goldE", 7773 "\\redA", "\\redB", "\\redC", "\\redD", "\\redE", 7774 "\\maroonA", "\\maroonB", "\\maroonC", "\\maroonD", "\\maroonE", 7775 "\\purpleA", "\\purpleB", "\\purpleC", "\\purpleD", "\\purpleE", 7776 "\\mintA", "\\mintB", "\\mintC", 7777 "\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE", 7778 "\\grayF", "\\grayG", "\\grayH", "\\grayI", 7779 "\\kaBlue", "\\kaGreen" 7780], { 7781 numArgs: 1, 7782 allowedInText: true, 7783 greediness: 3 7784}, function(context, args) { 7785 var body = args[0]; 7786 return { 7787 type: "color", 7788 color: "katex-" + context.funcName.slice(1), 7789 value: ordargument(body) 7790 }; 7791}); 7792 7793// There are 2 flags for operators; whether they produce limits in 7794// displaystyle, and whether they are symbols and should grow in 7795// displaystyle. These four groups cover the four possible choices. 7796 7797// No limits, not symbols 7798defineFunction([ 7799 "\\arcsin", "\\arccos", "\\arctan", "\\arg", "\\cos", "\\cosh", 7800 "\\cot", "\\coth", "\\csc", "\\deg", "\\dim", "\\exp", "\\hom", 7801 "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", 7802 "\\tan", "\\tanh" 7803], { 7804 numArgs: 0 7805}, function(context) { 7806 return { 7807 type: "op", 7808 limits: false, 7809 symbol: false, 7810 body: context.funcName 7811 }; 7812}); 7813 7814// Limits, not symbols 7815defineFunction([ 7816 "\\det", "\\gcd", "\\inf", "\\lim", "\\liminf", "\\limsup", "\\max", 7817 "\\min", "\\Pr", "\\sup" 7818], { 7819 numArgs: 0 7820}, function(context) { 7821 return { 7822 type: "op", 7823 limits: true, 7824 symbol: false, 7825 body: context.funcName 7826 }; 7827}); 7828 7829// No limits, symbols 7830defineFunction([ 7831 "\\int", "\\iint", "\\iiint", "\\oint" 7832], { 7833 numArgs: 0 7834}, function(context) { 7835 return { 7836 type: "op", 7837 limits: false, 7838 symbol: true, 7839 body: context.funcName 7840 }; 7841}); 7842 7843// Limits, symbols 7844defineFunction([ 7845 "\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", 7846 "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", 7847 "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint" 7848], { 7849 numArgs: 0 7850}, function(context) { 7851 return { 7852 type: "op", 7853 limits: true, 7854 symbol: true, 7855 body: context.funcName 7856 }; 7857}); 7858 7859// \mathop class command 7860defineFunction("\\mathop", { 7861 numArgs: 1 7862}, function(context, args) { 7863 var body = args[0]; 7864 return { 7865 type: "op", 7866 limits: false, 7867 symbol: false, 7868 value: ordargument(body) 7869 }; 7870}); 7871 7872// Fractions 7873defineFunction([ 7874 "\\dfrac", "\\frac", "\\tfrac", 7875 "\\dbinom", "\\binom", "\\tbinom", 7876 "\\\\atopfrac" // can’t be entered directly 7877], { 7878 numArgs: 2, 7879 greediness: 2 7880}, function(context, args) { 7881 var numer = args[0]; 7882 var denom = args[1]; 7883 var hasBarLine; 7884 var leftDelim = null; 7885 var rightDelim = null; 7886 var size = "auto"; 7887 7888 switch (context.funcName) { 7889 case "\\dfrac": 7890 case "\\frac": 7891 case "\\tfrac": 7892 hasBarLine = true; 7893 break; 7894 case "\\\\atopfrac": 7895 hasBarLine = false; 7896 break; 7897 case "\\dbinom": 7898 case "\\binom": 7899 case "\\tbinom": 7900 hasBarLine = false; 7901 leftDelim = "("; 7902 rightDelim = ")"; 7903 break; 7904 default: 7905 throw new Error("Unrecognized genfrac command"); 7906 } 7907 7908 switch (context.funcName) { 7909 case "\\dfrac": 7910 case "\\dbinom": 7911 size = "display"; 7912 break; 7913 case "\\tfrac": 7914 case "\\tbinom": 7915 size = "text"; 7916 break; 7917 } 7918 7919 return { 7920 type: "genfrac", 7921 numer: numer, 7922 denom: denom, 7923 hasBarLine: hasBarLine, 7924 leftDelim: leftDelim, 7925 rightDelim: rightDelim, 7926 size: size 7927 }; 7928}); 7929 7930// Left and right overlap functions 7931defineFunction(["\\llap", "\\rlap"], { 7932 numArgs: 1, 7933 allowedInText: true 7934}, function(context, args) { 7935 var body = args[0]; 7936 return { 7937 type: context.funcName.slice(1), 7938 body: body 7939 }; 7940}); 7941 7942// Delimiter functions 7943var checkDelimiter = function(delim, context) { 7944 if (utils.contains(delimiters, delim.value)) { 7945 return delim; 7946 } else { 7947 throw new ParseError( 7948 "Invalid delimiter: '" + delim.value + "' after '" + 7949 context.funcName + "'", delim); 7950 } 7951}; 7952 7953defineFunction([ 7954 "\\bigl", "\\Bigl", "\\biggl", "\\Biggl", 7955 "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", 7956 "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", 7957 "\\big", "\\Big", "\\bigg", "\\Bigg" 7958], { 7959 numArgs: 1 7960}, function(context, args) { 7961 var delim = checkDelimiter(args[0], context); 7962 7963 return { 7964 type: "delimsizing", 7965 size: delimiterSizes[context.funcName].size, 7966 mclass: delimiterSizes[context.funcName].mclass, 7967 value: delim.value 7968 }; 7969}); 7970 7971defineFunction([ 7972 "\\left", "\\right" 7973], { 7974 numArgs: 1 7975}, function(context, args) { 7976 var delim = checkDelimiter(args[0], context); 7977 7978 // \left and \right are caught somewhere in Parser.js, which is 7979 // why this data doesn't match what is in buildHTML. 7980 return { 7981 type: "leftright", 7982 value: delim.value 7983 }; 7984}); 7985 7986defineFunction("\\middle", { 7987 numArgs: 1 7988}, function(context, args) { 7989 var delim = checkDelimiter(args[0], context); 7990 if (!context.parser.leftrightDepth) { 7991 throw new ParseError("\\middle without preceding \\left", delim); 7992 } 7993 7994 return { 7995 type: "middle", 7996 value: delim.value 7997 }; 7998}); 7999 8000// Sizing functions (handled in Parser.js explicitly, hence no handler) 8001defineFunction([ 8002 "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", 8003 "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge" 8004], 0, null); 8005 8006// Style changing functions (handled in Parser.js explicitly, hence no 8007// handler) 8008defineFunction([ 8009 "\\displaystyle", "\\textstyle", "\\scriptstyle", 8010 "\\scriptscriptstyle" 8011], 0, null); 8012 8013defineFunction([ 8014 // styles 8015 "\\mathrm", "\\mathit", "\\mathbf", 8016 8017 // families 8018 "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", 8019 "\\mathtt", 8020 8021 // aliases 8022 "\\Bbb", "\\bold", "\\frak" 8023], { 8024 numArgs: 1, 8025 greediness: 2 8026}, function(context, args) { 8027 var body = args[0]; 8028 var func = context.funcName; 8029 if (func in fontAliases) { 8030 func = fontAliases[func]; 8031 } 8032 return { 8033 type: "font", 8034 font: func.slice(1), 8035 body: body 8036 }; 8037}); 8038 8039// Accents 8040defineFunction([ 8041 "\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", 8042 "\\check", "\\hat", "\\vec", "\\dot" 8043 // We don't support expanding accents yet 8044 // "\\widetilde", "\\widehat" 8045], { 8046 numArgs: 1 8047}, function(context, args) { 8048 var base = args[0]; 8049 return { 8050 type: "accent", 8051 accent: context.funcName, 8052 base: base 8053 }; 8054}); 8055 8056// Infix generalized fractions 8057defineFunction(["\\over", "\\choose", "\\atop"], { 8058 numArgs: 0, 8059 infix: true 8060}, function(context) { 8061 var replaceWith; 8062 switch (context.funcName) { 8063 case "\\over": 8064 replaceWith = "\\frac"; 8065 break; 8066 case "\\choose": 8067 replaceWith = "\\binom"; 8068 break; 8069 case "\\atop": 8070 replaceWith = "\\\\atopfrac"; 8071 break; 8072 default: 8073 throw new Error("Unrecognized infix genfrac command"); 8074 } 8075 return { 8076 type: "infix", 8077 replaceWith: replaceWith, 8078 token: context.token 8079 }; 8080}); 8081 8082// Row breaks for aligned data 8083defineFunction(["\\\\", "\\cr"], { 8084 numArgs: 0, 8085 numOptionalArgs: 1, 8086 argTypes: ["size"] 8087}, function(context, args) { 8088 var size = args[0]; 8089 return { 8090 type: "cr", 8091 size: size 8092 }; 8093}); 8094 8095// Environment delimiters 8096defineFunction(["\\begin", "\\end"], { 8097 numArgs: 1, 8098 argTypes: ["text"] 8099}, function(context, args) { 8100 var nameGroup = args[0]; 8101 if (nameGroup.type !== "ordgroup") { 8102 throw new ParseError("Invalid environment name", nameGroup); 8103 } 8104 var name = ""; 8105 for (var i = 0; i < nameGroup.value.length; ++i) { 8106 name += nameGroup.value[i].value; 8107 } 8108 return { 8109 type: "environment", 8110 name: name, 8111 nameGroup: nameGroup 8112 }; 8113}); 8114 8115},{"./ParseError":6,"./parseData":21,"./utils":25}],20:[function(require,module,exports){ 8116/** 8117 * These objects store data about MathML nodes. This is the MathML equivalent 8118 * of the types in domTree.js. Since MathML handles its own rendering, and 8119 * since we're mainly using MathML to improve accessibility, we don't manage 8120 * any of the styling state that the plain DOM nodes do. 8121 * 8122 * The `toNode` and `toMarkup` functions work simlarly to how they do in 8123 * domTree.js, creating namespaced DOM nodes and HTML text markup respectively. 8124 */ 8125 8126var utils = require("./utils"); 8127 8128/** 8129 * This node represents a general purpose MathML node of any type. The 8130 * constructor requires the type of node to create (for example, `"mo"` or 8131 * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags). 8132 */ 8133function MathNode(type, children) { 8134 this.type = type; 8135 this.attributes = {}; 8136 this.children = children || []; 8137} 8138 8139/** 8140 * Sets an attribute on a MathML node. MathML depends on attributes to convey a 8141 * semantic content, so this is used heavily. 8142 */ 8143MathNode.prototype.setAttribute = function(name, value) { 8144 this.attributes[name] = value; 8145}; 8146 8147/** 8148 * Converts the math node into a MathML-namespaced DOM element. 8149 */ 8150MathNode.prototype.toNode = function() { 8151 var node = document.createElementNS( 8152 "http://www.w3.org/1998/Math/MathML", this.type); 8153 8154 for (var attr in this.attributes) { 8155 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 8156 node.setAttribute(attr, this.attributes[attr]); 8157 } 8158 } 8159 8160 for (var i = 0; i < this.children.length; i++) { 8161 node.appendChild(this.children[i].toNode()); 8162 } 8163 8164 return node; 8165}; 8166 8167/** 8168 * Converts the math node into an HTML markup string. 8169 */ 8170MathNode.prototype.toMarkup = function() { 8171 var markup = "<" + this.type; 8172 8173 // Add the attributes 8174 for (var attr in this.attributes) { 8175 if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { 8176 markup += " " + attr + "=\""; 8177 markup += utils.escape(this.attributes[attr]); 8178 markup += "\""; 8179 } 8180 } 8181 8182 markup += ">"; 8183 8184 for (var i = 0; i < this.children.length; i++) { 8185 markup += this.children[i].toMarkup(); 8186 } 8187 8188 markup += "</" + this.type + ">"; 8189 8190 return markup; 8191}; 8192 8193/** 8194 * This node represents a piece of text. 8195 */ 8196function TextNode(text) { 8197 this.text = text; 8198} 8199 8200/** 8201 * Converts the text node into a DOM text node. 8202 */ 8203TextNode.prototype.toNode = function() { 8204 return document.createTextNode(this.text); 8205}; 8206 8207/** 8208 * Converts the text node into HTML markup (which is just the text itself). 8209 */ 8210TextNode.prototype.toMarkup = function() { 8211 return utils.escape(this.text); 8212}; 8213 8214module.exports = { 8215 MathNode: MathNode, 8216 TextNode: TextNode 8217}; 8218 8219},{"./utils":25}],21:[function(require,module,exports){ 8220/** 8221 * The resulting parse tree nodes of the parse tree. 8222 * 8223 * It is possible to provide position information, so that a ParseNode can 8224 * fulfil a role similar to a Token in error reporting. 8225 * For details on the corresponding properties see Token constructor. 8226 * Providing such information can lead to better error reporting. 8227 * 8228 * @param {string} type type of node, like e.g. "ordgroup" 8229 * @param {?object} value type-specific representation of the node 8230 * @param {string} mode parse mode in action for this node, 8231 * "math" or "text" 8232 * @param {Token=} firstToken first token of the input for this node, 8233 * will omit position information if unset 8234 * @param {Token=} lastToken last token of the input for this node, 8235 * will default to firstToken if unset 8236 */ 8237function ParseNode(type, value, mode, firstToken, lastToken) { 8238 this.type = type; 8239 this.value = value; 8240 this.mode = mode; 8241 if (firstToken && (!lastToken || lastToken.lexer === firstToken.lexer)) { 8242 this.lexer = firstToken.lexer; 8243 this.start = firstToken.start; 8244 this.end = (lastToken || firstToken).end; 8245 } 8246} 8247 8248module.exports = { 8249 ParseNode: ParseNode 8250}; 8251 8252 8253},{}],22:[function(require,module,exports){ 8254/** 8255 * Provides a single function for parsing an expression using a Parser 8256 * TODO(emily): Remove this 8257 */ 8258 8259var Parser = require("./Parser"); 8260 8261/** 8262 * Parses an expression using a Parser, then returns the parsed result. 8263 */ 8264var parseTree = function(toParse, settings) { 8265 if (!(typeof toParse === 'string' || toParse instanceof String)) { 8266 throw new TypeError('KaTeX can only parse string typed expression'); 8267 } 8268 var parser = new Parser(toParse, settings); 8269 8270 return parser.parse(); 8271}; 8272 8273module.exports = parseTree; 8274 8275},{"./Parser":7}],23:[function(require,module,exports){ 8276/** 8277 * This file holds a list of all no-argument functions and single-character 8278 * symbols (like 'a' or ';'). 8279 * 8280 * For each of the symbols, there are three properties they can have: 8281 * - font (required): the font to be used for this symbol. Either "main" (the 8282 normal font), or "ams" (the ams fonts). 8283 * - group (required): the ParseNode group type the symbol should have (i.e. 8284 "textord", "mathord", etc). 8285 See https://github.com/Khan/KaTeX/wiki/Examining-TeX#group-types 8286 * - replace: the character that this symbol or function should be 8287 * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi 8288 * character in the main font). 8289 * 8290 * The outermost map in the table indicates what mode the symbols should be 8291 * accepted in (e.g. "math" or "text"). 8292 */ 8293 8294module.exports = { 8295 math: {}, 8296 text: {} 8297}; 8298 8299function defineSymbol(mode, font, group, replace, name) { 8300 module.exports[mode][name] = { 8301 font: font, 8302 group: group, 8303 replace: replace 8304 }; 8305} 8306 8307// Some abbreviations for commonly used strings. 8308// This helps minify the code, and also spotting typos using jshint. 8309 8310// modes: 8311var math = "math"; 8312var text = "text"; 8313 8314// fonts: 8315var main = "main"; 8316var ams = "ams"; 8317 8318// groups: 8319var accent = "accent"; 8320var bin = "bin"; 8321var close = "close"; 8322var inner = "inner"; 8323var mathord = "mathord"; 8324var op = "op"; 8325var open = "open"; 8326var punct = "punct"; 8327var rel = "rel"; 8328var spacing = "spacing"; 8329var textord = "textord"; 8330 8331// Now comes the symbol table 8332 8333// Relation Symbols 8334defineSymbol(math, main, rel, "\u2261", "\\equiv"); 8335defineSymbol(math, main, rel, "\u227a", "\\prec"); 8336defineSymbol(math, main, rel, "\u227b", "\\succ"); 8337defineSymbol(math, main, rel, "\u223c", "\\sim"); 8338defineSymbol(math, main, rel, "\u22a5", "\\perp"); 8339defineSymbol(math, main, rel, "\u2aaf", "\\preceq"); 8340defineSymbol(math, main, rel, "\u2ab0", "\\succeq"); 8341defineSymbol(math, main, rel, "\u2243", "\\simeq"); 8342defineSymbol(math, main, rel, "\u2223", "\\mid"); 8343defineSymbol(math, main, rel, "\u226a", "\\ll"); 8344defineSymbol(math, main, rel, "\u226b", "\\gg"); 8345defineSymbol(math, main, rel, "\u224d", "\\asymp"); 8346defineSymbol(math, main, rel, "\u2225", "\\parallel"); 8347defineSymbol(math, main, rel, "\u22c8", "\\bowtie"); 8348defineSymbol(math, main, rel, "\u2323", "\\smile"); 8349defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq"); 8350defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq"); 8351defineSymbol(math, main, rel, "\u2250", "\\doteq"); 8352defineSymbol(math, main, rel, "\u2322", "\\frown"); 8353defineSymbol(math, main, rel, "\u220b", "\\ni"); 8354defineSymbol(math, main, rel, "\u221d", "\\propto"); 8355defineSymbol(math, main, rel, "\u22a2", "\\vdash"); 8356defineSymbol(math, main, rel, "\u22a3", "\\dashv"); 8357defineSymbol(math, main, rel, "\u220b", "\\owns"); 8358 8359// Punctuation 8360defineSymbol(math, main, punct, "\u002e", "\\ldotp"); 8361defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); 8362 8363// Misc Symbols 8364defineSymbol(math, main, textord, "\u0023", "\\#"); 8365defineSymbol(text, main, textord, "\u0023", "\\#"); 8366defineSymbol(math, main, textord, "\u0026", "\\&"); 8367defineSymbol(text, main, textord, "\u0026", "\\&"); 8368defineSymbol(math, main, textord, "\u2135", "\\aleph"); 8369defineSymbol(math, main, textord, "\u2200", "\\forall"); 8370defineSymbol(math, main, textord, "\u210f", "\\hbar"); 8371defineSymbol(math, main, textord, "\u2203", "\\exists"); 8372defineSymbol(math, main, textord, "\u2207", "\\nabla"); 8373defineSymbol(math, main, textord, "\u266d", "\\flat"); 8374defineSymbol(math, main, textord, "\u2113", "\\ell"); 8375defineSymbol(math, main, textord, "\u266e", "\\natural"); 8376defineSymbol(math, main, textord, "\u2663", "\\clubsuit"); 8377defineSymbol(math, main, textord, "\u2118", "\\wp"); 8378defineSymbol(math, main, textord, "\u266f", "\\sharp"); 8379defineSymbol(math, main, textord, "\u2662", "\\diamondsuit"); 8380defineSymbol(math, main, textord, "\u211c", "\\Re"); 8381defineSymbol(math, main, textord, "\u2661", "\\heartsuit"); 8382defineSymbol(math, main, textord, "\u2111", "\\Im"); 8383defineSymbol(math, main, textord, "\u2660", "\\spadesuit"); 8384 8385// Math and Text 8386defineSymbol(math, main, textord, "\u2020", "\\dag"); 8387defineSymbol(math, main, textord, "\u2021", "\\ddag"); 8388 8389// Large Delimiters 8390defineSymbol(math, main, close, "\u23b1", "\\rmoustache"); 8391defineSymbol(math, main, open, "\u23b0", "\\lmoustache"); 8392defineSymbol(math, main, close, "\u27ef", "\\rgroup"); 8393defineSymbol(math, main, open, "\u27ee", "\\lgroup"); 8394 8395// Binary Operators 8396defineSymbol(math, main, bin, "\u2213", "\\mp"); 8397defineSymbol(math, main, bin, "\u2296", "\\ominus"); 8398defineSymbol(math, main, bin, "\u228e", "\\uplus"); 8399defineSymbol(math, main, bin, "\u2293", "\\sqcap"); 8400defineSymbol(math, main, bin, "\u2217", "\\ast"); 8401defineSymbol(math, main, bin, "\u2294", "\\sqcup"); 8402defineSymbol(math, main, bin, "\u25ef", "\\bigcirc"); 8403defineSymbol(math, main, bin, "\u2219", "\\bullet"); 8404defineSymbol(math, main, bin, "\u2021", "\\ddagger"); 8405defineSymbol(math, main, bin, "\u2240", "\\wr"); 8406defineSymbol(math, main, bin, "\u2a3f", "\\amalg"); 8407 8408// Arrow Symbols 8409defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow"); 8410defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow"); 8411defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow"); 8412defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow"); 8413defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow"); 8414defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow"); 8415defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow"); 8416defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow"); 8417defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow"); 8418defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow"); 8419defineSymbol(math, main, rel, "\u21a6", "\\mapsto"); 8420defineSymbol(math, main, rel, "\u27fc", "\\longmapsto"); 8421defineSymbol(math, main, rel, "\u2197", "\\nearrow"); 8422defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow"); 8423defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow"); 8424defineSymbol(math, main, rel, "\u2198", "\\searrow"); 8425defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup"); 8426defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup"); 8427defineSymbol(math, main, rel, "\u2199", "\\swarrow"); 8428defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown"); 8429defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown"); 8430defineSymbol(math, main, rel, "\u2196", "\\nwarrow"); 8431defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons"); 8432 8433// AMS Negated Binary Relations 8434defineSymbol(math, ams, rel, "\u226e", "\\nless"); 8435defineSymbol(math, ams, rel, "\ue010", "\\nleqslant"); 8436defineSymbol(math, ams, rel, "\ue011", "\\nleqq"); 8437defineSymbol(math, ams, rel, "\u2a87", "\\lneq"); 8438defineSymbol(math, ams, rel, "\u2268", "\\lneqq"); 8439defineSymbol(math, ams, rel, "\ue00c", "\\lvertneqq"); 8440defineSymbol(math, ams, rel, "\u22e6", "\\lnsim"); 8441defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox"); 8442defineSymbol(math, ams, rel, "\u2280", "\\nprec"); 8443defineSymbol(math, ams, rel, "\u22e0", "\\npreceq"); 8444defineSymbol(math, ams, rel, "\u22e8", "\\precnsim"); 8445defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox"); 8446defineSymbol(math, ams, rel, "\u2241", "\\nsim"); 8447defineSymbol(math, ams, rel, "\ue006", "\\nshortmid"); 8448defineSymbol(math, ams, rel, "\u2224", "\\nmid"); 8449defineSymbol(math, ams, rel, "\u22ac", "\\nvdash"); 8450defineSymbol(math, ams, rel, "\u22ad", "\\nvDash"); 8451defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft"); 8452defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq"); 8453defineSymbol(math, ams, rel, "\u228a", "\\subsetneq"); 8454defineSymbol(math, ams, rel, "\ue01a", "\\varsubsetneq"); 8455defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq"); 8456defineSymbol(math, ams, rel, "\ue017", "\\varsubsetneqq"); 8457defineSymbol(math, ams, rel, "\u226f", "\\ngtr"); 8458defineSymbol(math, ams, rel, "\ue00f", "\\ngeqslant"); 8459defineSymbol(math, ams, rel, "\ue00e", "\\ngeqq"); 8460defineSymbol(math, ams, rel, "\u2a88", "\\gneq"); 8461defineSymbol(math, ams, rel, "\u2269", "\\gneqq"); 8462defineSymbol(math, ams, rel, "\ue00d", "\\gvertneqq"); 8463defineSymbol(math, ams, rel, "\u22e7", "\\gnsim"); 8464defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox"); 8465defineSymbol(math, ams, rel, "\u2281", "\\nsucc"); 8466defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq"); 8467defineSymbol(math, ams, rel, "\u22e9", "\\succnsim"); 8468defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox"); 8469defineSymbol(math, ams, rel, "\u2246", "\\ncong"); 8470defineSymbol(math, ams, rel, "\ue007", "\\nshortparallel"); 8471defineSymbol(math, ams, rel, "\u2226", "\\nparallel"); 8472defineSymbol(math, ams, rel, "\u22af", "\\nVDash"); 8473defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright"); 8474defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq"); 8475defineSymbol(math, ams, rel, "\ue018", "\\nsupseteqq"); 8476defineSymbol(math, ams, rel, "\u228b", "\\supsetneq"); 8477defineSymbol(math, ams, rel, "\ue01b", "\\varsupsetneq"); 8478defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq"); 8479defineSymbol(math, ams, rel, "\ue019", "\\varsupsetneqq"); 8480defineSymbol(math, ams, rel, "\u22ae", "\\nVdash"); 8481defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq"); 8482defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq"); 8483defineSymbol(math, ams, rel, "\ue016", "\\nsubseteqq"); 8484defineSymbol(math, ams, bin, "\u22b4", "\\unlhd"); 8485defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); 8486 8487// AMS Negated Arrows 8488defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow"); 8489defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow"); 8490defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow"); 8491defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow"); 8492defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow"); 8493defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow"); 8494 8495// AMS Misc 8496defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle"); 8497defineSymbol(math, ams, textord, "\u210f", "\\hslash"); 8498defineSymbol(math, ams, textord, "\u25bd", "\\triangledown"); 8499defineSymbol(math, ams, textord, "\u25ca", "\\lozenge"); 8500defineSymbol(math, ams, textord, "\u24c8", "\\circledS"); 8501defineSymbol(math, ams, textord, "\u00ae", "\\circledR"); 8502defineSymbol(math, ams, textord, "\u2221", "\\measuredangle"); 8503defineSymbol(math, ams, textord, "\u2204", "\\nexists"); 8504defineSymbol(math, ams, textord, "\u2127", "\\mho"); 8505defineSymbol(math, ams, textord, "\u2132", "\\Finv"); 8506defineSymbol(math, ams, textord, "\u2141", "\\Game"); 8507defineSymbol(math, ams, textord, "\u006b", "\\Bbbk"); 8508defineSymbol(math, ams, textord, "\u2035", "\\backprime"); 8509defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle"); 8510defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown"); 8511defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare"); 8512defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge"); 8513defineSymbol(math, ams, textord, "\u2605", "\\bigstar"); 8514defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle"); 8515defineSymbol(math, ams, textord, "\u2201", "\\complement"); 8516defineSymbol(math, ams, textord, "\u00f0", "\\eth"); 8517defineSymbol(math, ams, textord, "\u2571", "\\diagup"); 8518defineSymbol(math, ams, textord, "\u2572", "\\diagdown"); 8519defineSymbol(math, ams, textord, "\u25a1", "\\square"); 8520defineSymbol(math, ams, textord, "\u25a1", "\\Box"); 8521defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); 8522defineSymbol(math, ams, textord, "\u00a5", "\\yen"); 8523defineSymbol(math, ams, textord, "\u2713", "\\checkmark"); 8524 8525// AMS Hebrew 8526defineSymbol(math, ams, textord, "\u2136", "\\beth"); 8527defineSymbol(math, ams, textord, "\u2138", "\\daleth"); 8528defineSymbol(math, ams, textord, "\u2137", "\\gimel"); 8529 8530// AMS Greek 8531defineSymbol(math, ams, textord, "\u03dd", "\\digamma"); 8532defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); 8533 8534// AMS Delimiters 8535defineSymbol(math, ams, open, "\u250c", "\\ulcorner"); 8536defineSymbol(math, ams, close, "\u2510", "\\urcorner"); 8537defineSymbol(math, ams, open, "\u2514", "\\llcorner"); 8538defineSymbol(math, ams, close, "\u2518", "\\lrcorner"); 8539 8540// AMS Binary Relations 8541defineSymbol(math, ams, rel, "\u2266", "\\leqq"); 8542defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant"); 8543defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless"); 8544defineSymbol(math, ams, rel, "\u2272", "\\lesssim"); 8545defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox"); 8546defineSymbol(math, ams, rel, "\u224a", "\\approxeq"); 8547defineSymbol(math, ams, bin, "\u22d6", "\\lessdot"); 8548defineSymbol(math, ams, rel, "\u22d8", "\\lll"); 8549defineSymbol(math, ams, rel, "\u2276", "\\lessgtr"); 8550defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr"); 8551defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr"); 8552defineSymbol(math, ams, rel, "\u2251", "\\doteqdot"); 8553defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq"); 8554defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq"); 8555defineSymbol(math, ams, rel, "\u223d", "\\backsim"); 8556defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq"); 8557defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq"); 8558defineSymbol(math, ams, rel, "\u22d0", "\\Subset"); 8559defineSymbol(math, ams, rel, "\u228f", "\\sqsubset"); 8560defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq"); 8561defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec"); 8562defineSymbol(math, ams, rel, "\u227e", "\\precsim"); 8563defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox"); 8564defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft"); 8565defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq"); 8566defineSymbol(math, ams, rel, "\u22a8", "\\vDash"); 8567defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash"); 8568defineSymbol(math, ams, rel, "\u2323", "\\smallsmile"); 8569defineSymbol(math, ams, rel, "\u2322", "\\smallfrown"); 8570defineSymbol(math, ams, rel, "\u224f", "\\bumpeq"); 8571defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq"); 8572defineSymbol(math, ams, rel, "\u2267", "\\geqq"); 8573defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant"); 8574defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr"); 8575defineSymbol(math, ams, rel, "\u2273", "\\gtrsim"); 8576defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox"); 8577defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot"); 8578defineSymbol(math, ams, rel, "\u22d9", "\\ggg"); 8579defineSymbol(math, ams, rel, "\u2277", "\\gtrless"); 8580defineSymbol(math, ams, rel, "\u22db", "\\gtreqless"); 8581defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless"); 8582defineSymbol(math, ams, rel, "\u2256", "\\eqcirc"); 8583defineSymbol(math, ams, rel, "\u2257", "\\circeq"); 8584defineSymbol(math, ams, rel, "\u225c", "\\triangleq"); 8585defineSymbol(math, ams, rel, "\u223c", "\\thicksim"); 8586defineSymbol(math, ams, rel, "\u2248", "\\thickapprox"); 8587defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq"); 8588defineSymbol(math, ams, rel, "\u22d1", "\\Supset"); 8589defineSymbol(math, ams, rel, "\u2290", "\\sqsupset"); 8590defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq"); 8591defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc"); 8592defineSymbol(math, ams, rel, "\u227f", "\\succsim"); 8593defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox"); 8594defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright"); 8595defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq"); 8596defineSymbol(math, ams, rel, "\u22a9", "\\Vdash"); 8597defineSymbol(math, ams, rel, "\u2223", "\\shortmid"); 8598defineSymbol(math, ams, rel, "\u2225", "\\shortparallel"); 8599defineSymbol(math, ams, rel, "\u226c", "\\between"); 8600defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork"); 8601defineSymbol(math, ams, rel, "\u221d", "\\varpropto"); 8602defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); 8603defineSymbol(math, ams, rel, "\u2234", "\\therefore"); 8604defineSymbol(math, ams, rel, "\u220d", "\\backepsilon"); 8605defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); 8606defineSymbol(math, ams, rel, "\u2235", "\\because"); 8607defineSymbol(math, ams, rel, "\u22d8", "\\llless"); 8608defineSymbol(math, ams, rel, "\u22d9", "\\gggtr"); 8609defineSymbol(math, ams, bin, "\u22b2", "\\lhd"); 8610defineSymbol(math, ams, bin, "\u22b3", "\\rhd"); 8611defineSymbol(math, ams, rel, "\u2242", "\\eqsim"); 8612defineSymbol(math, main, rel, "\u22c8", "\\Join"); 8613defineSymbol(math, ams, rel, "\u2251", "\\Doteq"); 8614 8615// AMS Binary Operators 8616defineSymbol(math, ams, bin, "\u2214", "\\dotplus"); 8617defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus"); 8618defineSymbol(math, ams, bin, "\u22d2", "\\Cap"); 8619defineSymbol(math, ams, bin, "\u22d3", "\\Cup"); 8620defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge"); 8621defineSymbol(math, ams, bin, "\u229f", "\\boxminus"); 8622defineSymbol(math, ams, bin, "\u229e", "\\boxplus"); 8623defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes"); 8624defineSymbol(math, ams, bin, "\u22c9", "\\ltimes"); 8625defineSymbol(math, ams, bin, "\u22ca", "\\rtimes"); 8626defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes"); 8627defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes"); 8628defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge"); 8629defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee"); 8630defineSymbol(math, ams, bin, "\u229d", "\\circleddash"); 8631defineSymbol(math, ams, bin, "\u229b", "\\circledast"); 8632defineSymbol(math, ams, bin, "\u22c5", "\\centerdot"); 8633defineSymbol(math, ams, bin, "\u22ba", "\\intercal"); 8634defineSymbol(math, ams, bin, "\u22d2", "\\doublecap"); 8635defineSymbol(math, ams, bin, "\u22d3", "\\doublecup"); 8636defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes"); 8637 8638// AMS Arrows 8639defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow"); 8640defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow"); 8641defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows"); 8642defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows"); 8643defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow"); 8644defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow"); 8645defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail"); 8646defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft"); 8647defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons"); 8648defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft"); 8649defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft"); 8650defineSymbol(math, ams, rel, "\u21b0", "\\Lsh"); 8651defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows"); 8652defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft"); 8653defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft"); 8654defineSymbol(math, ams, rel, "\u22b8", "\\multimap"); 8655defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow"); 8656defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows"); 8657defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows"); 8658defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow"); 8659defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail"); 8660defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright"); 8661defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright"); 8662defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright"); 8663defineSymbol(math, ams, rel, "\u21b1", "\\Rsh"); 8664defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows"); 8665defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright"); 8666defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright"); 8667defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow"); 8668defineSymbol(math, ams, rel, "\u21dd", "\\leadsto"); 8669defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow"); 8670defineSymbol(math, ams, rel, "\u21be", "\\restriction"); 8671 8672defineSymbol(math, main, textord, "\u2018", "`"); 8673defineSymbol(math, main, textord, "$", "\\$"); 8674defineSymbol(text, main, textord, "$", "\\$"); 8675defineSymbol(math, main, textord, "%", "\\%"); 8676defineSymbol(text, main, textord, "%", "\\%"); 8677defineSymbol(math, main, textord, "_", "\\_"); 8678defineSymbol(text, main, textord, "_", "\\_"); 8679defineSymbol(math, main, textord, "\u2220", "\\angle"); 8680defineSymbol(math, main, textord, "\u221e", "\\infty"); 8681defineSymbol(math, main, textord, "\u2032", "\\prime"); 8682defineSymbol(math, main, textord, "\u25b3", "\\triangle"); 8683defineSymbol(math, main, textord, "\u0393", "\\Gamma"); 8684defineSymbol(math, main, textord, "\u0394", "\\Delta"); 8685defineSymbol(math, main, textord, "\u0398", "\\Theta"); 8686defineSymbol(math, main, textord, "\u039b", "\\Lambda"); 8687defineSymbol(math, main, textord, "\u039e", "\\Xi"); 8688defineSymbol(math, main, textord, "\u03a0", "\\Pi"); 8689defineSymbol(math, main, textord, "\u03a3", "\\Sigma"); 8690defineSymbol(math, main, textord, "\u03a5", "\\Upsilon"); 8691defineSymbol(math, main, textord, "\u03a6", "\\Phi"); 8692defineSymbol(math, main, textord, "\u03a8", "\\Psi"); 8693defineSymbol(math, main, textord, "\u03a9", "\\Omega"); 8694defineSymbol(math, main, textord, "\u00ac", "\\neg"); 8695defineSymbol(math, main, textord, "\u00ac", "\\lnot"); 8696defineSymbol(math, main, textord, "\u22a4", "\\top"); 8697defineSymbol(math, main, textord, "\u22a5", "\\bot"); 8698defineSymbol(math, main, textord, "\u2205", "\\emptyset"); 8699defineSymbol(math, ams, textord, "\u2205", "\\varnothing"); 8700defineSymbol(math, main, mathord, "\u03b1", "\\alpha"); 8701defineSymbol(math, main, mathord, "\u03b2", "\\beta"); 8702defineSymbol(math, main, mathord, "\u03b3", "\\gamma"); 8703defineSymbol(math, main, mathord, "\u03b4", "\\delta"); 8704defineSymbol(math, main, mathord, "\u03f5", "\\epsilon"); 8705defineSymbol(math, main, mathord, "\u03b6", "\\zeta"); 8706defineSymbol(math, main, mathord, "\u03b7", "\\eta"); 8707defineSymbol(math, main, mathord, "\u03b8", "\\theta"); 8708defineSymbol(math, main, mathord, "\u03b9", "\\iota"); 8709defineSymbol(math, main, mathord, "\u03ba", "\\kappa"); 8710defineSymbol(math, main, mathord, "\u03bb", "\\lambda"); 8711defineSymbol(math, main, mathord, "\u03bc", "\\mu"); 8712defineSymbol(math, main, mathord, "\u03bd", "\\nu"); 8713defineSymbol(math, main, mathord, "\u03be", "\\xi"); 8714defineSymbol(math, main, mathord, "o", "\\omicron"); 8715defineSymbol(math, main, mathord, "\u03c0", "\\pi"); 8716defineSymbol(math, main, mathord, "\u03c1", "\\rho"); 8717defineSymbol(math, main, mathord, "\u03c3", "\\sigma"); 8718defineSymbol(math, main, mathord, "\u03c4", "\\tau"); 8719defineSymbol(math, main, mathord, "\u03c5", "\\upsilon"); 8720defineSymbol(math, main, mathord, "\u03d5", "\\phi"); 8721defineSymbol(math, main, mathord, "\u03c7", "\\chi"); 8722defineSymbol(math, main, mathord, "\u03c8", "\\psi"); 8723defineSymbol(math, main, mathord, "\u03c9", "\\omega"); 8724defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon"); 8725defineSymbol(math, main, mathord, "\u03d1", "\\vartheta"); 8726defineSymbol(math, main, mathord, "\u03d6", "\\varpi"); 8727defineSymbol(math, main, mathord, "\u03f1", "\\varrho"); 8728defineSymbol(math, main, mathord, "\u03c2", "\\varsigma"); 8729defineSymbol(math, main, mathord, "\u03c6", "\\varphi"); 8730defineSymbol(math, main, bin, "\u2217", "*"); 8731defineSymbol(math, main, bin, "+", "+"); 8732defineSymbol(math, main, bin, "\u2212", "-"); 8733defineSymbol(math, main, bin, "\u22c5", "\\cdot"); 8734defineSymbol(math, main, bin, "\u2218", "\\circ"); 8735defineSymbol(math, main, bin, "\u00f7", "\\div"); 8736defineSymbol(math, main, bin, "\u00b1", "\\pm"); 8737defineSymbol(math, main, bin, "\u00d7", "\\times"); 8738defineSymbol(math, main, bin, "\u2229", "\\cap"); 8739defineSymbol(math, main, bin, "\u222a", "\\cup"); 8740defineSymbol(math, main, bin, "\u2216", "\\setminus"); 8741defineSymbol(math, main, bin, "\u2227", "\\land"); 8742defineSymbol(math, main, bin, "\u2228", "\\lor"); 8743defineSymbol(math, main, bin, "\u2227", "\\wedge"); 8744defineSymbol(math, main, bin, "\u2228", "\\vee"); 8745defineSymbol(math, main, textord, "\u221a", "\\surd"); 8746defineSymbol(math, main, open, "(", "("); 8747defineSymbol(math, main, open, "[", "["); 8748defineSymbol(math, main, open, "\u27e8", "\\langle"); 8749defineSymbol(math, main, open, "\u2223", "\\lvert"); 8750defineSymbol(math, main, open, "\u2225", "\\lVert"); 8751defineSymbol(math, main, close, ")", ")"); 8752defineSymbol(math, main, close, "]", "]"); 8753defineSymbol(math, main, close, "?", "?"); 8754defineSymbol(math, main, close, "!", "!"); 8755defineSymbol(math, main, close, "\u27e9", "\\rangle"); 8756defineSymbol(math, main, close, "\u2223", "\\rvert"); 8757defineSymbol(math, main, close, "\u2225", "\\rVert"); 8758defineSymbol(math, main, rel, "=", "="); 8759defineSymbol(math, main, rel, "<", "<"); 8760defineSymbol(math, main, rel, ">", ">"); 8761defineSymbol(math, main, rel, ":", ":"); 8762defineSymbol(math, main, rel, "\u2248", "\\approx"); 8763defineSymbol(math, main, rel, "\u2245", "\\cong"); 8764defineSymbol(math, main, rel, "\u2265", "\\ge"); 8765defineSymbol(math, main, rel, "\u2265", "\\geq"); 8766defineSymbol(math, main, rel, "\u2190", "\\gets"); 8767defineSymbol(math, main, rel, ">", "\\gt"); 8768defineSymbol(math, main, rel, "\u2208", "\\in"); 8769defineSymbol(math, main, rel, "\u2209", "\\notin"); 8770defineSymbol(math, main, rel, "\u2282", "\\subset"); 8771defineSymbol(math, main, rel, "\u2283", "\\supset"); 8772defineSymbol(math, main, rel, "\u2286", "\\subseteq"); 8773defineSymbol(math, main, rel, "\u2287", "\\supseteq"); 8774defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq"); 8775defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq"); 8776defineSymbol(math, main, rel, "\u22a8", "\\models"); 8777defineSymbol(math, main, rel, "\u2190", "\\leftarrow"); 8778defineSymbol(math, main, rel, "\u2264", "\\le"); 8779defineSymbol(math, main, rel, "\u2264", "\\leq"); 8780defineSymbol(math, main, rel, "<", "\\lt"); 8781defineSymbol(math, main, rel, "\u2260", "\\ne"); 8782defineSymbol(math, main, rel, "\u2260", "\\neq"); 8783defineSymbol(math, main, rel, "\u2192", "\\rightarrow"); 8784defineSymbol(math, main, rel, "\u2192", "\\to"); 8785defineSymbol(math, ams, rel, "\u2271", "\\ngeq"); 8786defineSymbol(math, ams, rel, "\u2270", "\\nleq"); 8787defineSymbol(math, main, spacing, null, "\\!"); 8788defineSymbol(math, main, spacing, "\u00a0", "\\ "); 8789defineSymbol(math, main, spacing, "\u00a0", "~"); 8790defineSymbol(math, main, spacing, null, "\\,"); 8791defineSymbol(math, main, spacing, null, "\\:"); 8792defineSymbol(math, main, spacing, null, "\\;"); 8793defineSymbol(math, main, spacing, null, "\\enspace"); 8794defineSymbol(math, main, spacing, null, "\\qquad"); 8795defineSymbol(math, main, spacing, null, "\\quad"); 8796defineSymbol(math, main, spacing, "\u00a0", "\\space"); 8797defineSymbol(math, main, punct, ",", ","); 8798defineSymbol(math, main, punct, ";", ";"); 8799defineSymbol(math, main, punct, ":", "\\colon"); 8800defineSymbol(math, ams, bin, "\u22bc", "\\barwedge"); 8801defineSymbol(math, ams, bin, "\u22bb", "\\veebar"); 8802defineSymbol(math, main, bin, "\u2299", "\\odot"); 8803defineSymbol(math, main, bin, "\u2295", "\\oplus"); 8804defineSymbol(math, main, bin, "\u2297", "\\otimes"); 8805defineSymbol(math, main, textord, "\u2202", "\\partial"); 8806defineSymbol(math, main, bin, "\u2298", "\\oslash"); 8807defineSymbol(math, ams, bin, "\u229a", "\\circledcirc"); 8808defineSymbol(math, ams, bin, "\u22a1", "\\boxdot"); 8809defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup"); 8810defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown"); 8811defineSymbol(math, main, bin, "\u2020", "\\dagger"); 8812defineSymbol(math, main, bin, "\u22c4", "\\diamond"); 8813defineSymbol(math, main, bin, "\u22c6", "\\star"); 8814defineSymbol(math, main, bin, "\u25c3", "\\triangleleft"); 8815defineSymbol(math, main, bin, "\u25b9", "\\triangleright"); 8816defineSymbol(math, main, open, "{", "\\{"); 8817defineSymbol(text, main, textord, "{", "\\{"); 8818defineSymbol(math, main, close, "}", "\\}"); 8819defineSymbol(text, main, textord, "}", "\\}"); 8820defineSymbol(math, main, open, "{", "\\lbrace"); 8821defineSymbol(math, main, close, "}", "\\rbrace"); 8822defineSymbol(math, main, open, "[", "\\lbrack"); 8823defineSymbol(math, main, close, "]", "\\rbrack"); 8824defineSymbol(math, main, open, "\u230a", "\\lfloor"); 8825defineSymbol(math, main, close, "\u230b", "\\rfloor"); 8826defineSymbol(math, main, open, "\u2308", "\\lceil"); 8827defineSymbol(math, main, close, "\u2309", "\\rceil"); 8828defineSymbol(math, main, textord, "\\", "\\backslash"); 8829defineSymbol(math, main, textord, "\u2223", "|"); 8830defineSymbol(math, main, textord, "\u2223", "\\vert"); 8831defineSymbol(math, main, textord, "\u2225", "\\|"); 8832defineSymbol(math, main, textord, "\u2225", "\\Vert"); 8833defineSymbol(math, main, rel, "\u2191", "\\uparrow"); 8834defineSymbol(math, main, rel, "\u21d1", "\\Uparrow"); 8835defineSymbol(math, main, rel, "\u2193", "\\downarrow"); 8836defineSymbol(math, main, rel, "\u21d3", "\\Downarrow"); 8837defineSymbol(math, main, rel, "\u2195", "\\updownarrow"); 8838defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow"); 8839defineSymbol(math, math, op, "\u2210", "\\coprod"); 8840defineSymbol(math, math, op, "\u22c1", "\\bigvee"); 8841defineSymbol(math, math, op, "\u22c0", "\\bigwedge"); 8842defineSymbol(math, math, op, "\u2a04", "\\biguplus"); 8843defineSymbol(math, math, op, "\u22c2", "\\bigcap"); 8844defineSymbol(math, math, op, "\u22c3", "\\bigcup"); 8845defineSymbol(math, math, op, "\u222b", "\\int"); 8846defineSymbol(math, math, op, "\u222b", "\\intop"); 8847defineSymbol(math, math, op, "\u222c", "\\iint"); 8848defineSymbol(math, math, op, "\u222d", "\\iiint"); 8849defineSymbol(math, math, op, "\u220f", "\\prod"); 8850defineSymbol(math, math, op, "\u2211", "\\sum"); 8851defineSymbol(math, math, op, "\u2a02", "\\bigotimes"); 8852defineSymbol(math, math, op, "\u2a01", "\\bigoplus"); 8853defineSymbol(math, math, op, "\u2a00", "\\bigodot"); 8854defineSymbol(math, math, op, "\u222e", "\\oint"); 8855defineSymbol(math, math, op, "\u2a06", "\\bigsqcup"); 8856defineSymbol(math, math, op, "\u222b", "\\smallint"); 8857defineSymbol(text, main, inner, "\u2026", "\\textellipsis"); 8858defineSymbol(math, main, inner, "\u2026", "\\mathellipsis"); 8859defineSymbol(text, main, inner, "\u2026", "\\ldots"); 8860defineSymbol(math, main, inner, "\u2026", "\\ldots"); 8861defineSymbol(math, main, inner, "\u22ef", "\\cdots"); 8862defineSymbol(math, main, inner, "\u22f1", "\\ddots"); 8863defineSymbol(math, main, textord, "\u22ee", "\\vdots"); 8864defineSymbol(math, main, accent, "\u00b4", "\\acute"); 8865defineSymbol(math, main, accent, "\u0060", "\\grave"); 8866defineSymbol(math, main, accent, "\u00a8", "\\ddot"); 8867defineSymbol(math, main, accent, "\u007e", "\\tilde"); 8868defineSymbol(math, main, accent, "\u00af", "\\bar"); 8869defineSymbol(math, main, accent, "\u02d8", "\\breve"); 8870defineSymbol(math, main, accent, "\u02c7", "\\check"); 8871defineSymbol(math, main, accent, "\u005e", "\\hat"); 8872defineSymbol(math, main, accent, "\u20d7", "\\vec"); 8873defineSymbol(math, main, accent, "\u02d9", "\\dot"); 8874defineSymbol(math, main, mathord, "\u0131", "\\imath"); 8875defineSymbol(math, main, mathord, "\u0237", "\\jmath"); 8876 8877defineSymbol(text, main, textord, "\u2013", "--"); 8878defineSymbol(text, main, textord, "\u2014", "---"); 8879defineSymbol(text, main, textord, "\u2018", "`"); 8880defineSymbol(text, main, textord, "\u2019", "'"); 8881defineSymbol(text, main, textord, "\u201c", "``"); 8882defineSymbol(text, main, textord, "\u201d", "''"); 8883defineSymbol(math, main, textord, "\u00b0", "\\degree"); 8884defineSymbol(text, main, textord, "\u00b0", "\\degree"); 8885defineSymbol(math, main, mathord, "\u00a3", "\\pounds"); 8886defineSymbol(math, ams, textord, "\u2720", "\\maltese"); 8887defineSymbol(text, ams, textord, "\u2720", "\\maltese"); 8888 8889defineSymbol(text, main, spacing, "\u00a0", "\\ "); 8890defineSymbol(text, main, spacing, "\u00a0", " "); 8891defineSymbol(text, main, spacing, "\u00a0", "~"); 8892 8893// There are lots of symbols which are the same, so we add them in afterwards. 8894var i; 8895var ch; 8896 8897// All of these are textords in math mode 8898var mathTextSymbols = "0123456789/@.\""; 8899for (i = 0; i < mathTextSymbols.length; i++) { 8900 ch = mathTextSymbols.charAt(i); 8901 defineSymbol(math, main, textord, ch, ch); 8902} 8903 8904// All of these are textords in text mode 8905var textSymbols = "0123456789!@*()-=+[]\";:?/.,"; 8906for (i = 0; i < textSymbols.length; i++) { 8907 ch = textSymbols.charAt(i); 8908 defineSymbol(text, main, textord, ch, ch); 8909} 8910 8911// All of these are textords in text mode, and mathords in math mode 8912var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 8913for (i = 0; i < letters.length; i++) { 8914 ch = letters.charAt(i); 8915 defineSymbol(math, main, mathord, ch, ch); 8916 defineSymbol(text, main, textord, ch, ch); 8917} 8918 8919// Latin-1 letters 8920for (i = 0x00C0; i <= 0x00D6; i++) { 8921 ch = String.fromCharCode(i); 8922 defineSymbol(text, main, textord, ch, ch); 8923} 8924 8925for (i = 0x00D8; i <= 0x00F6; i++) { 8926 ch = String.fromCharCode(i); 8927 defineSymbol(text, main, textord, ch, ch); 8928} 8929 8930for (i = 0x00F8; i <= 0x00FF; i++) { 8931 ch = String.fromCharCode(i); 8932 defineSymbol(text, main, textord, ch, ch); 8933} 8934 8935// Cyrillic 8936for (i = 0x0410; i <= 0x044F; i++) { 8937 ch = String.fromCharCode(i); 8938 defineSymbol(text, main, textord, ch, ch); 8939} 8940 8941// Unicode versions of existing characters 8942defineSymbol(text, main, textord, "\u2013", "–"); 8943defineSymbol(text, main, textord, "\u2014", "—"); 8944defineSymbol(text, main, textord, "\u2018", "‘"); 8945defineSymbol(text, main, textord, "\u2019", "’"); 8946defineSymbol(text, main, textord, "\u201c", "“"); 8947defineSymbol(text, main, textord, "\u201d", "”"); 8948 8949},{}],24:[function(require,module,exports){ 8950var hangulRegex = /[\uAC00-\uD7AF]/; 8951 8952// This regex combines 8953// - Hiragana: [\u3040-\u309F] 8954// - Katakana: [\u30A0-\u30FF] 8955// - CJK ideograms: [\u4E00-\u9FAF] 8956// - Hangul syllables: [\uAC00-\uD7AF] 8957// Notably missing are halfwidth Katakana and Romanji glyphs. 8958var cjkRegex = 8959 /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/; 8960 8961module.exports = { 8962 cjkRegex: cjkRegex, 8963 hangulRegex: hangulRegex 8964}; 8965 8966},{}],25:[function(require,module,exports){ 8967/** 8968 * This file contains a list of utility functions which are useful in other 8969 * files. 8970 */ 8971 8972/** 8973 * Provide an `indexOf` function which works in IE8, but defers to native if 8974 * possible. 8975 */ 8976var nativeIndexOf = Array.prototype.indexOf; 8977var indexOf = function(list, elem) { 8978 if (list == null) { 8979 return -1; 8980 } 8981 if (nativeIndexOf && list.indexOf === nativeIndexOf) { 8982 return list.indexOf(elem); 8983 } 8984 var i = 0; 8985 var l = list.length; 8986 for (; i < l; i++) { 8987 if (list[i] === elem) { 8988 return i; 8989 } 8990 } 8991 return -1; 8992}; 8993 8994/** 8995 * Return whether an element is contained in a list 8996 */ 8997var contains = function(list, elem) { 8998 return indexOf(list, elem) !== -1; 8999}; 9000 9001/** 9002 * Provide a default value if a setting is undefined 9003 */ 9004var deflt = function(setting, defaultIfUndefined) { 9005 return setting === undefined ? defaultIfUndefined : setting; 9006}; 9007 9008// hyphenate and escape adapted from Facebook's React under Apache 2 license 9009 9010var uppercase = /([A-Z])/g; 9011var hyphenate = function(str) { 9012 return str.replace(uppercase, "-$1").toLowerCase(); 9013}; 9014 9015var ESCAPE_LOOKUP = { 9016 "&": "&", 9017 ">": ">", 9018 "<": "<", 9019 "\"": """, 9020 "'": "'" 9021}; 9022 9023var ESCAPE_REGEX = /[&><"']/g; 9024 9025function escaper(match) { 9026 return ESCAPE_LOOKUP[match]; 9027} 9028 9029/** 9030 * Escapes text to prevent scripting attacks. 9031 * 9032 * @param {*} text Text value to escape. 9033 * @return {string} An escaped string. 9034 */ 9035function escape(text) { 9036 return ("" + text).replace(ESCAPE_REGEX, escaper); 9037} 9038 9039/** 9040 * A function to set the text content of a DOM element in all supported 9041 * browsers. Note that we don't define this if there is no document. 9042 */ 9043var setTextContent; 9044if (typeof document !== "undefined") { 9045 var testNode = document.createElement("span"); 9046 if ("textContent" in testNode) { 9047 setTextContent = function(node, text) { 9048 node.textContent = text; 9049 }; 9050 } else { 9051 setTextContent = function(node, text) { 9052 node.innerText = text; 9053 }; 9054 } 9055} 9056 9057/** 9058 * A function to clear a node. 9059 */ 9060function clearNode(node) { 9061 setTextContent(node, ""); 9062} 9063 9064module.exports = { 9065 contains: contains, 9066 deflt: deflt, 9067 escape: escape, 9068 hyphenate: hyphenate, 9069 indexOf: indexOf, 9070 setTextContent: setTextContent, 9071 clearNode: clearNode 9072}; 9073 9074},{}]},{},[1])(1) 9075});