UNPKG

katex

Version:

Fast math typesetting for the web.

1,338 lines (1,167 loc) 565 kB
/** * Lexing or parsing positional information for error reporting. * This object is immutable. */ class SourceLocation { // The + prefix indicates that these fields aren't writeable // Lexer holding the input string. // Start offset, zero-based inclusive. // End offset, zero-based exclusive. constructor(lexer, start, end) { this.lexer = void 0; this.start = void 0; this.end = void 0; this.lexer = lexer; this.start = start; this.end = end; } /** * Merges two `SourceLocation`s from location providers, given they are * provided in order of appearance. * - Returns the first one's location if only the first is provided. * - Returns a merged range of the first and the last if both are provided * and their lexers match. * - Otherwise, returns null. */ static range(first, second) { if (!second) { return first && first.loc; } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { return null; } else { return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); } } } /** * Interface required to break circular dependency between Token, Lexer, and * ParseError. */ /** * The resulting token returned from `lex`. * * It consists of the token text plus some position information. * The position information is essentially a range in an input string, * but instead of referencing the bare input string, we refer to the lexer. * That way it is possible to attach extra metadata to the input string, * like for example a file name or similar. * * The position information is optional, so it is OK to construct synthetic * tokens if appropriate. Not providing available position information may * lead to degraded error reporting, though. */ class Token { constructor(text, // the text of this token loc) { this.text = void 0; this.loc = void 0; this.text = text; this.loc = loc; } /** * Given a pair of tokens (this and endToken), compute a `Token` encompassing * the whole input range enclosed by these two. */ range(endToken, // last token of the range, inclusive text) // the text of the newly constructed token { return new Token(text, SourceLocation.range(this, endToken)); } } /** * This is the ParseError class, which is the main error thrown by KaTeX * functions when something has gone wrong. This is used to distinguish internal * errors from errors in the expression that the user provided. * * If possible, a caller should provide a Token or ParseNode with information * about where in the source string the problem occurred. */ class ParseError { // Error position based on passed-in Token or ParseNode. constructor(message, // The error message token) // An object providing position information { this.position = void 0; let error = "KaTeX parse error: " + message; let start; const loc = token && token.loc; if (loc && loc.start <= loc.end) { // If we have the input and a position, make the error a bit fancier // Get the input const input = loc.lexer.input; // Prepend some information start = loc.start; const end = loc.end; if (start === input.length) { error += " at end of input: "; } else { error += " at position " + (start + 1) + ": "; } // Underline token in question using combining underscores const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error let left; if (start > 15) { left = "…" + input.slice(start - 15, start); } else { left = input.slice(0, start); } let right; if (end + 15 < input.length) { right = input.slice(end, end + 15) + "…"; } else { right = input.slice(end); } error += left + underlined + right; } // Some hackery to make ParseError a prototype of Error // See http://stackoverflow.com/a/8460753 const self = new Error(error); self.name = "ParseError"; // $FlowFixMe self.__proto__ = ParseError.prototype; // $FlowFixMe self.position = start; return self; } } // $FlowFixMe More hackery ParseError.prototype.__proto__ = Error.prototype; /** * This file contains a list of utility functions which are useful in other * files. */ /** * Return whether an element is contained in a list */ const contains = function contains(list, elem) { return list.indexOf(elem) !== -1; }; /** * Provide a default value if a setting is undefined * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022. */ const deflt = function deflt(setting, defaultIfUndefined) { return setting === undefined ? defaultIfUndefined : setting; }; // hyphenate and escape adapted from Facebook's React under Apache 2 license const uppercase = /([A-Z])/g; const hyphenate = function hyphenate(str) { return str.replace(uppercase, "-$1").toLowerCase(); }; const ESCAPE_LOOKUP = { "&": "&amp;", ">": "&gt;", "<": "&lt;", "\"": "&quot;", "'": "&#x27;" }; const ESCAPE_REGEX = /[&><"']/g; /** * Escapes text to prevent scripting attacks. */ function escape(text) { return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]); } /** * Sometimes we want to pull out the innermost element of a group. In most * cases, this will just be the group itself, but when ordgroups and colors have * a single element, we want to pull that out. */ const getBaseElem = function getBaseElem(group) { if (group.type === "ordgroup") { if (group.body.length === 1) { return getBaseElem(group.body[0]); } else { return group; } } else if (group.type === "color") { if (group.body.length === 1) { return getBaseElem(group.body[0]); } else { return group; } } else if (group.type === "font") { return getBaseElem(group.body); } else { return group; } }; /** * TeXbook algorithms often reference "character boxes", which are simply groups * with a single character in them. To decide if something is a character box, * we find its innermost group, and see if it is a single character. */ const isCharacterBox = function isCharacterBox(group) { const baseElem = getBaseElem(group); // These are all they types of groups which hold single characters return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom"; }; const assert = function assert(value) { if (!value) { throw new Error('Expected non-null, but got ' + String(value)); } return value; }; /** * Return the protocol of a URL, or "_relative" if the URL does not specify a * protocol (and thus is relative). */ const protocolFromUrl = function protocolFromUrl(url) { const protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url); return protocol != null ? protocol[1] : "_relative"; }; var utils = { contains, deflt, escape, hyphenate, getBaseElem, isCharacterBox, protocolFromUrl }; /* eslint no-console:0 */ /** * The main Settings object * * The current options stored are: * - displayMode: Whether the expression should be typeset as inline math * (false, the default), meaning that the math starts in * \textstyle and is placed in an inline-block); or as display * math (true), meaning that the math starts in \displaystyle * and is placed in a block with vertical margin. */ class Settings { constructor(options) { this.displayMode = void 0; this.output = void 0; this.leqno = void 0; this.fleqn = void 0; this.throwOnError = void 0; this.errorColor = void 0; this.macros = void 0; this.minRuleThickness = void 0; this.colorIsTextColor = void 0; this.strict = void 0; this.trust = void 0; this.maxSize = void 0; this.maxExpand = void 0; // allow null options options = options || {}; this.displayMode = utils.deflt(options.displayMode, false); this.output = utils.deflt(options.output, "htmlAndMathml"); this.leqno = utils.deflt(options.leqno, false); this.fleqn = utils.deflt(options.fleqn, false); this.throwOnError = utils.deflt(options.throwOnError, true); this.errorColor = utils.deflt(options.errorColor, "#cc0000"); this.macros = options.macros || {}; this.minRuleThickness = Math.max(0, utils.deflt(options.minRuleThickness, 0)); this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); this.strict = utils.deflt(options.strict, "warn"); this.trust = utils.deflt(options.trust, false); this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity)); this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); } /** * Report nonstrict (non-LaTeX-compatible) input. * Can safely not be called if `this.strict` is false in JavaScript. */ reportNonstrict(errorCode, errorMsg, token) { let strict = this.strict; if (typeof strict === "function") { // Allow return value of strict function to be boolean or string // (or null/undefined, meaning no further processing). strict = strict(errorCode, errorMsg, token); } if (!strict || strict === "ignore") { return; } else if (strict === true || strict === "error") { throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + `${errorMsg} [${errorCode}]`, token); } else if (strict === "warn") { typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + `${errorMsg} [${errorCode}]`); } else { // won't happen in type-safe code typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + `unrecognized '${strict}': ${errorMsg} [${errorCode}]`); } } /** * Check whether to apply strict (LaTeX-adhering) behavior for unusual * input (like `\\`). Unlike `nonstrict`, will not throw an error; * instead, "error" translates to a return value of `true`, while "ignore" * translates to a return value of `false`. May still print a warning: * "warn" prints a warning and returns `false`. * This is for the second category of `errorCode`s listed in the README. */ useStrictBehavior(errorCode, errorMsg, token) { let strict = this.strict; if (typeof strict === "function") { // Allow return value of strict function to be boolean or string // (or null/undefined, meaning no further processing). // But catch any exceptions thrown by function, treating them // like "error". try { strict = strict(errorCode, errorMsg, token); } catch (error) { strict = "error"; } } if (!strict || strict === "ignore") { return false; } else if (strict === true || strict === "error") { return true; } else if (strict === "warn") { typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + `${errorMsg} [${errorCode}]`); return false; } else { // won't happen in type-safe code typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + `unrecognized '${strict}': ${errorMsg} [${errorCode}]`); return false; } } /** * Check whether to test potentially dangerous input, and return * `true` (trusted) or `false` (untrusted). The sole argument `context` * should be an object with `command` field specifying the relevant LaTeX * command (as a string starting with `\`), and any other arguments, etc. * If `context` has a `url` field, a `protocol` field will automatically * get added by this function (changing the specified object). */ isTrusted(context) { if (context.url && !context.protocol) { context.protocol = utils.protocolFromUrl(context.url); } const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; return Boolean(trust); } } /** * This file contains information and classes for the various kinds of styles * used in TeX. It provides a generic `Style` class, which holds information * about a specific style. It then provides instances of all the different kinds * of styles possible, and provides functions to move between them and get * information about them. */ /** * The main style class. Contains a unique id for the style, a size (which is * the same for cramped and uncramped version of a style), and a cramped flag. */ class Style { constructor(id, size, cramped) { this.id = void 0; this.size = void 0; this.cramped = void 0; this.id = id; this.size = size; this.cramped = cramped; } /** * Get the style of a superscript given a base in the current style. */ sup() { return styles[sup[this.id]]; } /** * Get the style of a subscript given a base in the current style. */ sub() { return styles[sub[this.id]]; } /** * Get the style of a fraction numerator given the fraction in the current * style. */ fracNum() { return styles[fracNum[this.id]]; } /** * Get the style of a fraction denominator given the fraction in the current * style. */ fracDen() { return styles[fracDen[this.id]]; } /** * Get the cramped version of a style (in particular, cramping a cramped style * doesn't change the style). */ cramp() { return styles[cramp[this.id]]; } /** * Get a text or display version of this style. */ text() { return styles[text[this.id]]; } /** * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle) */ isTight() { return this.size >= 2; } } // Export an interface for type checking, but don't expose the implementation. // This way, no more styles can be generated. // IDs of the different styles const D = 0; const Dc = 1; const T = 2; const Tc = 3; const S = 4; const Sc = 5; const SS = 6; const SSc = 7; // Instances of the different styles const styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)]; // Lookup tables for switching from one style to another const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc]; const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc]; const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc]; const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc]; const cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc]; const text = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles. var Style$1 = { DISPLAY: styles[D], TEXT: styles[T], SCRIPT: styles[S], SCRIPTSCRIPT: styles[SS] }; /* * This file defines the Unicode scripts and script families that we * support. To add new scripts or families, just add a new entry to the * scriptData array below. Adding scripts to the scriptData array allows * characters from that script to appear in \text{} environments. */ /** * Each script or script family has a name and an array of blocks. * Each block is an array of two numbers which specify the start and * end points (inclusive) of a block of Unicode codepoints. */ /** * Unicode block data for the families of scripts we support in \text{}. * Scripts only need to appear here if they do not have font metrics. */ const scriptData = [{ // Latin characters beyond the Latin-1 characters we have metrics for. // Needed for Czech, Hungarian and Turkish text, for example. name: 'latin', blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B [0x0300, 0x036f]] }, { // The Cyrillic script used by Russian and related languages. // A Cyrillic subset used to be supported as explicitly defined // symbols in symbols.js name: 'cyrillic', blocks: [[0x0400, 0x04ff]] }, { // The Brahmic scripts of South and Southeast Asia // Devanagari (0900–097F) // Bengali (0980–09FF) // Gurmukhi (0A00–0A7F) // Gujarati (0A80–0AFF) // Oriya (0B00–0B7F) // Tamil (0B80–0BFF) // Telugu (0C00–0C7F) // Kannada (0C80–0CFF) // Malayalam (0D00–0D7F) // Sinhala (0D80–0DFF) // Thai (0E00–0E7F) // Lao (0E80–0EFF) // Tibetan (0F00–0FFF) // Myanmar (1000–109F) name: 'brahmic', blocks: [[0x0900, 0x109F]] }, { name: 'georgian', blocks: [[0x10A0, 0x10ff]] }, { // Chinese and Japanese. // The "k" in cjk is for Korean, but we've separated Korean out name: "cjk", blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana [0x4E00, 0x9FAF], // CJK ideograms [0xFF00, 0xFF60]] }, { // Korean name: 'hangul', blocks: [[0xAC00, 0xD7AF]] }]; /** * Given a codepoint, return the name of the script or script family * it is from, or null if it is not part of a known block */ function scriptFromCodepoint(codepoint) { for (let i = 0; i < scriptData.length; i++) { const script = scriptData[i]; for (let i = 0; i < script.blocks.length; i++) { const block = script.blocks[i]; if (codepoint >= block[0] && codepoint <= block[1]) { return script.name; } } } return null; } /** * A flattened version of all the supported blocks in a single array. * This is an optimization to make supportedCodepoint() fast. */ const allBlocks = []; scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b))); /** * Given a codepoint, return true if it falls within one of the * scripts or script families defined above and false otherwise. * * Micro benchmarks shows that this is faster than * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() * in Firefox, Chrome and Node. */ function supportedCodepoint(codepoint) { for (let i = 0; i < allBlocks.length; i += 2) { if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { return true; } } return false; } /** * This file provides support to domTree.js and delimiter.js. * It's a storehouse of path geometry for SVG images. */ // In all paths below, the viewBox-to-em scale is 1000:1. const hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping. // The viniculum of a \sqrt can be made thicker by a KaTeX rendering option. // Think of variable extraViniculum as two detours in the SVG path. // The detour begins at the lower left of the area labeled extraViniculum below. // The detour proceeds one extraViniculum distance up and slightly to the right, // displacing the radiused corner between surd and viniculum. The radius is // traversed as usual, then the detour resumes. It goes right, to the end of // the very long viniculumn, then down one extraViniculum distance, // after which it resumes regular path geometry for the radical. /* viniculum / /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum / █████████████████████←0.04em (40 unit) std viniculum thickness / / / / / /\ / / surd */ const sqrtMain = function sqrtMain(extraViniculum, hLinePad) { // sqrtMain path geometry is from glyph U221A in the font KaTeX Main return `M95,${622 + extraViniculum + hLinePad} c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429 c69,-144,104.5,-217.7,106.5,-221 l${extraViniculum / 2.075} -${extraViniculum} c5.3,-9.3,12,-14,20,-14 H400000v${40 + extraViniculum}H845.2724 s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7 c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z M${834 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`; }; const sqrtSize1 = function sqrtSize1(extraViniculum, hLinePad) { // size1 is from glyph U221A in the font KaTeX_Size1-Regular return `M263,${601 + extraViniculum + hLinePad}c0.7,0,18,39.7,52,119 c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 c340,-704.7,510.7,-1060.3,512,-1067 l${extraViniculum / 2.084} -${extraViniculum} c4.7,-7.3,11,-11,19,-11 H40000v${40 + extraViniculum}H1012.3 s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232 c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1 s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26 c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z M${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`; }; const sqrtSize2 = function sqrtSize2(extraViniculum, hLinePad) { // size2 is from glyph U221A in the font KaTeX_Size2-Regular return `M983 ${10 + extraViniculum + hLinePad} l${extraViniculum / 3.13} -${extraViniculum} c4,-6.7,10,-10,18,-10 H400000v${40 + extraViniculum} H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744 c-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30 c26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722 c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5 c53.7,-170.3,84.5,-266.8,92.5,-289.5z M${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`; }; const sqrtSize3 = function sqrtSize3(extraViniculum, hLinePad) { // size3 is from glyph U221A in the font KaTeX_Size3-Regular return `M424,${2398 + extraViniculum + hLinePad} c-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514 c0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20 s-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121 s209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081 l${extraViniculum / 4.223} -${extraViniculum}c4,-6.7,10,-10,18,-10 H400000 v${40 + extraViniculum}H1014.6 s-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185 c-2,6,-10,9,-24,9 c-8,0,-12,-0.7,-12,-2z M${1001 + extraViniculum} ${hLinePad} h400000v${40 + extraViniculum}h-400000z`; }; const sqrtSize4 = function sqrtSize4(extraViniculum, hLinePad) { // size4 is from glyph U221A in the font KaTeX_Size4-Regular return `M473,${2713 + extraViniculum + hLinePad} c339.3,-1799.3,509.3,-2700,510,-2702 l${extraViniculum / 5.298} -${extraViniculum} c3.3,-7.3,9.3,-11,18,-11 H400000v${40 + extraViniculum}H1017.7 s-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9 c-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200 c0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26 s76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104, 606zM${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}H1017.7z`; }; const sqrtTall = function sqrtTall(extraViniculum, hLinePad, viewBoxHeight) { // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular // One path edge has a variable length. It runs vertically from the viniculumn // to a point near (14 units) the bottom of the surd. The viniculum // is normally 40 units thick. So the length of the line in question is: const vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum; return `M702 ${extraViniculum + hLinePad}H400000${40 + extraViniculum} H742v${vertSegment}l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1 h-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170 c-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667 219 661 l218 661zM702 ${hLinePad}H400000v${40 + extraViniculum}H742z`; }; const sqrtPath = function sqrtPath(size, extraViniculum, viewBoxHeight) { extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox. let path = ""; switch (size) { case "sqrtMain": path = sqrtMain(extraViniculum, hLinePad); break; case "sqrtSize1": path = sqrtSize1(extraViniculum, hLinePad); break; case "sqrtSize2": path = sqrtSize2(extraViniculum, hLinePad); break; case "sqrtSize3": path = sqrtSize3(extraViniculum, hLinePad); break; case "sqrtSize4": path = sqrtSize4(extraViniculum, hLinePad); break; case "sqrtTall": path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight); } return path; }; const path = { // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main doubleleftarrow: `M262 157 l10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5 c2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87 -86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7 -2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z m8 0v40h399730v-40zm0 194v40h399730v-40z`, // doublerightarrow is from glyph U+21D2 in font KaTeX Main doublerightarrow: `M399738 392l -10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88 -33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68 -17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18 -13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782 c-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3 -107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z`, // leftarrow is from glyph U+2190 in font KaTeX Main leftarrow: `M400000 241H110l3-3c68.7-52.7 113.7-120 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8 -5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247 c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202 l-3-3h399890zM100 241v40h399900v-40z`, // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular leftbrace: `M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117 -45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7 5-6 9-10 13-.7 1-7.3 1-20 1H6z`, leftbraceunder: `M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7 -331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z`, // overgroup is from the MnSymbol package (public domain) leftgroup: `M400000 80 H435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0 435 0h399565z`, leftgroupunder: `M400000 262 H435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219 435 219h399565z`, // Harpoons are from glyph U+21BD in font KaTeX Main leftharpoon: `M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3 -3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5 -18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7 -196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z`, leftharpoonplus: `M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3 -4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7 -10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z m0 0v40h400000v-40z`, leftharpoondown: `M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667 -152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z`, leftharpoondownplus: `M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7 -2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0 v40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z`, // hook is from glyph U+21A9 in font KaTeX Main lefthook: `M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5 -83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3 -68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21 71.5 23h399859zM103 281v-40h399897v40z`, leftlinesegment: `M40 281 V428 H0 V94 H40 V241 H400000 v40z M40 281 V428 H0 V94 H40 V241 H400000 v40z`, leftmapsto: `M40 281 V448H0V74H40V241H400000v40z M40 281 V448H0V74H40V241H400000v40z`, // tofrom is from glyph U+21C4 in font KaTeX AMS Regular leftToFrom: `M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23 -.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8 c28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z`, longequal: `M0 50 h400000 v40H0z m0 194h40000v40H0z M0 50 h400000 v40H0z m0 194h40000v40H0z`, midbrace: `M200428 334 c-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14 -53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z`, midbraceunder: `M199572 214 c100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0 -5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z`, oiintSize1: `M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6 -320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z m368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8 60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z`, oiintSize2: `M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8 -451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z m502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2 c0 110 84 276 504 276s502.4-166 502.4-276z`, oiiintSize1: `M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6 -480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z m525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0 85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z`, oiiintSize2: `M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8 -707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z m770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1 c0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z`, rightarrow: `M0 241v40h399891c-47.3 35.3-84 78-110 128 -16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85 -40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5 -12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67 151.7 139 205zm0 0v40h399900v-40z`, rightbrace: `M400000 542l -6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5 s-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1 c124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z`, rightbraceunder: `M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237 -174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z`, rightgroup: `M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0 3-1 3-3v-38c-76-158-257-219-435-219H0z`, rightgroupunder: `M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z`, rightharpoon: `M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3 -3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2 -10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5zm0 0v40h399900v-40z`, rightharpoonplus: `M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11 -18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z m0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z`, rightharpoondown: `M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5 -7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95 -27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z`, rightharpoondownplus: `M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3 -64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z m0-194v40h400000v-40zm0 0v40h400000v-40z`, righthook: `M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0 -13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z`, rightlinesegment: `M399960 241 V94 h40 V428 h-40 V281 H0 v-40z M399960 241 V94 h40 V428 h-40 V281 H0 v-40z`, rightToFrom: `M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32 -52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142 -167z M100 147v40h399900v-40zM0 341v40h399900v-40z`, // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular twoheadleftarrow: `M0 167c68 40 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69 -70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3 -40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19 -37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z`, twoheadrightarrow: `M400000 167 c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333 -19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z`, // tilde1 is a modified version of a glyph from the MnSymbol package tilde1: `M200 55.538c-77 0-168 73.953-177 73.953-3 0-7 -2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128 -68.267.847-113-73.952-191-73.952z`, // ditto tilde2, tilde3, & tilde4 tilde2: `M344 55.266c-142 0-300.638 81.316-311.5 86.418 -8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114 c1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751 181.476 676 181.476c-149 0-189-126.21-332-126.21z`, tilde3: `M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457 -11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696 -338 0-409-156.573-744-156.573z`, tilde4: `M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345 -11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409 -175.236-744-175.236z`, // vec is from glyph U+20D7 in font KaTeX Main vec: `M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5 3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11 10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63 -1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1 -7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59 H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359 c-16-25.333-24-45-24-59z`, // widehat1 is a modified version of a glyph from the MnSymbol package widehat1: `M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22 c-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z`, // ditto widehat2, widehat3, & widehat4 widehat2: `M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10 -11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`, widehat3: `M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10 -11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`, widehat4: `M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10 -11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`, // widecheck paths are all inverted versions of widehat widecheck1: `M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1, -5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z`, widecheck2: `M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10, -11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`, widecheck3: `M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10, -11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`, widecheck4: `M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10, -11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`, // The next ten paths support reaction arrows from the mhchem package. // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX // baraboveleftarrow is mostly from from glyph U+2190 in font KaTeX Main baraboveleftarrow: `M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202 c4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5 c-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130 s-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47 121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6 s2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11 c0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z M100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z`, // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main rightarrowabovebar: `M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32 -27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39 -84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5 -119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5 -12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67 151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z`, // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end. // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em baraboveshortleftharpoon: `M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17 c2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21 c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40 c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`, rightharpoonaboveshortbar: `M0,241 l0,40c399126,0,399993,0,399993,0 c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, -231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z`, shortbaraboveleftharpoon: `M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9, 1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7, -152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`, shortrightharpoonabovebar: `M53,241l0,40c398570,0,399437,0,399437,0 c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, -231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z` }; /** * This node represents a document fragment, which contains elements, but when * placed into the DOM doesn't have any representation itself. It only contains * children and doesn't have any DOM node properties. */ class DocumentFragment { // HtmlDomNode // Never used; needed for satisfying interface. constructor(children) { this.children = void 0; this.classes = void 0; this.height = void 0; this.depth = void 0; this.maxFontSize = void 0; this.style = void 0; this.children = children; this.classes = []; this.height = 0; this.depth = 0; this.maxFontSize = 0; this.style = {}; } hasClass(className) { return utils.contains(this.classes, className); } /** Convert the fragment into a node. */ toNode() { const frag = document.createDocumentFragment(); for (let i = 0; i < this.children.length; i++) { frag.appendChild(this.children[i].toNode()); } return frag; } /** Convert the fragment into HTML markup. */ toMarkup() { let markup = ""; // Simply concatenate the markup for the children together. for (let i = 0; i < this.children.length; i++) { markup += this.children[i].toMarkup(); } return markup; } /** * Converts the math node into a string, similar to innerText. Applies to * MathDomNode's only. */ toText() { // To avoid this, we would subclass documentFragment separately for // MathML, but polyfills for subclassing is expensive per PR 1469. // $FlowFixMe: Only works for ChildType = MathDomNode. const toText = child => child.toText(); return this.children.map(toText).join(""); } } /** * These objects store the data about the DOM nodes we create, as well as some * extra data. They can then be transformed into real DOM nodes with the * `toNode` function or HTML markup using `toMarkup`. They are useful for both * storing extra properties on the nodes, as well as providing a way to easily * work with the DOM. * * Similar functions for working with MathML nodes exist in mathMLTree.js. * * TODO: refactor `span` and `anchor` into common superclass when * target environments support class inheritance */ /** * Create an HTML className based on a list of classes. In addition to joining * with spaces, we also remove empty classes. */ const createClass = function createClass(classes) { return classes.filter(cls => cls).join(" "); }; const initNode = function initNode(classes, options, style) { this.classes = classes || []; this.attributes = {}; this.height = 0; this.depth = 0; this.maxFontSize = 0; this.style = style || {}; if (options) { if (options.style.isTight()) { this.classes.push("mtight"); } const color = options.getColor(); if (color) { this.style.color = color; } } }; /** * Convert into an HTML node */ const toNode = function toNode(tagName) { const node = document.createElement(tagName); // Apply the class node.className = createClass(this.classes); // Apply inline styles for (const style in this.style) { if (this.style.hasOwnProperty(style)) { // $FlowFixMe Flow doesn't seem to understand span.style's type. node.style[style] = this.style[style]; } } // Apply attributes for (const attr in this.attributes) { if (this.attributes.hasOwnProperty(attr)) { node.setAttribute(attr, this.attributes[attr]); } } // Append the children, also as HTML nodes for (let i = 0; i < this.children.length; i++) { node.appendChild(this.children[i].toNode()); } return node; }; /** * Convert into an HTML markup string */ const toMarkup = function toMarkup(tagName) { let markup = `<${tagName}`; // Add the class if (this.classes.length) { markup += ` class="${utils.escape(createClass(this.classes))}"`; } let styles = ""; // Add the styles, after hyphenation for (const style in this.style) { if (this.style.hasOwnProperty(style)) { styles += `${utils.hyphenate(style)}:${this.style[style]};`; } } if (styles) { markup += ` style="${utils.escape(styles)}"`; } // Add the attributes for (const attr in this.attributes) { if (this.attributes.hasOwnProperty(attr)) { markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; } } markup += ">"; // Add the markup of the children, also as markup for (let i = 0; i < this.children.length; i++) { markup += this.children[i].toMarkup(); } markup += `</${tagName}>`; return markup; }; // Making the type below exact with all optional fields doesn't work due to // - https://github.com/facebook/flow/issues/4582 // - https://github.com/facebook/flow/issues/5688 // However, since *all* fields are optional, $Shape<> works as suggested in 5688 // above. // This type does not include all CSS properties. Additional properties should // be added as needed. /** * This node represents a span node, with a className, a list of children, and * an inline style. It also contains information about its height, depth, and * maxFontSize. * * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan * otherwise. This typesafety is important when HTML builders access a span's * children. */ class Span { constructor(classes, children, options, style) { this.children = void 0; this.attributes = void 0; this.classes = void 0; this.height = void 0; this.depth = void 0; this.width = void 0; this.maxFontSize = void 0; this.style = void 0; initNode.call(this, classes, options, style); this.children = children || []; } /** * Sets an arbitrary attribute on the span. Warning: use this wisely. Not * all browsers support attributes the same, and having too many custom * attributes is probably bad. */ setAttribute(attribute, value) { this.attributes[attribute] = value; } hasClass(className) { return utils.contains(this.classes, className); } toNode() { return toNode.call(this, "span"); } toMarkup() { return toMarkup.call(this, "span"); } } /** * This node represents an anchor (<a>) element with a hyperlink. See `span` * for further details. */ class Anchor { constructor(href, classes, children, options) { this.children = void 0; this.attributes = void 0; this.classes = void 0; this.height = void 0; this.depth = void 0; this.maxFontSize = void 0; this.style = void 0; initNode.call(this, classes, options); this.children = children || []; this.setAttribute('href', href); } setAttribute(attribute, value) { this.attributes[attribute] = value; } hasClass(className) { return utils.contains(this.classes, className); } toNode() { return toNode.call(this, "a"); } toMarkup() { return toMarkup.call(this, "a"); } } /** * This node represents an image embed (<img>) element. */ class Img { constructor(src, alt, style) { this.src = void 0; this.alt = void 0; this.classes = void 0; this.height = void 0; this.depth = void 0; this.maxFontSize = void 0; this.style = void 0; this.alt = alt; this.src = src; this.classes = ["mord"]; this.style = style; } hasClass(className) { return utils.contains(this.classes, className); } toNode() { const node = document.createElement("img"); node.src = this.src; node.alt = this.alt; node.className = "mord"; // Apply inline styles for (const style in this.style) { if (this.style.hasOwnProperty(style)) { // $FlowFixMe node.style[style] = this.style[style]; } } return node; } toMarkup() { let markup = `<img src='${this.src} 'alt='${this.alt}' `; // Add the styles, after hyphenation let styles = ""; for (const style in this.style) { if (this.style.hasOwnProperty(style)) { styles += `${utils.hyphenate(style)}:${this.style[style]};`; } } if (styles) { markup += ` style="${utils.escape(styles)}"`; } markup += "'/>"; return markup; } } const iCombinations = { 'î': '\u0131\u0302', 'ï': '\u0131\u0308', 'í': '\u0131\u0301', // 'ī': '\u0131\u0304', // enable when we add Extended Latin 'ì': '\u0131\u0300' }; /** * A symbol node contains information about a single symbol. It either renders * to a single text node, or a span with a single text node in it, dependi