"use strict"; (self["webpackChunk"] = self["webpackChunk"] || []).push([[48136],{ /***/ 48136: /*!********************************************************************!*\ !*** ./node_modules/_mathlatex@0.99.6@mathlatex/dist/mathlive.mjs ***! \********************************************************************/ /***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { /* unused harmony exports MathfieldElement, _renderMathInElement, convertAsciiMathToLatex, convertLatexToAsciiMath, convertLatexToMarkup, convertLatexToMathMl, convertLatexToSpeakableText, convertMathJsonToLatex, globalMathLive, makeSharedVirtualKeyboard, renderMathInDocument, renderMathInElement, validateLatex, version */ /** MathLive 0.98.5 */ var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __restKey = (key) => typeof key === "symbol" ? key : key + ""; var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; // src/common/types.ts function isArray(x) { return Array.isArray(x); } // src/editor/l10n-strings.ts var STRINGS = { // Simplified Chinese en: { "keyboard.tooltip.symbols": "\u7B26\u53F7", "keyboard.tooltip.greek": "\u5E0C\u814A\u5B57\u6BCD", "keyboard.tooltip.numeric": "\u6570\u5B57", "keyboard.tooltip.alphabetic": "\u7F57\u9A6C\u5B57\u6BCD", "tooltip.cut to clipboard": "\u526a\u5207\u5230\u526a\u8d34\u677f", "tooltip.copy to clipboard": "\u590D\u5236\u5230\u526A\u8D34\u677F", "tooltip.paste from clipboard":"\u7c98\u8d34", "tooltip.redo": "\u91CD\u505A", "tooltip.toggle virtual keyboard": "\u5207\u6362\u865A\u62DF\u952E\u76D8", "tooltip.undo": "\u64A4\u6D88", "menu.insert matrix": "\u63D2\u5165\u77E9\u9635", "menu.borders": "\u77E9\u9635\u5206\u9694\u7B26", "menu.array.add row above": "\u5728\u540E\u9762\u6DFB\u52A0\u884C", "menu.array.add row below": "\u5728\u524D\u9762\u6DFB\u52A0\u884C", "menu.array.add column after": "\u5728\u540E\u9762\u6DFB\u52A0\u5217r", "menu.array.add column before": "\u5728\u524D\u9762\u6DFB\u52A0\u5217", "menu.array.delete row": "\u5220\u9664\u884C", "menu.array.delete rows": "\u5220\u9664\u9009\u5B9A\u884C", "menu.array.delete column": "\u5220\u9664\u5217", "menu.array.delete columns": "\u5220\u9664\u9009\u5B9A\u7684\u5217", "menu.mode": "\u6A21\u5F0F", "menu.mode-math": "\u6570\u5B66", "menu.mode-text": "\u6587\u672C", "menu.mode-latex": "LaTeX", "tooltip.blackboard": "\u9ED1\u677F", "tooltip.bold": "\u7C97\u4F53", "tooltip.italic": "\u659C\u4F53", "tooltip.fraktur": "Fraktur", "tooltip.script": "\u811A\u672C", "tooltip.caligraphic": "\u8349\u4E66", "tooltip.typewriter": "\u6253\u5B57\u673A", "tooltip.roman-upright": "\u7F57\u9A6C\u76F4\u7ACB", "tooltip.row-by-col": "%@ \xD7 %@", "menu.font-style": "\u5B57\u4F53\u6837\u5F0F", "menu.accent": "\u91CD\u97F3", "menu.decoration": "\u88C5\u9970", "menu.color": "\u989C\u8272", "menu.background-color": "\u80CC\u666F", "menu.evaluate": "\u8BA1\u7B97", "menu.simplify": "\u7B80\u5316", "menu.solve": "\u6C42\u89E3", "menu.solve-for": "\u6C42\u89E3 %@", "menu.cut": "\u526A\u5207", "menu.copy": "\u590D\u5236", "menu.copy-as-latex": "\u590D\u5236\u4E3A LaTeX", "menu.copy-as-ascii-math": "\u590D\u5236\u4E3A ASCII Math", "menu.copy-as-mathml": "\u590D\u5236\u4E3A MathML", "menu.paste": "\u7C98\u8D34", "menu.select-all": "\u5168\u9009", // Colors (accessible labels in color swatches) "color.red": "\u7EA2\u8272", "color.orange": "\u6A59\u8272", "color.yellow": "\u9EC4\u8272", "color.lime": "\u7EFF\u9EC4\u8272", "color.green": "\u7EFF\u8272", "color.teal": "\u9752\u8272", "color.cyan": "\u84DD\u7EFF\u8272", "color.blue": "\u84DD\u8272", "color.indigo": "\u975B\u84DD\u8272", "color.purple": "\u7D2B\u8272", "color.magenta": "\u6D0B\u7EA2\u8272", "color.black": "\u9ED1\u8272", "color.dark-grey": "\u6DF1\u7070\u8272", "color.grey": "\u7070\u8272", "color.light-grey": "\u6D45\u7070\u8272", "color.white": "\u767D\u8272" }, }; // src/ui/utils/capabilities.ts function isBrowser() { return "window" in globalThis && "document" in globalThis; } function isTouchCapable() { if ("matchMedia" in window) return window.matchMedia("(pointer: coarse)").matches; return "ontouchstart" in window || navigator.maxTouchPoints > 0; } function canVibrate() { return typeof navigator.vibrate === "function"; } function osPlatform() { var _a3, _b3; if (!isBrowser()) return "other"; const platform2 = (_b3 = (_a3 = navigator["userAgentData"]) == null ? void 0 : _a3.platform) != null ? _b3 : navigator.platform; if (/^mac/i.test(platform2)) { if (navigator.maxTouchPoints === 5) return "ios"; return "macos"; } if (/^win/i.test(platform2)) return "windows"; if (/android/i.test(navigator.userAgent)) return "android"; if (/iphone|ipod|ipad/i.test(navigator.userAgent)) return "ios"; if (/\bcros\b/i.test(navigator.userAgent)) return "chromeos"; return "other"; } function supportRegexPropertyEscape() { if (!isBrowser()) return true; if (/firefox/i.test(navigator.userAgent)) { const m = navigator.userAgent.match(/firefox\/(\d+)/i); if (!m) return false; const version2 = parseInt(m[1]); return version2 >= 78; } if (/trident/i.test(navigator.userAgent)) return false; if (/edge/i.test(navigator.userAgent)) { const m = navigator.userAgent.match(/edg\/(\d+)/i); if (!m) return false; const version2 = parseInt(m[1]); return version2 >= 79; } return true; } function supportPopover() { return HTMLElement.prototype.hasOwnProperty("popover"); } // src/core/l10n.ts var l10n = { strings: STRINGS, _locale: "", // Important! Set the locale to empty so it can be determined at runtime _dirty: false, _subscribers: [], _numberFormatter: void 0, get locale() { if (!l10n._locale) l10n._locale = isBrowser() ? navigator.language.slice(0, 5) : "en-US"; return l10n._locale; }, set locale(value) { l10n._locale = value; l10n._numberFormatter = void 0; l10n.dirty = true; }, get numberFormatter() { if (!l10n._numberFormatter) l10n._numberFormatter = new Intl.NumberFormat(l10n.locale); return l10n._numberFormatter; }, /* * Two forms for this function: * - merge(locale, strings) * Merge a dictionary of keys -> values for the specified locale * - merge(strings) * Merge a dictionary of locale code -> dictionary of keys -> values * */ merge(locale, strings) { if (typeof locale === "string" && strings) { l10n.strings[locale] = __spreadValues(__spreadValues({}, l10n.strings[locale]), strings); l10n.dirty = true; } else { for (const l of Object.keys( locale )) l10n.merge(l, locale[l]); } }, get dirty() { return l10n._dirty; }, set dirty(val) { if (l10n._dirty || l10n._dirty === val) return; l10n._dirty = true; setTimeout(() => { l10n._dirty = false; this._subscribers.forEach((x) => x == null ? void 0 : x()); }, 0); }, subscribe(callback) { l10n._subscribers.push(callback); return l10n._subscribers.length - 1; }, unsubscribe(id) { if (id < 0 || id >= l10n._subscribers.length) return; l10n._subscribers[id] = void 0; }, /** * Update the l10n strings in the DOM */ update(root) { let elements = root.querySelectorAll("[data-l10n-tooltip]"); for (const element of elements) { const key = element.getAttribute("data-l10n-tooltip"); if (key) { const localized = localize(key); if (localized) element.setAttribute("data-tooltip", localized); } } elements = root.querySelectorAll("[data-l10n-arial-label]"); for (const element of elements) { const key = element.getAttribute("data-l10n-arial-label"); if (key) { const localized = localize(key); if (localized) element.setAttribute("aria-label", localized); } } } }; function localize(key, ...params) { if (key === void 0) return void 0; let result = ""; const locale = l10n.locale; if (l10n.strings[locale]) result = l10n.strings[locale][key]; const language = locale.slice(0, 2); if (!result && l10n.strings[language]) result = l10n.strings[language][key]; if (!result) result = l10n.strings.en[key]; if (!result) return void 0; const regex = /(%@|%([0-9]+)\$@)/g; let match = regex.exec(result); let index = 0; while (match) { const parameter = params[index++]; if (parameter) { const parameterIndex = match[2] ? parseInt(match[2], 10) - 1 : index - 1; let repl = params[parameterIndex]; if (typeof repl === "number") repl = l10n.numberFormatter.format(repl); result = result.replace(match[1], repl); } match = regex.exec(result); } result = result.replace(/%%/g, "%"); return result; } // src/core/color.ts var MATHEMATICA_COLORS = { m0: "#3F3D99", // Strong blue m1: "#993D71", // Strong cerise m2: "#998B3D", // Strong gold m3: "#3D9956", // Malachite green m4: "#3D5A99", // Strong cobalt blue m5: "#993D90", // Strong orchid m6: "#996D3D", // Strong orange m7: "#43993D", // Strong sap green m8: "#3D7999", // Cornflower blue m9: "#843D99" // Mulberry }; var MATLAB_COLORS = { blue: "#0072BD", // [0, 0.4470, 0.7410] blue orange: "#D95319", // [0.8500, 0.3250, 0.0980] orange yellow: "#EDB120", // [0.9290, 0.6940, 0.1250] yellow purple: "#7E2F8E", // [0.4940, 0.1840, 0.5560] purple green: "#77AC30", // [0.4660, 0.6740, 0.1880] green cyan: "#4DBEEE", // [0.3010, 0.7450, 0.9330] cyan red: "#A2142F" // [0.6350, 0.0780, 0.1840] dark red }; var BACKGROUND_COLORS = { "red": "#fbbbb6", "orange": "#ffe0c2", "yellow": "#fff1c2", "lime": "#d0e8b9", "green": "#bceac4", "teal": "#b9f1f1", "cyan": "#b8e5c9", "blue": "#b6d9fb", "indigo": "#d1c2f0", "purple": "#e3baf8", "magenta": "#f9c8e0", "black": "#353535", "dark-grey": "#8C8C8C", "grey": "#D0D0D0", "light-grey": "#F0F0F0", "white": "#ffffff" }; var FOREGROUND_COLORS = { "red": "#d7170b", //<- 700, 500 ->'#f21c0d' "orange": "#fe8a2b", "yellow": "#ffc02b", // <- 600, 500 -> '#ffcf33', "lime": "#63b215", "green": "#21ba3a", "teal": "#17cfcf", "cyan": "#13a7ec", "blue": "#0d80f2", "indigo": "#63c", "purple": "#a219e6", "magenta": "#eb4799", "black": "#000", "dark-grey": "#666", "grey": "#A6A6A6", "light-grey": "#d4d5d2", "white": "#ffffff" }; var DVIPS_TO_CHROMATIC = { Red: "red", Orange: "orange", Yellow: "yellow", LimeGreen: "lime", Green: "green", TealBlue: "teal", Blue: "blue", Violet: "indigo", Purple: "purple", Magenta: "magenta", Black: "black", Gray: "grey", White: "white" }; var DVIPS_COLORS = { Apricot: "#FBB982", Aquamarine: "#00B5BE", Bittersweet: "#C04F17", Black: "#221E1F", // Indeed. Blue: "#2D2F92", BlueGreen: "#00B3B8", BlueViolet: "#473992", BrickRed: "#B6321C", Brown: "#792500", BurntOrange: "#F7921D", CadetBlue: "#74729A", CarnationPink: "#F282B4", Cerulean: "#00A2E3", CornflowerBlue: "#41B0E4", Cyan: "#00AEEF", Dandelion: "#FDBC42", DarkOrchid: "#A4538A", Emerald: "#00A99D", ForestGreen: "#009B55", Fuchsia: "#8C368C", Goldenrod: "#FFDF42", Gray: "#949698", Green: "#00A64F", GreenYellow: "#DFE674", JungleGreen: "#00A99A", Lavender: "#F49EC4", Limegreen: "#8DC73E", Magenta: "#EC008C", Mahogany: "#A9341F", Maroon: "#AF3235", Melon: "#F89E7B", MidnightBlue: "#006795", Mulberry: "#A93C93", NavyBlue: "#006EB8", OliveGreen: "#3C8031", Orange: "#F58137", OrangeRed: "#ED135A", Orchid: "#AF72B0", Peach: "#F7965A", Periwinkle: "#7977B8", PineGreen: "#008B72", Plum: "#92268F", ProcessBlue: "#00B0F0", Purple: "#99479B", RawSienna: "#974006", Red: "#ED1B23", RedOrange: "#F26035", RedViolet: "#A1246B", Rhodamine: "#EF559F", RoyalBlue: "#0071BC", RoyalPurple: "#613F99", RubineRed: "#ED017D", Salmon: "#F69289", SeaGreen: "#3FBC9D", Sepia: "#671800", SkyBlue: "#46C5DD", SpringGreen: "#C6DC67", Tan: "#DA9D76", TealBlue: "#00AEB3", Thistle: "#D883B7", Turquoise: "#00B4CE", Violet: "#58429B", VioletRed: "#EF58A0", White: "#FFFFFF", WildStrawberry: "#EE2967", Yellow: "#FFF200", YellowGreen: "#98CC70", YellowOrange: "#FAA21A" }; function defaultColorMap(s) { var _a3, _b3, _c2, _d2, _e, _f; const colorSpec = s.split("!"); let baseRed; let baseGreen; let baseBlue; let red = 255; let green = 255; let blue = 255; let mix = -1; const complementary = colorSpec.length > 0 && colorSpec[0].startsWith("-"); if (complementary) colorSpec[0] = colorSpec[0].slice(1); for (let i = 0; i < colorSpec.length; i++) { baseRed = red; baseGreen = green; baseBlue = blue; const colorName = (_a3 = colorSpec[i].trim().match(/^([A-Za-z\d-]+)/)) == null ? void 0 : _a3[1]; const lcColorName = colorName == null ? void 0 : colorName.toLowerCase(); const color = !colorName ? colorSpec[i].trim() : (_f = (_e = (_d2 = (_c2 = (_b3 = FOREGROUND_COLORS[lcColorName]) != null ? _b3 : FOREGROUND_COLORS[DVIPS_TO_CHROMATIC[colorName]]) != null ? _c2 : MATLAB_COLORS[colorName]) != null ? _d2 : DVIPS_COLORS[colorName]) != null ? _e : MATHEMATICA_COLORS[colorName]) != null ? _f : colorSpec[i].trim(); let m = color.match(/^#([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i); if ((m == null ? void 0 : m[1]) && m[2] && m[3]) { red = Math.max(0, Math.min(255, Number.parseInt(m[1], 16))); green = Math.max(0, Math.min(255, Number.parseInt(m[2], 16))); blue = Math.max(0, Math.min(255, Number.parseInt(m[3], 16))); } else { m = color.match(/^#([\da-f]{3})$/i); if (m == null ? void 0 : m[1]) { const r1 = Number.parseInt(m[1][0], 16); const g1 = Number.parseInt(m[1][1], 16); const b1 = Number.parseInt(m[1][2], 16); red = Math.max(0, Math.min(255, r1 * 16 + r1)); green = Math.max(0, Math.min(255, g1 * 16 + g1)); blue = Math.max(0, Math.min(255, b1 * 16 + b1)); } else { m = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i); if ((m == null ? void 0 : m[1]) && m[2] && m[3]) { red = Math.max(0, Math.min(255, Number.parseInt(m[1]))); green = Math.max(0, Math.min(255, Number.parseInt(m[2]))); blue = Math.max(0, Math.min(255, Number.parseInt(m[3]))); } else return void 0; } } if (mix >= 0) { red = (1 - mix) * red + mix * baseRed; green = (1 - mix) * green + mix * baseGreen; blue = (1 - mix) * blue + mix * baseBlue; mix = -1; } if (i + 1 < colorSpec.length) mix = Math.max(0, Math.min(100, Number.parseInt(colorSpec[++i]))) / 100; } if (mix >= 0) { red = mix * red + (1 - mix) * baseRed; green = mix * green + (1 - mix) * baseGreen; blue = mix * blue + (1 - mix) * baseBlue; } if (complementary) { red = 255 - red; green = 255 - green; blue = 255 - blue; } return "#" + ("00" + Math.round(red).toString(16)).slice(-2) + ("00" + Math.round(green).toString(16)).slice(-2) + ("00" + Math.round(blue).toString(16)).slice(-2); } function defaultBackgroundColorMap(s) { var _a3, _b3; s = s.trim(); return (_b3 = (_a3 = BACKGROUND_COLORS[s.toLowerCase()]) != null ? _a3 : BACKGROUND_COLORS[DVIPS_TO_CHROMATIC[s]]) != null ? _b3 : defaultColorMap(s); } function parseHex(hex) { if (!hex) return void 0; if (hex[0] !== "#") return void 0; hex = hex.slice(1); let result; if (hex.length <= 4) { result = { r: parseInt(hex[0] + hex[0], 16), g: parseInt(hex[1] + hex[1], 16), b: parseInt(hex[2] + hex[2], 16) }; if (hex.length === 4) result.a = parseInt(hex[3] + hex[3], 16) / 255; } else { result = { r: parseInt(hex[0] + hex[1], 16), g: parseInt(hex[2] + hex[3], 16), b: parseInt(hex[4] + hex[5], 16) }; if (hex.length === 8) result.a = parseInt(hex[6] + hex[7], 16) / 255; } if (result && result.a === void 0) result.a = 1; return result; } function hueToRgbChannel(t1, t2, hue) { if (hue < 0) hue += 6; if (hue >= 6) hue -= 6; if (hue < 1) return (t2 - t1) * hue + t1; else if (hue < 3) return t2; else if (hue < 4) return (t2 - t1) * (4 - hue) + t1; return t1; } function hslToRgb(hsl) { let [hue, sat, light] = [hsl.h, hsl.s, hsl.l]; hue = (hue + 360) % 360 / 60; light = Math.max(0, Math.min(light, 1)); sat = Math.max(0, Math.min(sat, 1)); const t2 = light <= 0.5 ? light * (sat + 1) : light + sat - light * sat; const t1 = light * 2 - t2; return { r: Math.round(255 * hueToRgbChannel(t1, t2, hue + 2)), g: Math.round(255 * hueToRgbChannel(t1, t2, hue)), b: Math.round(255 * hueToRgbChannel(t1, t2, hue - 2)) }; } function clampByte(v) { if (v < 0) return 0; if (v > 255) return 255; return Math.round(v); } function rgbToHexstring(rgb) { const { r, g, b } = rgb; let hexString = ((1 << 24) + (clampByte(r) << 16) + (clampByte(g) << 8) + clampByte(b)).toString(16).slice(1); if (hexString[0] === hexString[1] && hexString[2] === hexString[3] && hexString[4] === hexString[5] && hexString[6] === hexString[7]) hexString = hexString[0] + hexString[2] + hexString[4]; return "#" + hexString; } function rgbToHsl(rgb) { let { r, g, b } = rgb; r = r / 255; g = g / 255; b = b / 255; const min = Math.min(r, g, b); const max = Math.max(r, g, b); const delta = max - min; let h; let s; if (max === min) h = 0; else if (r === max) h = (g - b) / delta; else if (g === max) h = 2 + (b - r) / delta; else if (b === max) h = 4 + (r - g) / delta; h = Math.min(h * 60, 360); if (h < 0) h += 360; const l = (min + max) / 2; if (max === min) s = 0; else if (l <= 0.5) s = delta / (max + min); else s = delta / (2 - max - min); return { h, s, l }; } function highlight(color) { let rgb = parseHex(color); if (!rgb) return color; let { h, s, l } = rgbToHsl(rgb); s += 0.1; l -= 0.1; return rgbToHexstring(hslToRgb({ h, s, l })); } // src/core/unicode.ts var UNICODE_TO_LATEX = { 60: "\\lt", 62: "\\gt", 111: "o", // Also \omicron 38: "\\&", // Also \And 123: "\\lbrace", 125: "\\rbrace", 91: "\\lbrack", 93: "\\rbrack", 58: "\\colon", // Also : 160: "~", // Also \space 172: "\\neg", // Also \lnot 183: "\\cdot", 188: "\\frac{1}{4}", 189: "\\frac{1}{2}", 190: "\\frac{3}{4}", 8304: "^{0}", 8305: "^{i}", 185: "^{1}", 178: "^{2}", // ² 179: "^{3}", 8224: "\\dagger", // Also \dag 8225: "\\ddagger", // Also \ddag 8230: "\\ldots", // Also \mathellipsis 8308: "^{4}", 8309: "^{5}", 8310: "^{6}", 8311: "^{7}", 8312: "^{8}", 8313: "^{9}", 8314: "^{+}", 8315: "^{-}", 8316: "^{=}", 8319: "^{n}", 8320: "_{0}", 8321: "_{1}", 8322: "_{2}", 8323: "_{3}", 8324: "_{4}", 8325: "_{5}", 8326: "_{6}", 8327: "_{7}", 8328: "_{8}", 8329: "_{9}", 8330: "_{+}", 8331: "_{-}", 8332: "_{=}", 8336: "_{a}", 8337: "_{e}", 8338: "_{o}", 8339: "_{x}", 8242: "\\prime", 39: "\\prime", 8592: "\\gets", // Also \leftarrow 8594: "\\to", // Also \rightarrow 9651: "\\triangle", // Also \bigtriangleup, \vartriangle 9661: "\\triangledown", 8715: "\\owns", // Also \ni 8727: "\\ast", // Also * 8739: "\\vert", // Also |, \mvert, \lvert, \rvert 8741: "\\Vert", // Also \parallel \shortparallel 8743: "\\land", // Also \wedge 8744: "\\lor", // Also \vee 8901: "\\cdot", // Also \centerdot, \cdotp 8904: "\\bowtie", // Also \Joint 8800: "\\ne", // Also \neq 8804: "\\le", // Also \leq 8805: "\\ge", // Also \geq 8869: "\\bot", // Also \perp 10231: "\\biconditional", // Also \longleftrightarrow 10232: "\\impliedby", // Also \Longleftarrow 10233: "\\implies", // Also \Longrightarrow 10234: "\\iff", 8450: "\\mathbb{C}", 8469: "\\mathbb{N}", 8473: "\\mathbb{P}", 8474: "\\mathbb{Q}", 8477: "\\mathbb{R}", 8484: "\\mathbb{Z}", 8461: "\\mathbb{H}", 8476: "\\Re", 8465: "\\Im", 42: "\\ast", 11036: "\\square", 9633: "\\square", 8720: "\\coprod", 8716: "\\not\\ni", 9671: "\\diamond", 8846: "\\uplus", 8851: "\\sqcap", 8852: "\\sqcup", 8768: "\\wr", 8750: "\\oint", 8226: "\\textbullet", 8722: "-", 978: "\\Upsilon" }; var MATH_LETTER_EXCEPTIONS = { 119893: 8462, 119965: 8492, 119968: 8496, 119969: 8497, 119971: 8459, 119972: 8464, 119975: 8466, 119976: 8499, 119981: 8475, 119994: 8495, 119996: 8458, 120004: 8500, 120070: 8493, 120075: 8460, 120076: 8465, 120085: 8476, 120093: 8488, 120122: 8450, 120127: 8461, 120133: 8469, 120135: 8473, 120136: 8474, 120137: 8477, 120145: 8484 }; var MATH_UNICODE_BLOCKS = [ { start: 119808, len: 26, offset: 65, style: "bold" }, { start: 119834, len: 26, offset: 97, style: "bold" }, { start: 119860, len: 26, offset: 65, style: "italic" }, { start: 119886, len: 26, offset: 97, style: "italic" }, { start: 119912, len: 26, offset: 65, style: "bolditalic" }, { start: 119938, len: 26, offset: 97, style: "bolditalic" }, { start: 119964, len: 26, offset: 65, variant: "script" }, { start: 119990, len: 26, offset: 97, variant: "script" }, { start: 120016, len: 26, offset: 65, variant: "script", style: "bold" }, { start: 120042, len: 26, offset: 97, variant: "script", style: "bold" }, { start: 120068, len: 26, offset: 65, variant: "fraktur" }, { start: 120094, len: 26, offset: 97, variant: "fraktur" }, { start: 120172, len: 26, offset: 65, variant: "fraktur", style: "bold" }, { start: 120198, len: 26, offset: 97, variant: "fraktur", style: "bold" }, { start: 120120, len: 26, offset: 65, variant: "double-struck" }, { start: 120146, len: 26, offset: 97, variant: "double-struck" }, { start: 120224, len: 26, offset: 65, variant: "sans-serif" }, { start: 120250, len: 26, offset: 97, variant: "sans-serif" }, { start: 120276, len: 26, offset: 65, variant: "sans-serif", style: "bold" }, { start: 120302, len: 26, offset: 97, variant: "sans-serif", style: "bold" }, { start: 120328, len: 26, offset: 65, variant: "sans-serif", style: "italic" }, { start: 120354, len: 26, offset: 97, variant: "sans-serif", style: "italic" }, { start: 120380, len: 26, offset: 65, variant: "sans-serif", style: "bolditalic" }, { start: 120406, len: 26, offset: 97, variant: "sans-serif", style: "bolditalic" }, { start: 120432, len: 26, offset: 65, variant: "monospace" }, { start: 120458, len: 26, offset: 97, variant: "monospace" }, { start: 120488, len: 25, offset: 913, style: "bold" }, { start: 120514, len: 25, offset: 945, style: "bold" }, { start: 120546, len: 25, offset: 913, style: "italic" }, { start: 120572, len: 25, offset: 945, style: "italic" }, { start: 120604, len: 25, offset: 913, style: "bolditalic" }, { start: 120630, len: 25, offset: 945, style: "bolditalic" }, { start: 120662, len: 25, offset: 913, variant: "sans-serif", style: "bold" }, { start: 120688, len: 25, offset: 945, variant: "sans-serif", style: "bold" }, { start: 120720, len: 25, offset: 913, variant: "sans-serif", style: "bolditalic" }, { start: 120746, len: 25, offset: 945, variant: "sans-serif", style: "bolditalic" }, { start: 120782, len: 10, offset: 48, variant: "main", style: "bold" }, { start: 120792, len: 10, offset: 48, variant: "double-struck" }, { start: 120803, len: 10, offset: 48, variant: "sans-serif" }, { start: 120812, len: 10, offset: 48, variant: "sans-serif", style: "bold" }, { start: 120822, len: 10, offset: 48, variant: "monospace" } ]; function mathVariantToUnicode(char, variant, style) { if (!/[A-Za-z\d]/.test(char)) return char; if (style === "up") style = void 0; if (!variant && !style) return char; const codepoint = char.codePointAt(0); if (codepoint === void 0) return char; for (const MATH_UNICODE_BLOCK of MATH_UNICODE_BLOCKS) { if (!variant || MATH_UNICODE_BLOCK.variant === variant) { if (!style || MATH_UNICODE_BLOCK.style === style) { if (codepoint >= MATH_UNICODE_BLOCK.offset && codepoint < MATH_UNICODE_BLOCK.offset + MATH_UNICODE_BLOCK.len) { const result = MATH_UNICODE_BLOCK.start + codepoint - MATH_UNICODE_BLOCK.offset; return String.fromCodePoint(MATH_LETTER_EXCEPTIONS[result] || result); } } } } return char; } function unicodeToMathVariant(codepoint) { var _a3; if ((codepoint < 119808 || codepoint > 120831) && (codepoint < 8448 || codepoint > 8527)) return { char: String.fromCodePoint(codepoint) }; for (const c in MATH_LETTER_EXCEPTIONS) { if (MATH_LETTER_EXCEPTIONS[c] === codepoint) { codepoint = (_a3 = c.codePointAt(0)) != null ? _a3 : 0; break; } } for (const MATH_UNICODE_BLOCK of MATH_UNICODE_BLOCKS) { if (codepoint >= MATH_UNICODE_BLOCK.start && codepoint < MATH_UNICODE_BLOCK.start + MATH_UNICODE_BLOCK.len) { return { char: String.fromCodePoint( codepoint - MATH_UNICODE_BLOCK.start + MATH_UNICODE_BLOCK.offset ), variant: MATH_UNICODE_BLOCK.variant, style: MATH_UNICODE_BLOCK.style }; } } return { char: String.fromCodePoint(codepoint) }; } function unicodeToLatex(s) { var _a3; let result = ""; for (const c of s) { if ("{}<>[]$&#^_%:'\u02DC".includes(c)) { result += c; continue; } const codepoint = (_a3 = c.codePointAt(0)) != null ? _a3 : 0; let latex = UNICODE_TO_LATEX[codepoint]; if (latex) { if (latex.startsWith("\\")) result += latex + " "; else result += latex; } else { const { char, variant, style } = unicodeToMathVariant(codepoint); latex = char; switch (variant) { case "double-struck": latex = `\\mathbb{${latex}}`; break; case "fraktur": latex = `\\mathfrak{${latex}}`; break; case "script": latex = `\\mathscr{${latex}}`; break; case "sans-serif": latex = `\\mathsf{${latex}}`; break; case "monospace": latex = `\\mathtt{${latex}}`; break; case "calligraphic": latex = `\\mathcal{${latex}}`; break; } switch (style) { case "bold": latex = `\\mathbf{${latex}}`; break; case "italic": latex = `\\mathit{${latex}}`; break; case "bolditalic": latex = `\\mathbfit{${latex}}`; break; } result += latex; } } return result; } // src/latex-commands/definitions-utils.ts function argAtoms(arg) { if (!arg) return []; if (Array.isArray(arg)) return arg; if (typeof arg === "object" && "group" in arg) return arg.group; return []; } var MATH_SYMBOLS = {}; var REVERSE_MATH_SYMBOLS = __spreadValues({}, UNICODE_TO_LATEX); var LATEX_COMMANDS = {}; var ENVIRONMENTS = {}; var TEXVC_MACROS = { ////////////////////////////////////////////////////////////////////// // texvc.sty // The texvc package contains macros available in mediawiki pages. // We omit the functions deprecated at // https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax // We also omit texvc's \O, which conflicts with \text{\O} darr: "\\downarrow", dArr: "\\Downarrow", Darr: "\\Downarrow", lang: "\\langle", rang: "\\rangle", uarr: "\\uparrow", uArr: "\\Uparrow", Uarr: "\\Uparrow", N: "\\mathbb{N}", R: "\\mathbb{R}", Z: "\\mathbb{Z}", alef: "\\aleph", alefsym: "\\aleph", Alpha: "\\mathrm{A}", Beta: "\\mathrm{B}", bull: "\\bullet", Chi: "\\mathrm{X}", clubs: "\\clubsuit", cnums: "\\mathbb{C}", Complex: "\\mathbb{C}", Dagger: "\\ddagger", diamonds: "\\diamondsuit", empty: "\\emptyset", Epsilon: "\\mathrm{E}", Eta: "\\mathrm{H}", exist: "\\exists", harr: "\\leftrightarrow", hArr: "\\Leftrightarrow", Harr: "\\Leftrightarrow", hearts: "\\heartsuit", image: "\\Im", infin: "\\infty", Iota: "\\mathrm{I}", isin: "\\in", Kappa: "\\mathrm{K}", larr: "\\leftarrow", lArr: "\\Leftarrow", Larr: "\\Leftarrow", lrarr: "\\leftrightarrow", lrArr: "\\Leftrightarrow", Lrarr: "\\Leftrightarrow", Mu: "\\mathrm{M}", natnums: "\\mathbb{N}", Nu: "\\mathrm{N}", Omicron: "\\mathrm{O}", plusmn: "\\pm", rarr: "\\rightarrow", rArr: "\\Rightarrow", Rarr: "\\Rightarrow", real: "\\Re", reals: "\\mathbb{R}", Reals: "\\mathbb{R}", Rho: "\\mathrm{P}", sdot: "\\cdot", sect: "\\S", spades: "\\spadesuit", sub: "\\subset", sube: "\\subseteq", supe: "\\supseteq", Tau: "\\mathrm{T}", thetasym: "\\vartheta", // TODO: varcoppa: { def: "\\\mbox{\\coppa}", expand: false }, weierp: "\\wp", Zeta: "\\mathrm{Z}" }; var AMSMATH_MACROS = { // amsmath.sty // http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf // Italic Greek capital letters. AMS defines these with \DeclareMathSymbol, // but they are equivalent to \mathit{\Letter}. varGamma: "\\mathit{\\Gamma}", varDelta: "\\mathit{\\Delta}", varTheta: "\\mathit{\\Theta}", varLambda: "\\mathit{\\Lambda}", varXi: "\\mathit{\\Xi}", varPi: "\\mathit{\\Pi}", varSigma: "\\mathit{\\Sigma}", varUpsilon: "\\mathit{\\Upsilon}", varPhi: "\\mathit{\\Phi}", varPsi: "\\mathit{\\Psi}", varOmega: "\\mathit{\\Omega}", // From http://tug.ctan.org/macros/latex/required/amsmath/amsmath.dtx // > \newcommand{\pod}[1]{ // > \allowbreak // > \if@display // > \mkern18mu // > \else // > \mkern8mu // > \fi // > (#1) // > } // 18mu = \quad // > \renewcommand{\pmod}[1]{ // > \pod{{\operator@font mod}\mkern6mu#1} // > } pmod: { def: "\\quad(\\operatorname{mod}\\ #1)", args: 1, expand: false, captureSelection: false }, // > \newcommand{\mod}[1]{ // > \allowbreak // > \if@display // > \mkern18mu // > \else // > \mkern12mu // > \fi //> {\operator@font mod}\,\,#1} mod: { def: "\\quad\\operatorname{mod}\\,\\,#1", args: 1, expand: false }, // > \renewcommand{\bmod}{ // > \nonscript\mskip-\medmuskip\mkern5mu // > \mathbin{\operator@font mod} // > \penalty900 \mkern5mu // > \nonscript\mskip-\medmuskip // > } // 5mu = \; bmod: { def: "\\;\\mathbin{\\operatorname{mod }}", expand: false } }; var BRAKET_MACROS = { bra: { def: "\\mathinner{\\langle{#1}|}", args: 1, captureSelection: false }, ket: { def: "\\mathinner{|{#1}\\rangle}", args: 1, captureSelection: false }, braket: { def: "\\mathinner{\\langle{#1}\\rangle}", args: 1, captureSelection: false }, set: { def: "\\mathinner{\\lbrace #1 \\rbrace}", args: 1, captureSelection: false }, Bra: { def: "\\left\\langle #1\\right|", args: 1, captureSelection: false }, Ket: { def: "\\left|#1\\right\\rangle", args: 1, captureSelection: false }, Braket: { def: "\\left\\langle{#1}\\right\\rangle", args: 1, captureSelection: false }, Set: { def: "\\left\\lbrace #1 \\right\\rbrace", args: 1, captureSelection: false } }; var DEFAULT_MACROS = { "iff": { primitive: true, captureSelection: true, def: "\\;\u27FA\\;" // >2,000 Note: additional spaces around the arrows }, "nicefrac": "^{#1}\\!\\!/\\!_{#2}", "phase": { def: "\\enclose{phasorangle}{#1}", args: 1, captureSelection: false }, // Proof Wiki "rd": "\\mathrm{d}", "rD": "\\mathrm{D}", // From Wolfram Alpha "doubleStruckCapitalN": "\\mathbb{N}", "doubleStruckCapitalR": "\\mathbb{R}", "doubleStruckCapitalQ": "\\mathbb{Q}", "doubleStruckCapitalZ": "\\mathbb{Z}", "doubleStruckCapitalP": "\\mathbb{P}", "scriptCapitalE": "\\mathscr{E}", "scriptCapitalH": "\\mathscr{H}", "scriptCapitalL": "\\mathscr{L}", "gothicCapitalC": "\\mathfrak{C}", "gothicCapitalH": "\\mathfrak{H}", "gothicCapitalI": "\\mathfrak{I}", "gothicCapitalR": "\\mathfrak{R}", "imaginaryI": "\\mathrm{i}", // NOTE: set in main (upright) as per ISO 80000-2:2009. "imaginaryJ": "\\mathrm{j}", // NOTE: set in main (upright) as per ISO 80000-2:2009. "exponentialE": "\\mathrm{e}", // NOTE: set in main (upright) as per ISO 80000-2:2009. "differentialD": "\\mathrm{d}", // NOTE: set in main (upright) as per ISO 80000-2:2009. "capitalDifferentialD": "\\mathrm{D}", // NOTE: set in main (upright) as per ISO 80000-2:2009. "mathstrut": { def: "\\vphantom{(}", primitive: true }, // https://ctan.math.washington.edu/tex-archive/macros/latex/contrib/actuarialangle/actuarialangle.pdf "angl": "\\enclose{actuarial}{#1}", "angln": "\\enclose{actuarial}{n}", "anglr": "\\enclose{actuarial}{r}", "anglk": "\\enclose{actuarial}{k}", ////////////////////////////////////////////////////////////////////// // mathtools.sty // In the summer of 2022, mathtools did some renaming of macros. // This is the latest version, with some legacy commands. "mathtools": { primitive: true, package: { //\providecommand\ordinarycolon{:} ordinarycolon: ":", //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}} //TODO(edemaine): Not yet centered. Fix via \raisebox or #726 vcentcolon: "\\mathrel{\\mathop\\ordinarycolon}", // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon} dblcolon: '{\\mathop{\\char"2237}}', // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=} coloneqq: '{\\mathop{\\char"2254}}', // ≔ // \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=} Coloneqq: '{\\mathop{\\char"2237\\char"3D}}', // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} coloneq: '{\\mathop{\\char"3A\\char"2212}}', // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} Coloneq: '{\\mathop{\\char"2237\\char"2212}}', // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon} eqqcolon: '{\\mathop{\\char"2255}}', // ≕ // \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} Eqqcolon: '{\\mathop{\\char"3D\\char"2237}}', // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon} eqcolon: '{\\mathop{\\char"2239}}', // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} Eqcolon: '{\\mathop{\\char"2212\\char"2237}}', // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} colonapprox: '{\\mathop{\\char"003A\\char"2248}}', // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} Colonapprox: '{\\mathop{\\char"2237\\char"2248}}', // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} colonsim: '{\\mathop{\\char"3A\\char"223C}}', // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} Colonsim: '{\\mathop{\\char"2237\\char"223C}}', colondash: "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}", Colondash: "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}", dashcolon: "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}", Dashcolon: "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}" // Some Unicode characters are implemented with macros to mathtools functions. // defineMacro("\u2237", "\\dblcolon"); // :: // defineMacro("\u2239", "\\eqcolon"); // -: // defineMacro("\u2254", "\\coloneqq"); // := // defineMacro("\u2255", "\\eqqcolon"); // =: // defineMacro("\u2A74", "\\Coloneqq"); // ::= } }, ////////////////////////////////////////////////////////////////////// // colonequals.sty // Alternate names for mathtools's macros: "ratio": "\\vcentcolon", "coloncolon": "\\dblcolon", "colonequals": "\\coloneq", "coloncolonequals": "\\Coloneq", "equalscolon": "\\eqcolon", "equalscoloncolon": "\\Eqcolon", "colonminus": "\\colondash", "coloncolonminus": "\\Colondash", "minuscolon": "\\dashcolon", "minuscoloncolon": "\\Dashcolon", // \colonapprox name is same in mathtools and colonequals. "coloncolonapprox": "\\Colonapprox", // \colonsim name is same in mathtools and colonequals. "coloncolonsim": "\\Colonsim", // Additional macros, implemented by analogy with mathtools definitions: "simcolon": "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}", "Simcolon": "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}", "simcoloncolon": "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}", "approxcolon": "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}", "Approxcolon": "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}", "approxcoloncolon": "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}", // Present in newtxmath, pxfonts and txfonts "notni": "\\mathrel{\\char`\u220C}", "limsup": "\\operatorname*{lim\\,sup}", "liminf": "\\operatorname*{lim\\,inf}", ////////////////////////////////////////////////////////////////////// // From amsopn.sty "injlim": "\\operatorname*{inj\\,lim}", "projlim": "\\operatorname*{proj\\,lim}", "varlimsup": "\\operatorname*{\\overline{lim}}", "varliminf": "\\operatorname*{\\underline{lim}}", "varinjlim": "\\operatorname*{\\underrightarrow{lim}}", "varprojlim": "\\operatorname*{\\underleftarrow{lim}}", ////////////////////////////////////////////////////////////////////// // statmath.sty // https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf "argmin": "\\operatorname*{arg\\,min}", "argmax": "\\operatorname*{arg\\,max}", "plim": "\\mathop{\\operatorname{plim}}\\limits", // mhchem "tripledash": { def: "\\vphantom{-}\\raise{4mu}{\\mkern1.5mu\\rule{2mu}{1.5mu}\\mkern{2.25mu}\\rule{2mu}{1.5mu}\\mkern{2.25mu}\\rule{2mu}{1.5mu}\\mkern{2mu}}", expand: true }, "braket.sty": { package: BRAKET_MACROS }, "amsmath.sty": { package: AMSMATH_MACROS, primitive: true }, "texvc.sty": { package: TEXVC_MACROS, primitive: false } }; var TEXT_SYMBOLS = { " ": 32, // want that in Text mode. "\\!": 33, "\\#": 35, "\\$": 36, "\\%": 37, "\\&": 38, "-": 45, // In Math mode, '-' is substituted to U+2212, but we don't "\\textunderscore": 95, // '_' "\\euro": 8364, "\\maltese": 10016, "\\{": 123, "\\}": 125, "\\textbraceleft": 123, "\\textbraceright": 125, "\\lbrace": 123, "\\rbrace": 125, "\\lbrack": 91, "\\rbrack": 93, "\\nobreakspace": 160, "\\ldots": 8230, "\\textellipsis": 8230, "\\backslash": 92, "`": 8216, "'": 8217, "``": 8220, "''": 8221, "\\degree": 176, "\\textasciicircum": 94, "\\textasciitilde": 126, "\\textasteriskcentered": 42, "\\textbackslash": 92, // '\' "\\textbullet": 8226, "\\textdollar": 36, "\\textsterling": 163, "\\textdagger": 8224, "\\textdaggerdbl": 8225, "\u2013": 8211, // EN DASH "\u2014": 8212, // EM DASH "\u2018": 8216, // LEFT SINGLE QUOTATION MARK "\u2019": 8217, // RIGHT SINGLE QUOTATION MARK "\u201C": 8220, // LEFT DOUBLE QUOTATION MARK "\u201D": 8221, // RIGHT DOUBLE QUOTATION MARK '"': 8221, // DOUBLE PRIME "\\ss": 223, // LATIN SMALL LETTER SHARP S "\\ae": 230, // LATIN SMALL LETTER AE "\\oe": 339, // LATIN SMALL LIGATURE OE "\\AE": 198, // LATIN CAPITAL LETTER AE "\\OE": 338, // LATIN CAPITAL LIGATURE OE "\\O": 216, // LATIN CAPITAL LETTER O WITH STROKE "\\i": 305, // LATIN SMALL LETTER DOTLESS I "\\j": 567, // LATIN SMALL LETTER DOTLESS J "\\aa": 229, // LATIN SMALL LETTER A WITH RING ABOVE "\\AA": 197 // LATIN CAPITAL LETTER A WITH RING ABOVE }; var COMMAND_MODE_CHARACTERS = /[\w!@*()-=+{}\[\]\\';:?/.,~<>`|$%#&^" ]/; var LETTER; var LETTER_AND_DIGITS; if (supportRegexPropertyEscape()) { LETTER = new RegExp("\\p{Letter}", "u"); LETTER_AND_DIGITS = new RegExp("[0-9\\p{Letter}]", "u"); } else { LETTER = /[a-zA-ZаАбБвВгГдДеЕёЁжЖзЗиИйЙкКлЛмМнНоОпПрРсСтТуУфФхХцЦчЧшШщЩъЪыЫьЬэЭюЮяĄąĆćĘꣳŃńÓóŚśŹźŻżàâäôéèëêïîçùûüÿæœÀÂÄÔÉÈËÊÏΟÇÙÛÜÆŒößÖẞìíòúÌÍÒÚáñÁÑ]/; LETTER_AND_DIGITS = /[\da-zA-ZаАбБвВгГдДеЕёЁжЖзЗиИйЙкКлЛмМнНоОпПрРсСтТуУфФхХцЦчЧшШщЩъЪыЫьЬэЭюЮяĄąĆćĘꣳŃńÓóŚśŹźŻżàâäôéèëêïîçùûüÿæœÀÂÄÔÉÈËÊÏΟÇÙÛÜÆŒößÖẞìíòúÌÍÒÚáñÁÑ]/; } function defineSymbol(symbol, codepoint, type = "mord", variant) { if (codepoint === void 0) return; MATH_SYMBOLS[symbol] = { definitionType: "symbol", type, variant, codepoint }; if (!REVERSE_MATH_SYMBOLS[codepoint]) REVERSE_MATH_SYMBOLS[codepoint] = symbol; } function defineSymbols(value, inType, inVariant) { if (typeof value === "string") { for (let i = 0; i < value.length; i++) { const ch = value.charAt(i); defineSymbol(ch, ch.codePointAt(0)); } return; } for (const [symbol, val, type, variant] of value) defineSymbol(symbol, val, type != null ? type : inType, variant != null ? variant : inVariant); } function defineSymbolRange(from, to) { for (let i = from; i <= to; i++) defineSymbol(String.fromCodePoint(i), i); } function getEnvironmentDefinition(name) { var _a3; return (_a3 = ENVIRONMENTS[name]) != null ? _a3 : null; } function suggest(mf, s) { var _a3, _b3; if (s.length === 0 || s === "\\" || !s.startsWith("\\")) return []; const result = []; for (const p in LATEX_COMMANDS) { if (p.startsWith(s) && !LATEX_COMMANDS[p].infix) result.push({ match: p, frequency: (_a3 = LATEX_COMMANDS[p].frequency) != null ? _a3 : 0 }); } for (const p in MATH_SYMBOLS) { if (p.startsWith(s)) result.push({ match: p, frequency: (_b3 = MATH_SYMBOLS[p].frequency) != null ? _b3 : 0 }); } const command = s.substring(1); for (const p of Object.keys(mf.options.macros)) if (p.startsWith(command)) result.push({ match: "\\" + p, frequency: 0 }); result.sort((a, b) => { var _a4, _b4; if (a.frequency === b.frequency) { if (a.match.length === b.match.length) return a.match < b.match ? -1 : 1; return a.match.length - b.match.length; } return ((_a4 = b.frequency) != null ? _a4 : 0) - ((_b4 = a.frequency) != null ? _b4 : 0); }); return result.map((x) => x.match); } function parseParameterTemplateArgument(argTemplate) { let type = "auto"; const r = argTemplate.match(/:([^=]+)/); if (r) type = r[1].trim(); return type; } function parseParameterTemplate(parameterTemplate) { if (!parameterTemplate) return []; const result = []; let parameters = parameterTemplate.split("]"); if (parameters[0].startsWith("[")) { result.push({ isOptional: true, type: parseParameterTemplateArgument(parameters[0].slice(1)) }); for (let i = 1; i <= parameters.length; i++) result.push(...parseParameterTemplate(parameters[i])); } else { parameters = parameterTemplate.split("}"); if (parameters[0].startsWith("{")) { result.push({ isOptional: false, type: parseParameterTemplateArgument(parameters[0].slice(1)) }); for (let i = 1; i <= parameters.length; i++) result.push(...parseParameterTemplate(parameters[i])); } } return result; } function parseArgAsString(atoms) { if (!atoms) return ""; let result = ""; let success = true; for (const atom of atoms) { if (typeof atom.value === "string") result += atom.value; else success = false; } return success ? result : ""; } function defineEnvironment(names, createAtom) { if (typeof names === "string") names = [names]; const def = { tabular: false, params: [], createAtom }; for (const name of names) ENVIRONMENTS[name] = def; } function defineTabularEnvironment(names, parameters, createAtom) { if (typeof names === "string") names = [names]; const parsedParameters = parseParameterTemplate(parameters); const data = { tabular: true, params: parsedParameters, createAtom }; for (const name of names) ENVIRONMENTS[name] = data; } function defineFunction(names, parameters, options) { var _a3, _b3; if (!options) options = {}; const data = { definitionType: "function", // The parameters for this function, an array of // {optional, type} params: parseParameterTemplate(parameters), ifMode: options.ifMode, isFunction: (_a3 = options.isFunction) != null ? _a3 : false, applyMode: options.applyMode, infix: (_b3 = options.infix) != null ? _b3 : false, parse: options.parse, createAtom: options.createAtom, applyStyle: options.applyStyle, serialize: options.serialize, render: options.render }; if (typeof names === "string") LATEX_COMMANDS["\\" + names] = data; else for (const name of names) LATEX_COMMANDS["\\" + name] = data; } var _DEFAULT_MACROS; function getMacros(otherMacros) { if (!_DEFAULT_MACROS) _DEFAULT_MACROS = normalizeMacroDictionary(DEFAULT_MACROS); if (!otherMacros) return _DEFAULT_MACROS; return normalizeMacroDictionary(__spreadValues(__spreadValues({}, _DEFAULT_MACROS), otherMacros)); } function normalizeMacroDefinition(def, options) { var _a3, _b3, _c2, _d2; if (typeof def === "string") { let argCount = 0; const defString = def; if (/(^|[^\\])#1/.test(defString)) argCount = 1; if (/(^|[^\\])#2/.test(defString)) argCount = 2; if (/(^|[^\\])#3/.test(defString)) argCount = 3; if (/(^|[^\\])#4/.test(defString)) argCount = 4; if (/(^|[^\\])#5/.test(defString)) argCount = 5; if (/(^|[^\\])#6/.test(defString)) argCount = 6; if (/(^|[^\\])#7/.test(defString)) argCount = 7; if (/(^|[^\\])#8/.test(defString)) argCount = 8; if (/(^|[^\\])#9/.test(defString)) argCount = 9; return { expand: (_a3 = options == null ? void 0 : options.expand) != null ? _a3 : true, captureSelection: (_b3 = options == null ? void 0 : options.captureSelection) != null ? _b3 : true, args: argCount, def: defString }; } return __spreadValues({ expand: (_c2 = options == null ? void 0 : options.expand) != null ? _c2 : true, captureSelection: (_d2 = options == null ? void 0 : options.captureSelection) != null ? _d2 : true, args: 0 }, def); } function normalizeMacroDictionary(macros) { if (!macros) return {}; const result = {}; for (const macro of Object.keys(macros)) { const macroDef = macros[macro]; if (macroDef === void 0 || macroDef === null) delete result[macro]; else if (typeof macroDef === "object" && "package" in macroDef) { for (const packageMacro of Object.keys(macroDef.package)) { result[packageMacro] = normalizeMacroDefinition( macroDef.package[packageMacro], { expand: !macroDef.primitive, captureSelection: macroDef.captureSelection } ); } } else result[macro] = normalizeMacroDefinition(macroDef); } return result; } function getDefinition(token, parseMode = "math") { if (!token || token.length === 0) return null; let info = null; if (token.startsWith("\\")) { info = LATEX_COMMANDS[token]; if (info) { if (!info.ifMode || info.ifMode === parseMode) return info; return null; } if (parseMode === "math") info = MATH_SYMBOLS[token]; else if (TEXT_SYMBOLS[token]) { info = { definitionType: "symbol", type: "mord", codepoint: TEXT_SYMBOLS[token] }; } } else if (parseMode === "math") { info = MATH_SYMBOLS[token]; if (!info && token.length === 1) { const command = charToLatex("math", token.codePointAt(0)); if (command.startsWith("\\")) return __spreadProps(__spreadValues({}, getDefinition(command, "math")), { command }); return null; } } else if (TEXT_SYMBOLS[token]) { info = { definitionType: "symbol", type: "mord", codepoint: TEXT_SYMBOLS[token] }; } else if (parseMode === "text") { info = { definitionType: "symbol", type: "mord", codepoint: token.codePointAt(0) }; } return info != null ? info : null; } function getMacroDefinition(token, macros) { if (!token.startsWith("\\")) return null; const command = token.slice(1); return macros[command]; } function charToLatex(parseMode, codepoint) { if (codepoint === void 0) return ""; if (parseMode === "math" && REVERSE_MATH_SYMBOLS[codepoint]) return REVERSE_MATH_SYMBOLS[codepoint]; if (parseMode === "text") { const textSymbol = Object.keys(TEXT_SYMBOLS).find( (x) => TEXT_SYMBOLS[x] === codepoint ); if (textSymbol) return textSymbol; return String.fromCodePoint(codepoint); } return String.fromCodePoint(codepoint); } // src/core/font-metrics-data.ts var M1 = [0, 0.68889, 0, 0, 0.72222]; var M2 = [0, 0.68889, 0, 0, 0.66667]; var M3 = [0, 0.68889, 0, 0, 0.77778]; var M4 = [0, 0.68889, 0, 0, 0.61111]; var M5 = [0.16667, 0.68889, 0, 0, 0.77778]; var M6 = [0, 0.68889, 0, 0, 0.55556]; var M7 = [0, 0, 0, 0, 0.25]; var M8 = [0, 0.825, 0, 0, 2.33334]; var M9 = [0, 0.9, 0, 0, 2.33334]; var M10 = [0, 0.68889, 0, 0, 0.54028]; var M11 = [-0.03598, 0.46402, 0, 0, 0.5]; var M12 = [-0.13313, 0.36687, 0, 0, 1]; var M13 = [0.01354, 0.52239, 0, 0, 1]; var M14 = [0.01354, 0.52239, 0, 0, 1.11111]; var M15 = [0, 0.54986, 0, 0, 1]; var M16 = [0, 0.69224, 0, 0, 0.5]; var M17 = [0, 0.43056, 0, 0, 1]; var M18 = [0.08198, 0.58198, 0, 0, 0.77778]; var M19 = [0.19444, 0.69224, 0, 0, 0.41667]; var M20 = [0.1808, 0.675, 0, 0, 1]; var M21 = [0.19444, 0.69224, 0, 0, 0.83334]; var M22 = [0.13667, 0.63667, 0, 0, 1]; var M23 = [-0.064, 0.437, 0, 0, 1.334]; var M24 = [0.08167, 0.58167, 0, 0, 0.77778]; var M25 = [0, 0.69224, 0, 0, 0.72222]; var M26 = [0, 0.69224, 0, 0, 0.66667]; var M27 = [-0.13313, 0.36687, 0, 0, 0.77778]; var M28 = [0.06062, 0.54986, 0, 0, 0.77778]; var M29 = [0, 0.69224, 0, 0, 0.77778]; var M30 = [0.25583, 0.75583, 0, 0, 0.77778]; var M31 = [0.25142, 0.75726, 0, 0, 0.77778]; var M32 = [0.20576, 0.70576, 0, 0, 0.77778]; var M33 = [0.30274, 0.79383, 0, 0, 0.77778]; var M34 = [0.22958, 0.72958, 0, 0, 0.77778]; var M35 = [0.1808, 0.675, 0, 0, 0.77778]; var M36 = [0.13667, 0.63667, 0, 0, 0.77778]; var M37 = [0.13597, 0.63597, 0, 0, 0.77778]; var M38 = [0.03517, 0.54986, 0, 0, 0.77778]; var M39 = [0, 0.675, 0, 0, 0.77778]; var M40 = [0.19444, 0.69224, 0, 0, 0.61111]; var M41 = [0, 0.54986, 0, 0, 0.76042]; var M42 = [0, 0.54986, 0, 0, 0.66667]; var M43 = [0.0391, 0.5391, 0, 0, 0.77778]; var M44 = [0.03517, 0.54986, 0, 0, 1.33334]; var M45 = [0.38569, 0.88569, 0, 0, 0.77778]; var M46 = [0.23222, 0.74111, 0, 0, 0.77778]; var M47 = [0.19444, 0.69224, 0, 0, 0.77778]; var M48 = [0, 0.37788, 0, 0, 0.5]; var M49 = [0, 0.54986, 0, 0, 0.72222]; var M50 = [0, 0.69224, 0, 0, 0.83334]; var M51 = [0.11111, 0.69224, 0, 0, 0.66667]; var M52 = [0.26167, 0.75726, 0, 0, 0.77778]; var M53 = [0.48256, 0.98256, 0, 0, 0.77778]; var M54 = [0.28481, 0.79383, 0, 0, 0.77778]; var M55 = [0.08167, 0.58167, 0, 0, 0.22222]; var M56 = [0.08167, 0.58167, 0, 0, 0.38889]; var M57 = [0, 0.43056, 0.04028, 0, 0.66667]; var M58 = [0.41951, 0.91951, 0, 0, 0.77778]; var M59 = [0.24982, 0.74947, 0, 0, 0.38865]; var M60 = [0.08319, 0.58283, 0, 0, 0.75623]; var M61 = [0, 0.10803, 0, 0, 0.27764]; var M62 = [0, 0.47534, 0, 0, 0.50181]; var M63 = [0.18906, 0.47534, 0, 0, 0.50181]; var M64 = [0, 0.69141, 0, 0, 0.50181]; var M65 = [0.24982, 0.74947, 0, 0, 0.27764]; var M66 = [0, 0.69141, 0, 0, 0.21471]; var M67 = [0.25, 0.75, 0, 0, 0.44722]; var M68 = [0, 0.64444, 0, 0, 0.575]; var M69 = [0.08556, 0.58556, 0, 0, 0.89444]; var M70 = [0, 0.69444, 0, 0, 0.89444]; var M71 = [0, 0.68611, 0, 0, 0.9]; var M72 = [0, 0.68611, 0, 0, 0.86944]; var M73 = [0.25, 0.75, 0, 0, 0.575]; var M74 = [0.25, 0.75, 0, 0, 0.31944]; var M75 = [0, 0.69444, 0, 0, 0.63889]; var M76 = [0, 0.69444, 0, 0, 0.31944]; var M77 = [0, 0.44444, 0, 0, 0.63889]; var M78 = [0, 0.44444, 0, 0, 0.51111]; var M79 = [0, 0.69444, 0, 0, 0.575]; var M80 = [0.13333, 0.63333, 0, 0, 0.89444]; var M81 = [0, 0.44444, 0, 0, 0.31944]; var M82 = [0, 0.69444, 0, 0, 0.86944]; var M83 = [0, 0.68611, 0, 0, 0.69166]; var M84 = [0, 0.68611, 0, 0, 0.83055]; var M85 = [0, 0.68611, 0, 0, 0.89444]; var M86 = [0, 0.69444, 0, 0, 0.60278]; var M87 = [0.19444, 0.69444, 0, 0, 0.51111]; var M88 = [0, 0.69444, 0, 0, 0.83055]; var M89 = [-0.10889, 0.39111, 0, 0, 1.14999]; var M90 = [0.19444, 0.69444, 0, 0, 0.575]; var M91 = [0.19444, 0.69444, 0, 0, 1.14999]; var M92 = [0.19444, 0.69444, 0, 0, 0.70277]; var M93 = [0.05556, 0.75, 0, 0, 0.575]; var M94 = [0, 0.68611, 0, 0, 0.95833]; var M95 = [0.08556, 0.58556, 0, 0, 0.76666]; var M96 = [-0.02639, 0.47361, 0, 0, 0.575]; var M97 = [0, 0.44444, 0, 0, 0.89444]; var M98 = [0, 0.55556, 0, 0, 0.76666]; var M99 = [-0.10889, 0.39111, 0, 0, 0.89444]; var M100 = [222e-5, 0.50222, 0, 0, 0.89444]; var M101 = [0.19667, 0.69667, 0, 0, 0.89444]; var M102 = [0.08556, 0.58556, 0, 0, 1.14999]; var M103 = [0, 0.69444, 0, 0, 0.70277]; var M104 = [-0.02778, 0.47222, 0, 0, 0.575]; var M105 = [0.25, 0.75, 0, 0, 0.51111]; var M106 = [-0.13889, 0.36111, 0, 0, 1.14999]; var M107 = [0.19444, 0.69444, 0, 0, 1.02222]; var M108 = [0.12963, 0.69444, 0, 0, 0.89444]; var M109 = [0.19444, 0.69444, 0, 0, 0.44722]; var M110 = [0, 0.64444, 0.13167, 0, 0.59111]; var M111 = [0.19444, 0.64444, 0.13167, 0, 0.59111]; var M112 = [0, 0.68611, 0.17208, 0, 0.8961]; var M113 = [0.19444, 0.44444, 0.105, 0, 0.53222]; var M114 = [0, 0.44444, 0.085, 0, 0.82666]; var M115 = [0, 0.69444, 0.06709, 0, 0.59111]; var M116 = [0, 0.69444, 0.12945, 0, 0.35555]; var M117 = [0, 0.69444, 0, 0, 0.94888]; var M118 = [0, 0.69444, 0.11472, 0, 0.59111]; var M119 = [0, 0.68611, 0.10778, 0, 0.88555]; var M120 = [0, 0.69444, 0.07939, 0, 0.62055]; var M121 = [0, 0.69444, 0.12417, 0, 0.30667]; var M122 = [0, 0.64444, 0.13556, 0, 0.51111]; var M123 = [0.19444, 0.64444, 0.13556, 0, 0.51111]; var M124 = [0, 0.68333, 0.16389, 0, 0.74333]; var M125 = [0.19444, 0.43056, 0.08847, 0, 0.46]; var M126 = [0, 0.43056, 0.07514, 0, 0.71555]; var M127 = [0, 0.69444, 0.06646, 0, 0.51111]; var M128 = [0, 0.69444, 0, 0, 0.83129]; var M129 = [0, 0.69444, 0.1225, 0, 0.51111]; var M130 = [0, 0.68333, 0.09403, 0, 0.76666]; var M131 = [0, 0.68333, 0.11111, 0, 0.76666]; var M132 = [0, 0.69444, 0.06961, 0, 0.51444]; var M133 = [0, 0.69444, 0, 0, 0.27778]; var M134 = [0.25, 0.75, 0, 0, 0.38889]; var M135 = [0, 0.64444, 0, 0, 0.5]; var M136 = [0, 0.69444, 0, 0, 0.77778]; var M137 = [0, 0.68333, 0, 0, 0.75]; var M138 = [0, 0.68333, 0, 0, 0.77778]; var M139 = [0, 0.68333, 0, 0, 0.68056]; var M140 = [0, 0.68333, 0, 0, 0.72222]; var M141 = [0.25, 0.75, 0, 0, 0.5]; var M142 = [0.25, 0.75, 0, 0, 0.27778]; var M143 = [0, 0.69444, 0, 0, 0.5]; var M144 = [0, 0.69444, 0, 0, 0.55556]; var M145 = [0, 0.43056, 0, 0, 0.44445]; var M146 = [0, 0.43056, 0, 0, 0.5]; var M147 = [0.19444, 0.43056, 0, 0, 0.55556]; var M148 = [0, 0.43056, 0, 0, 0.55556]; var M149 = [0.08333, 0.58333, 0, 0, 0.77778]; var M150 = [0, 0.43056, 0, 0, 0.27778]; var M151 = [0, 0.66786, 0, 0, 0.27778]; var M152 = [0, 0.69444, 0, 0, 0.75]; var M153 = [0, 0.66786, 0, 0, 0.5]; var M154 = [0, 0.68333, 0, 0, 0.625]; var M155 = [0.19444, 0.69444, 0, 0, 0.44445]; var M156 = [0, 0.69444, 0, 0, 0.72222]; var M157 = [0.19444, 0.69444, 0, 0, 0.5]; var M158 = [0.19444, 0.69444, 0, 0, 1]; var M159 = [0.011, 0.511, 0, 0, 1.126]; var M160 = [0.19444, 0.69444, 0, 0, 0.61111]; var M161 = [0.05556, 0.75, 0, 0, 0.5]; var M162 = [0, 0.68333, 0, 0, 0.83334]; var M163 = [0.0391, 0.5391, 0, 0, 0.66667]; var M164 = [-0.05555, 0.44445, 0, 0, 0.5]; var M165 = [0, 0.43056, 0, 0, 0.77778]; var M166 = [0, 0.55556, 0, 0, 0.66667]; var M167 = [-0.03625, 0.46375, 0, 0, 0.77778]; var M168 = [-0.01688, 0.48312, 0, 0, 0.77778]; var M169 = [0.0391, 0.5391, 0, 0, 1]; var M170 = [0, 0.69444, 0, 0, 0.61111]; var M171 = [-0.03472, 0.46528, 0, 0, 0.5]; var M172 = [0.25, 0.75, 0, 0, 0.44445]; var M173 = [-0.14236, 0.35764, 0, 0, 1]; var M174 = [0.244, 0.744, 0, 0, 0.412]; var M175 = [0.19444, 0.69444, 0, 0, 0.88889]; var M176 = [0.12963, 0.69444, 0, 0, 0.77778]; var M177 = [0.19444, 0.69444, 0, 0, 0.38889]; var M178 = [0.011, 0.511, 0, 0, 1.638]; var M179 = [0.19444, 0.69444, 0, 0, 0]; var M180 = [0, 0.44444, 0, 0, 0.575]; var M181 = [0.19444, 0.44444, 0, 0, 0.575]; var M182 = [0, 0.68611, 0, 0, 0.75555]; var M183 = [0, 0.69444, 0, 0, 0.66759]; var M184 = [0, 0.68611, 0, 0, 0.80555]; var M185 = [0, 0.68611, 0.08229, 0, 0.98229]; var M186 = [0, 0.68611, 0, 0, 0.76666]; var M187 = [0, 0.44444, 0, 0, 0.58472]; var M188 = [0.19444, 0.44444, 0, 0, 0.6118]; var M189 = [0.19444, 0.43056, 0, 0, 0.5]; var M190 = [0, 0.68333, 0.02778, 0.08334, 0.76278]; var M191 = [0, 0.68333, 0.08125, 0.05556, 0.83125]; var M192 = [0, 0.43056, 0, 0.05556, 0.48472]; var M193 = [0.19444, 0.43056, 0, 0.08334, 0.51702]; var M194 = [0.25, 0.75, 0, 0, 0.42778]; var M195 = [0, 0.69444, 0, 0, 0.55]; var M196 = [0, 0.69444, 0, 0, 0.73334]; var M197 = [0, 0.69444, 0, 0, 0.79445]; var M198 = [0, 0.69444, 0, 0, 0.51945]; var M199 = [0, 0.69444, 0, 0, 0.70278]; var M200 = [0, 0.69444, 0, 0, 0.76389]; var M201 = [0.25, 0.75, 0, 0, 0.34306]; var M202 = [0, 0.69444, 0, 0, 0.56111]; var M203 = [0, 0.69444, 0, 0, 0.25556]; var M204 = [0.19444, 0.45833, 0, 0, 0.56111]; var M205 = [0, 0.45833, 0, 0, 0.56111]; var M206 = [0, 0.69444, 0, 0, 0.30556]; var M207 = [0, 0.69444, 0, 0, 0.58056]; var M208 = [0, 0.69444, 0, 0, 0.67223]; var M209 = [0, 0.69444, 0, 0, 0.85556]; var M210 = [0, 0.69444, 0, 0, 0.55834]; var M211 = [0, 0.65556, 0.11156, 0, 0.5]; var M212 = [0, 0.69444, 0.08094, 0, 0.70834]; var M213 = [0.17014, 0, 0, 0, 0.44445]; var M214 = [0, 0.69444, 0.0799, 0, 0.5]; var M215 = [0, 0.69444, 0, 0, 0.73752]; var M216 = [0, 0.69444, 0.09205, 0, 0.5]; var M217 = [0, 0.69444, 0.09031, 0, 0.77778]; var M218 = [0, 0.69444, 0.07816, 0, 0.27778]; var M219 = [0, 0.69444, 316e-5, 0, 0.5]; var M220 = [0.19444, 0.69444, 0, 0, 0.83334]; var M221 = [0.05556, 0.75, 0, 0, 0.83334]; var M222 = [0, 0.75, 0, 0, 0.5]; var M223 = [0.125, 0.08333, 0, 0, 0.27778]; var M224 = [0, 0.08333, 0, 0, 0.27778]; var M225 = [0, 0.65556, 0, 0, 0.5]; var M226 = [0, 0.69444, 0, 0, 0.47222]; var M227 = [0, 0.69444, 0, 0, 0.66667]; var M228 = [0, 0.69444, 0, 0, 0.59722]; var M229 = [0, 0.69444, 0, 0, 0.54167]; var M230 = [0, 0.69444, 0, 0, 0.70834]; var M231 = [0.25, 0.75, 0, 0, 0.28889]; var M232 = [0, 0.69444, 0, 0, 0.51667]; var M233 = [0, 0.44444, 0, 0, 0.44445]; var M234 = [0.19444, 0.44444, 0, 0, 0.51667]; var M235 = [0, 0.44444, 0, 0, 0.38333]; var M236 = [0, 0.44444, 0, 0, 0.51667]; var M237 = [0, 0.69444, 0, 0, 0.83334]; var M238 = [0.35001, 0.85, 0, 0, 0.45834]; var M239 = [0.35001, 0.85, 0, 0, 0.57778]; var M240 = [0.35001, 0.85, 0, 0, 0.41667]; var M241 = [0.35001, 0.85, 0, 0, 0.58334]; var M242 = [0, 0.72222, 0, 0, 0.55556]; var M243 = [1e-5, 0.6, 0, 0, 0.66667]; var M244 = [1e-5, 0.6, 0, 0, 0.77778]; var M245 = [0.25001, 0.75, 0, 0, 0.94445]; var M246 = [0.306, 0.805, 0.19445, 0, 0.47222]; var M247 = [0.30612, 0.805, 0.19445, 0, 0.47222]; var M248 = [0.25001, 0.75, 0, 0, 0.83334]; var M249 = [0.35001, 0.85, 0, 0, 0.47222]; var M250 = [0.25001, 0.75, 0, 0, 1.11111]; var M251 = [0.65002, 1.15, 0, 0, 0.59722]; var M252 = [0.65002, 1.15, 0, 0, 0.81111]; var M253 = [0.65002, 1.15, 0, 0, 0.47222]; var M254 = [0.65002, 1.15, 0, 0, 0.66667]; var M255 = [0, 0.75, 0, 0, 1]; var M256 = [0.55001, 1.05, 0, 0, 1.27778]; var M257 = [0.862, 1.36, 0.44445, 0, 0.55556]; var M258 = [0.86225, 1.36, 0.44445, 0, 0.55556]; var M259 = [0.55001, 1.05, 0, 0, 1.11111]; var M260 = [0.65002, 1.15, 0, 0, 0.52778]; var M261 = [0.65002, 1.15, 0, 0, 0.61111]; var M262 = [0.55001, 1.05, 0, 0, 1.51112]; var M263 = [0.95003, 1.45, 0, 0, 0.73611]; var M264 = [0.95003, 1.45, 0, 0, 1.04445]; var M265 = [0.95003, 1.45, 0, 0, 0.52778]; var M266 = [0.95003, 1.45, 0, 0, 0.75]; var M267 = [0, 0.75, 0, 0, 1.44445]; var M268 = [0.95003, 1.45, 0, 0, 0.58334]; var M269 = [1.25003, 1.75, 0, 0, 0.79167]; var M270 = [1.25003, 1.75, 0, 0, 1.27778]; var M271 = [1.25003, 1.75, 0, 0, 0.58334]; var M272 = [1.25003, 1.75, 0, 0, 0.80556]; var M273 = [0, 0.825, 0, 0, 1.8889]; var M274 = [1.25003, 1.75, 0, 0, 0.63889]; var M275 = [0.64502, 1.155, 0, 0, 0.875]; var M276 = [1e-5, 0.6, 0, 0, 0.875]; var M277 = [-99e-5, 0.601, 0, 0, 0.66667]; var M278 = [0.64502, 1.155, 0, 0, 0.66667]; var M279 = [1e-5, 0.9, 0, 0, 0.88889]; var M280 = [0.65002, 1.15, 0, 0, 0.88889]; var M281 = [0.90001, 0, 0, 0, 0.88889]; var M282 = [-499e-5, 0.605, 0, 0, 1.05556]; var M283 = [0, 0.12, 0, 0, 0.45]; var M284 = [0, 0.61111, 0, 0, 0.525]; var M285 = [0.08333, 0.69444, 0, 0, 0.525]; var M286 = [-0.08056, 0.53055, 0, 0, 0.525]; var M287 = [-0.05556, 0.55556, 0, 0, 0.525]; var M288 = [0, 0.43056, 0, 0, 0.525]; var M289 = [0.22222, 0.43056, 0, 0, 0.525]; var M290 = [0, 0, 0, 0, 0.525]; var font_metrics_data_default = { "AMS-Regular": { 32: M7, // U+0020 65: M1, // U+0041 A 66: M2, // U+0042 B 67: M1, // U+0043 C 68: M1, // U+0044 D 69: M2, // U+0045 E 70: M4, // U+0046 F 71: M3, // U+0047 G 72: M3, // U+0048 H 73: [0, 0.68889, 0, 0, 0.38889], // U+0049 I 74: [0.16667, 0.68889, 0, 0, 0.5], // U+004a J 75: M3, // U+004b K 76: M2, // U+004c L 77: [0, 0.68889, 0, 0, 0.94445], // U+004d M 78: M1, // U+004e N 79: M5, // U+004f O 80: M4, // U+0050 P 81: M5, // U+0051 Q 82: M1, // U+0052 R 83: M6, // U+0053 S 84: M2, // U+0054 T 85: M1, // U+0055 U 86: M1, // U+0056 V 87: [0, 0.68889, 0, 0, 1], // U+0057 W 88: M1, // U+0058 X 89: M1, // U+0059 Y 90: M2, // U+005a Z 107: M6, // U+006b k 160: M7, // U+00a0 165: [0, 0.675, 0.025, 0, 0.75], // U+00a5 ¥ 174: [0.15559, 0.69224, 0, 0, 0.94666], // U+00ae ® 240: M6, // U+00f0 ð 295: M10, // U+0127 ħ 710: M8, // U+02c6 ˆ 732: M9, // U+02dc ˜ 770: M8, // U+0302 ̂ 771: M9, // U+0303 ̃ 989: M24, // U+03dd ϝ 1008: M57, // U+03f0 ϰ 8245: [0, 0.54986, 0, 0, 0.275], // U+2035 ‵ 8463: M10, // U+210f ℏ 8487: M1, // U+2127 ℧ 8498: M6, // U+2132 Ⅎ 8502: M2, // U+2136 ℶ 8503: [0, 0.68889, 0, 0, 0.44445], // U+2137 ℷ 8504: M2, // U+2138 ℸ 8513: [0, 0.68889, 0, 0, 0.63889], // U+2141 ⅁ 8592: M11, // U+2190 ← 8594: M11, // U+2192 → 8602: M12, // U+219a ↚ 8603: M12, // U+219b ↛ 8606: M13, // U+219e ↞ 8608: M13, // U+21a0 ↠ 8610: M14, // U+21a2 ↢ 8611: M14, // U+21a3 ↣ 8619: M15, // U+21ab ↫ 8620: M15, // U+21ac ↬ 8621: [-0.13313, 0.37788, 0, 0, 1.38889], // U+21ad ↭ 8622: M12, // U+21ae ↮ 8624: M16, // U+21b0 ↰ 8625: M16, // U+21b1 ↱ 8630: M17, // U+21b6 ↶ 8631: M17, // U+21b7 ↷ 8634: M18, // U+21ba ↺ 8635: M18, // U+21bb ↻ 8638: M19, // U+21be ↾ 8639: M19, // U+21bf ↿ 8642: M19, // U+21c2 ⇂ 8643: M19, // U+21c3 ⇃ 8644: M20, // U+21c4 ⇄ 8646: M20, // U+21c6 ⇆ 8647: M20, // U+21c7 ⇇ 8648: M21, // U+21c8 ⇈ 8649: M20, // U+21c9 ⇉ 8650: M21, // U+21ca ⇊ 8651: M13, // U+21cb ⇋ 8652: M13, // U+21cc ⇌ 8653: M12, // U+21cd ⇍ 8654: M12, // U+21ce ⇎ 8655: M12, // U+21cf ⇏ 8666: M22, // U+21da ⇚ 8667: M22, // U+21db ⇛ 8669: [-0.13313, 0.37788, 0, 0, 1], // U+21dd ⇝ 8672: M23, // U+21e0 ⇠ 8674: M23, // U+21e2 ⇢ 8705: [0, 0.825, 0, 0, 0.5], // U+2201 ∁ 8708: M6, // U+2204 ∄ 8709: M24, // U+2205 ∅ 8717: [0, 0.43056, 0, 0, 0.42917], // U+220d ∍ 8722: M11, // U+2212 − 8724: [0.08198, 0.69224, 0, 0, 0.77778], // U+2214 ∔ 8726: M24, // U+2216 ∖ 8733: M29, // U+221d ∝ 8736: M25, // U+2220 ∠ 8737: M25, // U+2221 ∡ 8738: [0.03517, 0.52239, 0, 0, 0.72222], // U+2222 ∢ 8739: M55, // U+2223 ∣ 8740: [0.25142, 0.74111, 0, 0, 0.27778], // U+2224 ∤ 8741: M56, // U+2225 ∥ 8742: [0.25142, 0.74111, 0, 0, 0.5], // U+2226 ∦ 8756: M26, // U+2234 ∴ 8757: M26, // U+2235 ∵ 8764: M27, // U+223c ∼ 8765: [-0.13313, 0.37788, 0, 0, 0.77778], // U+223d ∽ 8769: M27, // U+2241 ≁ 8770: M167, // U+2242 ≂ 8774: M33, // U+2246 ≆ 8776: M168, // U+2248 ≈ 8778: M24, // U+224a ≊ 8782: M28, // U+224e ≎ 8783: M28, // U+224f ≏ 8785: M18, // U+2251 ≑ 8786: M18, // U+2252 ≒ 8787: M18, // U+2253 ≓ 8790: M29, // U+2256 ≖ 8791: M34, // U+2257 ≗ 8796: [0.08198, 0.91667, 0, 0, 0.77778], // U+225c ≜ 8806: M30, // U+2266 ≦ 8807: M30, // U+2267 ≧ 8808: M31, // U+2268 ≨ 8809: M31, // U+2269 ≩ 8812: [0.25583, 0.75583, 0, 0, 0.5], // U+226c ≬ 8814: M32, // U+226e ≮ 8815: M32, // U+226f ≯ 8816: M33, // U+2270 ≰ 8817: M33, // U+2271 ≱ 8818: M34, // U+2272 ≲ 8819: M34, // U+2273 ≳ 8822: M35, // U+2276 ≶ 8823: M35, // U+2277 ≷ 8828: M36, // U+227c ≼ 8829: M36, // U+227d ≽ 8830: M34, // U+227e ≾ 8831: M34, // U+227f ≿ 8832: M32, // U+2280 ⊀ 8833: M32, // U+2281 ⊁ 8840: M33, // U+2288 ⊈ 8841: M33, // U+2289 ⊉ 8842: M37, // U+228a ⊊ 8843: M37, // U+228b ⊋ 8847: M38, // U+228f ⊏ 8848: M38, // U+2290 ⊐ 8858: M18, // U+229a ⊚ 8859: M18, // U+229b ⊛ 8861: M18, // U+229d ⊝ 8862: M39, // U+229e ⊞ 8863: M39, // U+229f ⊟ 8864: M39, // U+22a0 ⊠ 8865: M39, // U+22a1 ⊡ 8872: [0, 0.69224, 0, 0, 0.61111], // U+22a8 ⊨ 8873: M25, // U+22a9 ⊩ 8874: [0, 0.69224, 0, 0, 0.88889], // U+22aa ⊪ 8876: M4, // U+22ac ⊬ 8877: M4, // U+22ad ⊭ 8878: M1, // U+22ae ⊮ 8879: M1, // U+22af ⊯ 8882: M38, // U+22b2 ⊲ 8883: M38, // U+22b3 ⊳ 8884: M36, // U+22b4 ⊴ 8885: M36, // U+22b5 ⊵ 8888: [0, 0.54986, 0, 0, 1.11111], // U+22b8 ⊸ 8890: M147, // U+22ba ⊺ 8891: M40, // U+22bb ⊻ 8892: M40, // U+22bc ⊼ 8901: [0, 0.54986, 0, 0, 0.27778], // U+22c5 ⋅ 8903: M24, // U+22c7 ⋇ 8905: M24, // U+22c9 ⋉ 8906: M24, // U+22ca ⋊ 8907: M29, // U+22cb ⋋ 8908: M29, // U+22cc ⋌ 8909: [-0.03598, 0.46402, 0, 0, 0.77778], // U+22cd ⋍ 8910: M41, // U+22ce ⋎ 8911: M41, // U+22cf ⋏ 8912: M38, // U+22d0 ⋐ 8913: M38, // U+22d1 ⋑ 8914: M42, // U+22d2 ⋒ 8915: M42, // U+22d3 ⋓ 8916: M26, // U+22d4 ⋔ 8918: M43, // U+22d6 ⋖ 8919: M43, // U+22d7 ⋗ 8920: M44, // U+22d8 ⋘ 8921: M44, // U+22d9 ⋙ 8922: M45, // U+22da ⋚ 8923: M45, // U+22db ⋛ 8926: M36, // U+22de ⋞ 8927: M36, // U+22df ⋟ 8928: M33, // U+22e0 ⋠ 8929: M33, // U+22e1 ⋡ 8934: M46, // U+22e6 ⋦ 8935: M46, // U+22e7 ⋧ 8936: M46, // U+22e8 ⋨ 8937: M46, // U+22e9 ⋩ 8938: M32, // U+22ea ⋪ 8939: M32, // U+22eb ⋫ 8940: M33, // U+22ec ⋬ 8941: M33, // U+22ed ⋭ 8994: M47, // U+2322 ⌢ 8995: M47, // U+2323 ⌣ 9416: [0.15559, 0.69224, 0, 0, 0.90222], // U+24c8 Ⓢ 9484: M16, // U+250c ┌ 9488: M16, // U+2510 ┐ 9492: M48, // U+2514 └ 9496: M48, // U+2518 ┘ 9585: [0.19444, 0.68889, 0, 0, 0.88889], // U+2571 ╱ 9586: [0.19444, 0.74111, 0, 0, 0.88889], // U+2572 ╲ 9632: M39, // U+25a0 ■ 9633: M39, // U+25a1 □ 9650: M49, // U+25b2 ▲ 9651: M49, // U+25b3 △ 9654: M38, // U+25b6 ▶ 9660: M49, // U+25bc ▼ 9661: M49, // U+25bd ▽ 9664: M38, // U+25c0 ◀ 9674: M51, // U+25ca ◊ 9733: [0.19444, 0.69224, 0, 0, 0.94445], // U+2605 ★ 10003: M50, // U+2713 ✓ 10016: M50, // U+2720 ✠ 10731: M51, // U+29eb ⧫ 10846: [0.19444, 0.75583, 0, 0, 0.61111], // U+2a5e ⩞ 10877: M36, // U+2a7d ⩽ 10878: M36, // U+2a7e ⩾ 10885: M30, // U+2a85 ⪅ 10886: M30, // U+2a86 ⪆ 10887: M37, // U+2a87 ⪇ 10888: M37, // U+2a88 ⪈ 10889: M52, // U+2a89 ⪉ 10890: M52, // U+2a8a ⪊ 10891: M53, // U+2a8b ⪋ 10892: M53, // U+2a8c ⪌ 10901: M36, // U+2a95 ⪕ 10902: M36, // U+2a96 ⪖ 10933: M31, // U+2ab5 ⪵ 10934: M31, // U+2ab6 ⪶ 10935: M52, // U+2ab7 ⪷ 10936: M52, // U+2ab8 ⪸ 10937: M52, // U+2ab9 ⪹ 10938: M52, // U+2aba ⪺ 10949: M30, // U+2ac5 ⫅ 10950: M30, // U+2ac6 ⫆ 10955: M54, // U+2acb ⫋ 10956: M54, // U+2acc ⫌ 57350: M55, // U+e006  57351: M56, // U+e007  57352: M24, // U+e008  57353: M57, // U+e009  57356: M31, // U+e00c  57357: M31, // U+e00d  57358: M58, // U+e00e  57359: M33, // U+e00f  57360: M33, // U+e010  57361: M58, // U+e011  57366: M31, // U+e016  57367: M31, // U+e017  57368: M31, // U+e018  57369: M31, // U+e019  57370: M37, // U+e01a  57371: M37 // U+e01b  }, "Caligraphic-Regular": { 32: M7, // U+0020 65: [0, 0.68333, 0, 0.19445, 0.79847], // U+0041 A 66: [0, 0.68333, 0.03041, 0.13889, 0.65681], // U+0042 B 67: [0, 0.68333, 0.05834, 0.13889, 0.52653], // U+0043 C 68: [0, 0.68333, 0.02778, 0.08334, 0.77139], // U+0044 D 69: [0, 0.68333, 0.08944, 0.11111, 0.52778], // U+0045 E 70: [0, 0.68333, 0.09931, 0.11111, 0.71875], // U+0046 F 71: [0.09722, 0.68333, 0.0593, 0.11111, 0.59487], // U+0047 G 72: [0, 0.68333, 965e-5, 0.11111, 0.84452], // U+0048 H 73: [0, 0.68333, 0.07382, 0, 0.54452], // U+0049 I 74: [0.09722, 0.68333, 0.18472, 0.16667, 0.67778], // U+004a J 75: [0, 0.68333, 0.01445, 0.05556, 0.76195], // U+004b K 76: [0, 0.68333, 0, 0.13889, 0.68972], // U+004c L 77: [0, 0.68333, 0, 0.13889, 1.2009], // U+004d M 78: [0, 0.68333, 0.14736, 0.08334, 0.82049], // U+004e N 79: [0, 0.68333, 0.02778, 0.11111, 0.79611], // U+004f O 80: [0, 0.68333, 0.08222, 0.08334, 0.69556], // U+0050 P 81: [0.09722, 0.68333, 0, 0.11111, 0.81667], // U+0051 Q 82: [0, 0.68333, 0, 0.08334, 0.8475], // U+0052 R 83: [0, 0.68333, 0.075, 0.13889, 0.60556], // U+0053 S 84: [0, 0.68333, 0.25417, 0, 0.54464], // U+0054 T 85: [0, 0.68333, 0.09931, 0.08334, 0.62583], // U+0055 U 86: [0, 0.68333, 0.08222, 0, 0.61278], // U+0056 V 87: [0, 0.68333, 0.08222, 0.08334, 0.98778], // U+0057 W 88: [0, 0.68333, 0.14643, 0.13889, 0.7133], // U+0058 X 89: [0.09722, 0.68333, 0.08222, 0.08334, 0.66834], // U+0059 Y 90: [0, 0.68333, 0.07944, 0.13889, 0.72473], // U+005a Z 160: M7 // U+00a0 }, "Fraktur-Regular": { 32: M7, // U+0020 33: [0, 0.69141, 0, 0, 0.29574], // U+0021 ! 34: M66, // U+0022 " 38: [0, 0.69141, 0, 0, 0.73786], // U+0026 & 39: [0, 0.69141, 0, 0, 0.21201], // U+0027 ' 40: M59, // U+0028 ( 41: M59, // U+0029 ) 42: [0, 0.62119, 0, 0, 0.27764], // U+002a * 43: M60, // U+002b + 44: M61, // U+002c , 45: M60, // U+002d - 46: M61, // U+002e . 47: [0.24982, 0.74947, 0, 0, 0.50181], // U+002f / 48: M62, // U+0030 0 49: M62, // U+0031 1 50: M62, // U+0032 2 51: M63, // U+0033 3 52: M63, // U+0034 4 53: M63, // U+0035 5 54: M64, // U+0036 6 55: M63, // U+0037 7 56: M64, // U+0038 8 57: M63, // U+0039 9 58: [0, 0.47534, 0, 0, 0.21606], // U+003a : 59: [0.12604, 0.47534, 0, 0, 0.21606], // U+003b ; 61: [-0.13099, 0.36866, 0, 0, 0.75623], // U+003d = 63: [0, 0.69141, 0, 0, 0.36245], // U+003f ? 65: [0, 0.69141, 0, 0, 0.7176], // U+0041 A 66: [0, 0.69141, 0, 0, 0.88397], // U+0042 B 67: [0, 0.69141, 0, 0, 0.61254], // U+0043 C 68: [0, 0.69141, 0, 0, 0.83158], // U+0044 D 69: [0, 0.69141, 0, 0, 0.66278], // U+0045 E 70: [0.12604, 0.69141, 0, 0, 0.61119], // U+0046 F 71: [0, 0.69141, 0, 0, 0.78539], // U+0047 G 72: [0.06302, 0.69141, 0, 0, 0.7203], // U+0048 H 73: [0, 0.69141, 0, 0, 0.55448], // U+0049 I 74: [0.12604, 0.69141, 0, 0, 0.55231], // U+004a J 75: [0, 0.69141, 0, 0, 0.66845], // U+004b K 76: [0, 0.69141, 0, 0, 0.66602], // U+004c L 77: [0, 0.69141, 0, 0, 1.04953], // U+004d M 78: [0, 0.69141, 0, 0, 0.83212], // U+004e N 79: [0, 0.69141, 0, 0, 0.82699], // U+004f O 80: [0.18906, 0.69141, 0, 0, 0.82753], // U+0050 P 81: [0.03781, 0.69141, 0, 0, 0.82699], // U+0051 Q 82: [0, 0.69141, 0, 0, 0.82807], // U+0052 R 83: [0, 0.69141, 0, 0, 0.82861], // U+0053 S 84: [0, 0.69141, 0, 0, 0.66899], // U+0054 T 85: [0, 0.69141, 0, 0, 0.64576], // U+0055 U 86: [0, 0.69141, 0, 0, 0.83131], // U+0056 V 87: [0, 0.69141, 0, 0, 1.04602], // U+0057 W 88: [0, 0.69141, 0, 0, 0.71922], // U+0058 X 89: [0.18906, 0.69141, 0, 0, 0.83293], // U+0059 Y 90: [0.12604, 0.69141, 0, 0, 0.60201], // U+005a Z 91: M65, // U+005b [ 93: M65, // U+005d ] 94: [0, 0.69141, 0, 0, 0.49965], // U+005e ^ 97: [0, 0.47534, 0, 0, 0.50046], // U+0061 a 98: [0, 0.69141, 0, 0, 0.51315], // U+0062 b 99: [0, 0.47534, 0, 0, 0.38946], // U+0063 c 100: [0, 0.62119, 0, 0, 0.49857], // U+0064 d 101: [0, 0.47534, 0, 0, 0.40053], // U+0065 e 102: [0.18906, 0.69141, 0, 0, 0.32626], // U+0066 f 103: [0.18906, 0.47534, 0, 0, 0.5037], // U+0067 g 104: [0.18906, 0.69141, 0, 0, 0.52126], // U+0068 h 105: [0, 0.69141, 0, 0, 0.27899], // U+0069 i 106: [0, 0.69141, 0, 0, 0.28088], // U+006a j 107: [0, 0.69141, 0, 0, 0.38946], // U+006b k 108: [0, 0.69141, 0, 0, 0.27953], // U+006c l 109: [0, 0.47534, 0, 0, 0.76676], // U+006d m 110: [0, 0.47534, 0, 0, 0.52666], // U+006e n 111: [0, 0.47534, 0, 0, 0.48885], // U+006f o 112: [0.18906, 0.52396, 0, 0, 0.50046], // U+0070 p 113: [0.18906, 0.47534, 0, 0, 0.48912], // U+0071 q 114: [0, 0.47534, 0, 0, 0.38919], // U+0072 r 115: [0, 0.47534, 0, 0, 0.44266], // U+0073 s 116: [0, 0.62119, 0, 0, 0.33301], // U+0074 t 117: [0, 0.47534, 0, 0, 0.5172], // U+0075 u 118: [0, 0.52396, 0, 0, 0.5118], // U+0076 v 119: [0, 0.52396, 0, 0, 0.77351], // U+0077 w 120: [0.18906, 0.47534, 0, 0, 0.38865], // U+0078 x 121: [0.18906, 0.47534, 0, 0, 0.49884], // U+0079 y 122: [0.18906, 0.47534, 0, 0, 0.39054], // U+007a z 160: M7, // U+00a0 8216: M66, // U+2018 ‘ 8217: M66, // U+2019 ’ 58112: [0, 0.62119, 0, 0, 0.49749], // U+e300  58113: [0, 0.62119, 0, 0, 0.4983], // U+e301  58114: [0.18906, 0.69141, 0, 0, 0.33328], // U+e302  58115: [0.18906, 0.69141, 0, 0, 0.32923], // U+e303  58116: [0.18906, 0.47534, 0, 0, 0.50343], // U+e304  58117: [0, 0.69141, 0, 0, 0.33301], // U+e305  58118: [0, 0.62119, 0, 0, 0.33409], // U+e306  58119: [0, 0.47534, 0, 0, 0.50073] // U+e307  }, "Main-Bold": { 32: M7, // U+0020 33: [0, 0.69444, 0, 0, 0.35], // U+0021 ! 34: M86, // U+0022 " 35: [0.19444, 0.69444, 0, 0, 0.95833], // U+0023 # 36: M93, // U+0024 $ 37: [0.05556, 0.75, 0, 0, 0.95833], // U+0025 % 38: M70, // U+0026 & 39: M76, // U+0027 ' 40: M67, // U+0028 ( 41: M67, // U+0029 ) 42: [0, 0.75, 0, 0, 0.575], // U+002a * 43: M80, // U+002b + 44: [0.19444, 0.15556, 0, 0, 0.31944], // U+002c , 45: M235, // U+002d - 46: [0, 0.15556, 0, 0, 0.31944], // U+002e . 47: M73, // U+002f / 48: M68, // U+0030 0 49: M68, // U+0031 1 50: M68, // U+0032 2 51: M68, // U+0033 3 52: M68, // U+0034 4 53: M68, // U+0035 5 54: M68, // U+0036 6 55: M68, // U+0037 7 56: M68, // U+0038 8 57: M68, // U+0039 9 58: M81, // U+003a : 59: [0.19444, 0.44444, 0, 0, 0.31944], // U+003b ; 60: M69, // U+003c < 61: M99, // U+003d = 62: M69, // U+003e > 63: [0, 0.69444, 0, 0, 0.54305], // U+003f ? 64: M70, // U+0040 @ 65: M72, // U+0041 A 66: [0, 0.68611, 0, 0, 0.81805], // U+0042 B 67: M84, // U+0043 C 68: [0, 0.68611, 0, 0, 0.88194], // U+0044 D 69: M182, // U+0045 E 70: [0, 0.68611, 0, 0, 0.72361], // U+0046 F 71: [0, 0.68611, 0, 0, 0.90416], // U+0047 G 72: M71, // U+0048 H 73: [0, 0.68611, 0, 0, 0.43611], // U+0049 I 74: [0, 0.68611, 0, 0, 0.59444], // U+004a J 75: [0, 0.68611, 0, 0, 0.90138], // U+004b K 76: M83, // U+004c L 77: [0, 0.68611, 0, 0, 1.09166], // U+004d M 78: M71, // U+004e N 79: [0, 0.68611, 0, 0, 0.86388], // U+004f O 80: [0, 0.68611, 0, 0, 0.78611], // U+0050 P 81: [0.19444, 0.68611, 0, 0, 0.86388], // U+0051 Q 82: [0, 0.68611, 0, 0, 0.8625], // U+0052 R 83: [0, 0.68611, 0, 0, 0.63889], // U+0053 S 84: [0, 0.68611, 0, 0, 0.8], // U+0054 T 85: [0, 0.68611, 0, 0, 0.88472], // U+0055 U 86: [0, 0.68611, 0.01597, 0, 0.86944], // U+0056 V 87: [0, 0.68611, 0.01597, 0, 1.18888], // U+0057 W 88: M72, // U+0058 X 89: [0, 0.68611, 0.02875, 0, 0.86944], // U+0059 Y 90: [0, 0.68611, 0, 0, 0.70277], // U+005a Z 91: M74, // U+005b [ 92: M73, // U+005c \ 93: M74, // U+005d ] 94: M79, // U+005e ^ 95: [0.31, 0.13444, 0.03194, 0, 0.575], // U+005f _ 97: [0, 0.44444, 0, 0, 0.55902], // U+0061 a 98: M75, // U+0062 b 99: M78, // U+0063 c 100: M75, // U+0064 d 101: [0, 0.44444, 0, 0, 0.52708], // U+0065 e 102: [0, 0.69444, 0.10903, 0, 0.35139], // U+0066 f 103: [0.19444, 0.44444, 0.01597, 0, 0.575], // U+0067 g 104: M75, // U+0068 h 105: M76, // U+0069 i 106: [0.19444, 0.69444, 0, 0, 0.35139], // U+006a j 107: [0, 0.69444, 0, 0, 0.60694], // U+006b k 108: M76, // U+006c l 109: [0, 0.44444, 0, 0, 0.95833], // U+006d m 110: M77, // U+006e n 111: M180, // U+006f o 112: [0.19444, 0.44444, 0, 0, 0.63889], // U+0070 p 113: [0.19444, 0.44444, 0, 0, 0.60694], // U+0071 q 114: [0, 0.44444, 0, 0, 0.47361], // U+0072 r 115: [0, 0.44444, 0, 0, 0.45361], // U+0073 s 116: [0, 0.63492, 0, 0, 0.44722], // U+0074 t 117: M77, // U+0075 u 118: [0, 0.44444, 0.01597, 0, 0.60694], // U+0076 v 119: [0, 0.44444, 0.01597, 0, 0.83055], // U+0077 w 120: [0, 0.44444, 0, 0, 0.60694], // U+0078 x 121: [0.19444, 0.44444, 0.01597, 0, 0.60694], // U+0079 y 122: M78, // U+007a z 123: M73, // U+007b { 124: M74, // U+007c | 125: M73, // U+007d } 126: [0.35, 0.34444, 0, 0, 0.575], // U+007e ~ 160: M7, // U+00a0 163: [0, 0.69444, 0, 0, 0.86853], // U+00a3 £ 168: M79, // U+00a8 ¨ 172: [0, 0.44444, 0, 0, 0.76666], // U+00ac ¬ 176: M82, // U+00b0 ° 177: M80, // U+00b1 ± 184: [0.17014, 0, 0, 0, 0.51111], // U+00b8 ¸ 198: [0, 0.68611, 0, 0, 1.04166], // U+00c6 Æ 215: M80, // U+00d7 × 216: [0.04861, 0.73472, 0, 0, 0.89444], // U+00d8 Ø 223: M228, // U+00df ß 230: [0, 0.44444, 0, 0, 0.83055], // U+00e6 æ 247: M80, // U+00f7 ÷ 248: [0.09722, 0.54167, 0, 0, 0.575], // U+00f8 ø 305: M81, // U+0131 ı 338: [0, 0.68611, 0, 0, 1.16944], // U+0152 Œ 339: M97, // U+0153 œ 567: [0.19444, 0.44444, 0, 0, 0.35139], // U+0237 ȷ 710: M79, // U+02c6 ˆ 711: [0, 0.63194, 0, 0, 0.575], // U+02c7 ˇ 713: [0, 0.59611, 0, 0, 0.575], // U+02c9 ˉ 714: M79, // U+02ca ˊ 715: M79, // U+02cb ˋ 728: M79, // U+02d8 ˘ 729: M76, // U+02d9 ˙ 730: M82, // U+02da ˚ 732: M79, // U+02dc ˜ 733: M79, // U+02dd ˝ 915: M83, // U+0393 Γ 916: M94, // U+0394 Δ 920: M85, // U+0398 Θ 923: M184, // U+039b Λ 926: M186, // U+039e Ξ 928: M71, // U+03a0 Π 931: M84, // U+03a3 Σ 933: M85, // U+03a5 Υ 934: M84, // U+03a6 Φ 936: M85, // U+03a8 Ψ 937: M84, // U+03a9 Ω 8211: [0, 0.44444, 0.03194, 0, 0.575], // U+2013 – 8212: [0, 0.44444, 0.03194, 0, 1.14999], // U+2014 — 8216: M76, // U+2018 ‘ 8217: M76, // U+2019 ’ 8220: M86, // U+201c “ 8221: M86, // U+201d ” 8224: M87, // U+2020 † 8225: M87, // U+2021 ‡ 8242: [0, 0.55556, 0, 0, 0.34444], // U+2032 ′ 8407: [0, 0.72444, 0.15486, 0, 0.575], // U+20d7 ⃗ 8463: M183, // U+210f ℏ 8465: M88, // U+2111 ℑ 8467: [0, 0.69444, 0, 0, 0.47361], // U+2113 ℓ 8472: [0.19444, 0.44444, 0, 0, 0.74027], // U+2118 ℘ 8476: M88, // U+211c ℜ 8501: M103, // U+2135 ℵ 8592: M89, // U+2190 ← 8593: M90, // U+2191 ↑ 8594: M89, // U+2192 → 8595: M90, // U+2193 ↓ 8596: M89, // U+2194 ↔ 8597: M73, // U+2195 ↕ 8598: M91, // U+2196 ↖ 8599: M91, // U+2197 ↗ 8600: M91, // U+2198 ↘ 8601: M91, // U+2199 ↙ 8636: M89, // U+21bc ↼ 8637: M89, // U+21bd ↽ 8640: M89, // U+21c0 ⇀ 8641: M89, // U+21c1 ⇁ 8656: M89, // U+21d0 ⇐ 8657: M92, // U+21d1 ⇑ 8658: M89, // U+21d2 ⇒ 8659: M92, // U+21d3 ⇓ 8660: M89, // U+21d4 ⇔ 8661: [0.25, 0.75, 0, 0, 0.70277], // U+21d5 ⇕ 8704: M75, // U+2200 ∀ 8706: [0, 0.69444, 0.06389, 0, 0.62847], // U+2202 ∂ 8707: M75, // U+2203 ∃ 8709: M93, // U+2205 ∅ 8711: M94, // U+2207 ∇ 8712: M95, // U+2208 ∈ 8715: M95, // U+220b ∋ 8722: M80, // U+2212 − 8723: M80, // U+2213 ∓ 8725: M73, // U+2215 ∕ 8726: M73, // U+2216 ∖ 8727: M104, // U+2217 ∗ 8728: M96, // U+2218 ∘ 8729: M96, // U+2219 ∙ 8730: [0.18, 0.82, 0, 0, 0.95833], // U+221a √ 8733: M97, // U+221d ∝ 8734: [0, 0.44444, 0, 0, 1.14999], // U+221e ∞ 8736: M25, // U+2220 ∠ 8739: M74, // U+2223 ∣ 8741: M73, // U+2225 ∥ 8743: M98, // U+2227 ∧ 8744: M98, // U+2228 ∨ 8745: M98, // U+2229 ∩ 8746: M98, // U+222a ∪ 8747: [0.19444, 0.69444, 0.12778, 0, 0.56875], // U+222b ∫ 8764: M99, // U+223c ∼ 8768: [0.19444, 0.69444, 0, 0, 0.31944], // U+2240 ≀ 8771: M100, // U+2243 ≃ 8776: [0.02444, 0.52444, 0, 0, 0.89444], // U+2248 ≈ 8781: M100, // U+224d ≍ 8801: M100, // U+2261 ≡ 8804: M101, // U+2264 ≤ 8805: M101, // U+2265 ≥ 8810: M102, // U+226a ≪ 8811: M102, // U+226b ≫ 8826: M69, // U+227a ≺ 8827: M69, // U+227b ≻ 8834: M69, // U+2282 ⊂ 8835: M69, // U+2283 ⊃ 8838: M101, // U+2286 ⊆ 8839: M101, // U+2287 ⊇ 8846: M98, // U+228e ⊎ 8849: M101, // U+2291 ⊑ 8850: M101, // U+2292 ⊒ 8851: M98, // U+2293 ⊓ 8852: M98, // U+2294 ⊔ 8853: M80, // U+2295 ⊕ 8854: M80, // U+2296 ⊖ 8855: M80, // U+2297 ⊗ 8856: M80, // U+2298 ⊘ 8857: M80, // U+2299 ⊙ 8866: M103, // U+22a2 ⊢ 8867: M103, // U+22a3 ⊣ 8868: M70, // U+22a4 ⊤ 8869: M70, // U+22a5 ⊥ 8900: M96, // U+22c4 ⋄ 8901: [-0.02639, 0.47361, 0, 0, 0.31944], // U+22c5 ⋅ 8902: M104, // U+22c6 ⋆ 8968: M105, // U+2308 ⌈ 8969: M105, // U+2309 ⌉ 8970: M105, // U+230a ⌊ 8971: M105, // U+230b ⌋ 8994: M106, // U+2322 ⌢ 8995: M106, // U+2323 ⌣ 9651: M107, // U+25b3 △ 9657: M104, // U+25b9 ▹ 9661: M107, // U+25bd ▽ 9667: M104, // U+25c3 ◃ 9711: M91, // U+25ef ◯ 9824: M108, // U+2660 ♠ 9825: M108, // U+2661 ♡ 9826: M108, // U+2662 ♢ 9827: M108, // U+2663 ♣ 9837: [0, 0.75, 0, 0, 0.44722], // U+266d ♭ 9838: M109, // U+266e ♮ 9839: M109, // U+266f ♯ 10216: M67, // U+27e8 ⟨ 10217: M67, // U+27e9 ⟩ 10815: M71, // U+2a3f ⨿ 10927: M101, // U+2aaf ⪯ 10928: M101, // U+2ab0 ⪰ 57376: M179 // U+e020  }, "Main-BoldItalic": { 32: M7, // U+0020 33: [0, 0.69444, 0.11417, 0, 0.38611], // U+0021 ! 34: M120, // U+0022 " 35: [0.19444, 0.69444, 0.06833, 0, 0.94444], // U+0023 # 37: [0.05556, 0.75, 0.12861, 0, 0.94444], // U+0025 % 38: [0, 0.69444, 0.08528, 0, 0.88555], // U+0026 & 39: M116, // U+0027 ' 40: [0.25, 0.75, 0.15806, 0, 0.47333], // U+0028 ( 41: [0.25, 0.75, 0.03306, 0, 0.47333], // U+0029 ) 42: [0, 0.75, 0.14333, 0, 0.59111], // U+002a * 43: [0.10333, 0.60333, 0.03306, 0, 0.88555], // U+002b + 44: [0.19444, 0.14722, 0, 0, 0.35555], // U+002c , 45: [0, 0.44444, 0.02611, 0, 0.41444], // U+002d - 46: [0, 0.14722, 0, 0, 0.35555], // U+002e . 47: [0.25, 0.75, 0.15806, 0, 0.59111], // U+002f / 48: M110, // U+0030 0 49: M110, // U+0031 1 50: M110, // U+0032 2 51: M110, // U+0033 3 52: M111, // U+0034 4 53: M110, // U+0035 5 54: M110, // U+0036 6 55: M111, // U+0037 7 56: M110, // U+0038 8 57: M110, // U+0039 9 58: [0, 0.44444, 0.06695, 0, 0.35555], // U+003a : 59: [0.19444, 0.44444, 0.06695, 0, 0.35555], // U+003b ; 61: [-0.10889, 0.39111, 0.06833, 0, 0.88555], // U+003d = 63: M118, // U+003f ? 64: [0, 0.69444, 0.09208, 0, 0.88555], // U+0040 @ 65: [0, 0.68611, 0, 0, 0.86555], // U+0041 A 66: [0, 0.68611, 0.0992, 0, 0.81666], // U+0042 B 67: [0, 0.68611, 0.14208, 0, 0.82666], // U+0043 C 68: [0, 0.68611, 0.09062, 0, 0.87555], // U+0044 D 69: [0, 0.68611, 0.11431, 0, 0.75666], // U+0045 E 70: [0, 0.68611, 0.12903, 0, 0.72722], // U+0046 F 71: [0, 0.68611, 0.07347, 0, 0.89527], // U+0047 G 72: M112, // U+0048 H 73: [0, 0.68611, 0.15681, 0, 0.47166], // U+0049 I 74: [0, 0.68611, 0.145, 0, 0.61055], // U+004a J 75: [0, 0.68611, 0.14208, 0, 0.89499], // U+004b K 76: [0, 0.68611, 0, 0, 0.69777], // U+004c L 77: [0, 0.68611, 0.17208, 0, 1.07277], // U+004d M 78: M112, // U+004e N 79: [0, 0.68611, 0.09062, 0, 0.85499], // U+004f O 80: [0, 0.68611, 0.0992, 0, 0.78721], // U+0050 P 81: [0.19444, 0.68611, 0.09062, 0, 0.85499], // U+0051 Q 82: [0, 0.68611, 0.02559, 0, 0.85944], // U+0052 R 83: [0, 0.68611, 0.11264, 0, 0.64999], // U+0053 S 84: [0, 0.68611, 0.12903, 0, 0.7961], // U+0054 T 85: [0, 0.68611, 0.17208, 0, 0.88083], // U+0055 U 86: [0, 0.68611, 0.18625, 0, 0.86555], // U+0056 V 87: [0, 0.68611, 0.18625, 0, 1.15999], // U+0057 W 88: [0, 0.68611, 0.15681, 0, 0.86555], // U+0058 X 89: [0, 0.68611, 0.19803, 0, 0.86555], // U+0059 Y 90: [0, 0.68611, 0.14208, 0, 0.70888], // U+005a Z 91: [0.25, 0.75, 0.1875, 0, 0.35611], // U+005b [ 93: [0.25, 0.75, 0.09972, 0, 0.35611], // U+005d ] 94: M115, // U+005e ^ 95: [0.31, 0.13444, 0.09811, 0, 0.59111], // U+005f _ 97: [0, 0.44444, 0.09426, 0, 0.59111], // U+0061 a 98: [0, 0.69444, 0.07861, 0, 0.53222], // U+0062 b 99: [0, 0.44444, 0.05222, 0, 0.53222], // U+0063 c 100: [0, 0.69444, 0.10861, 0, 0.59111], // U+0064 d 101: [0, 0.44444, 0.085, 0, 0.53222], // U+0065 e 102: [0.19444, 0.69444, 0.21778, 0, 0.4], // U+0066 f 103: M113, // U+0067 g 104: [0, 0.69444, 0.09426, 0, 0.59111], // U+0068 h 105: [0, 0.69326, 0.11387, 0, 0.35555], // U+0069 i 106: [0.19444, 0.69326, 0.1672, 0, 0.35555], // U+006a j 107: [0, 0.69444, 0.11111, 0, 0.53222], // U+006b k 108: [0, 0.69444, 0.10861, 0, 0.29666], // U+006c l 109: [0, 0.44444, 0.09426, 0, 0.94444], // U+006d m 110: [0, 0.44444, 0.09426, 0, 0.64999], // U+006e n 111: [0, 0.44444, 0.07861, 0, 0.59111], // U+006f o 112: [0.19444, 0.44444, 0.07861, 0, 0.59111], // U+0070 p 113: M113, // U+0071 q 114: [0, 0.44444, 0.11111, 0, 0.50167], // U+0072 r 115: [0, 0.44444, 0.08167, 0, 0.48694], // U+0073 s 116: [0, 0.63492, 0.09639, 0, 0.385], // U+0074 t 117: [0, 0.44444, 0.09426, 0, 0.62055], // U+0075 u 118: [0, 0.44444, 0.11111, 0, 0.53222], // U+0076 v 119: [0, 0.44444, 0.11111, 0, 0.76777], // U+0077 w 120: [0, 0.44444, 0.12583, 0, 0.56055], // U+0078 x 121: [0.19444, 0.44444, 0.105, 0, 0.56166], // U+0079 y 122: [0, 0.44444, 0.13889, 0, 0.49055], // U+007a z 126: [0.35, 0.34444, 0.11472, 0, 0.59111], // U+007e ~ 160: M7, // U+00a0 168: [0, 0.69444, 0.11473, 0, 0.59111], // U+00a8 ¨ 176: M117, // U+00b0 ° 184: [0.17014, 0, 0, 0, 0.53222], // U+00b8 ¸ 198: [0, 0.68611, 0.11431, 0, 1.02277], // U+00c6 Æ 216: [0.04861, 0.73472, 0.09062, 0, 0.88555], // U+00d8 Ø 223: [0.19444, 0.69444, 0.09736, 0, 0.665], // U+00df ß 230: M114, // U+00e6 æ 248: [0.09722, 0.54167, 0.09458, 0, 0.59111], // U+00f8 ø 305: [0, 0.44444, 0.09426, 0, 0.35555], // U+0131 ı 338: [0, 0.68611, 0.11431, 0, 1.14054], // U+0152 Œ 339: M114, // U+0153 œ 567: [0.19444, 0.44444, 0.04611, 0, 0.385], // U+0237 ȷ 710: M115, // U+02c6 ˆ 711: [0, 0.63194, 0.08271, 0, 0.59111], // U+02c7 ˇ 713: [0, 0.59444, 0.10444, 0, 0.59111], // U+02c9 ˉ 714: [0, 0.69444, 0.08528, 0, 0.59111], // U+02ca ˊ 715: [0, 0.69444, 0, 0, 0.59111], // U+02cb ˋ 728: [0, 0.69444, 0.10333, 0, 0.59111], // U+02d8 ˘ 729: M116, // U+02d9 ˙ 730: M117, // U+02da ˚ 732: M118, // U+02dc ˜ 733: M118, // U+02dd ˝ 915: [0, 0.68611, 0.12903, 0, 0.69777], // U+0393 Γ 916: [0, 0.68611, 0, 0, 0.94444], // U+0394 Δ 920: [0, 0.68611, 0.09062, 0, 0.88555], // U+0398 Θ 923: [0, 0.68611, 0, 0, 0.80666], // U+039b Λ 926: [0, 0.68611, 0.15092, 0, 0.76777], // U+039e Ξ 928: M112, // U+03a0 Π 931: [0, 0.68611, 0.11431, 0, 0.82666], // U+03a3 Σ 933: M119, // U+03a5 Υ 934: [0, 0.68611, 0.05632, 0, 0.82666], // U+03a6 Φ 936: M119, // U+03a8 Ψ 937: [0, 0.68611, 0.0992, 0, 0.82666], // U+03a9 Ω 8211: [0, 0.44444, 0.09811, 0, 0.59111], // U+2013 – 8212: [0, 0.44444, 0.09811, 0, 1.18221], // U+2014 — 8216: M116, // U+2018 ‘ 8217: M116, // U+2019 ’ 8220: [0, 0.69444, 0.16772, 0, 0.62055], // U+201c “ 8221: M120 // U+201d ” }, "Main-Italic": { 32: M7, // U+0020 33: M121, // U+0021 ! 34: M132, // U+0022 " 35: [0.19444, 0.69444, 0.06616, 0, 0.81777], // U+0023 # 37: [0.05556, 0.75, 0.13639, 0, 0.81777], // U+0025 % 38: [0, 0.69444, 0.09694, 0, 0.76666], // U+0026 & 39: M121, // U+0027 ' 40: [0.25, 0.75, 0.16194, 0, 0.40889], // U+0028 ( 41: [0.25, 0.75, 0.03694, 0, 0.40889], // U+0029 ) 42: [0, 0.75, 0.14917, 0, 0.51111], // U+002a * 43: [0.05667, 0.56167, 0.03694, 0, 0.76666], // U+002b + 44: [0.19444, 0.10556, 0, 0, 0.30667], // U+002c , 45: [0, 0.43056, 0.02826, 0, 0.35778], // U+002d - 46: [0, 0.10556, 0, 0, 0.30667], // U+002e . 47: [0.25, 0.75, 0.16194, 0, 0.51111], // U+002f / 48: M122, // U+0030 0 49: M122, // U+0031 1 50: M122, // U+0032 2 51: M122, // U+0033 3 52: M123, // U+0034 4 53: M122, // U+0035 5 54: M122, // U+0036 6 55: M123, // U+0037 7 56: M122, // U+0038 8 57: M122, // U+0039 9 58: [0, 0.43056, 0.0582, 0, 0.30667], // U+003a : 59: [0.19444, 0.43056, 0.0582, 0, 0.30667], // U+003b ; 61: [-0.13313, 0.36687, 0.06616, 0, 0.76666], // U+003d = 63: M129, // U+003f ? 64: [0, 0.69444, 0.09597, 0, 0.76666], // U+0040 @ 65: [0, 0.68333, 0, 0, 0.74333], // U+0041 A 66: [0, 0.68333, 0.10257, 0, 0.70389], // U+0042 B 67: [0, 0.68333, 0.14528, 0, 0.71555], // U+0043 C 68: [0, 0.68333, 0.09403, 0, 0.755], // U+0044 D 69: [0, 0.68333, 0.12028, 0, 0.67833], // U+0045 E 70: [0, 0.68333, 0.13305, 0, 0.65277], // U+0046 F 71: [0, 0.68333, 0.08722, 0, 0.77361], // U+0047 G 72: M124, // U+0048 H 73: [0, 0.68333, 0.15806, 0, 0.38555], // U+0049 I 74: [0, 0.68333, 0.14028, 0, 0.525], // U+004a J 75: [0, 0.68333, 0.14528, 0, 0.76888], // U+004b K 76: [0, 0.68333, 0, 0, 0.62722], // U+004c L 77: [0, 0.68333, 0.16389, 0, 0.89666], // U+004d M 78: M124, // U+004e N 79: M130, // U+004f O 80: [0, 0.68333, 0.10257, 0, 0.67833], // U+0050 P 81: [0.19444, 0.68333, 0.09403, 0, 0.76666], // U+0051 Q 82: [0, 0.68333, 0.03868, 0, 0.72944], // U+0052 R 83: [0, 0.68333, 0.11972, 0, 0.56222], // U+0053 S 84: [0, 0.68333, 0.13305, 0, 0.71555], // U+0054 T 85: M124, // U+0055 U 86: [0, 0.68333, 0.18361, 0, 0.74333], // U+0056 V 87: [0, 0.68333, 0.18361, 0, 0.99888], // U+0057 W 88: [0, 0.68333, 0.15806, 0, 0.74333], // U+0058 X 89: [0, 0.68333, 0.19383, 0, 0.74333], // U+0059 Y 90: [0, 0.68333, 0.14528, 0, 0.61333], // U+005a Z 91: [0.25, 0.75, 0.1875, 0, 0.30667], // U+005b [ 93: [0.25, 0.75, 0.10528, 0, 0.30667], // U+005d ] 94: M127, // U+005e ^ 95: [0.31, 0.12056, 0.09208, 0, 0.51111], // U+005f _ 97: [0, 0.43056, 0.07671, 0, 0.51111], // U+0061 a 98: [0, 0.69444, 0.06312, 0, 0.46], // U+0062 b 99: [0, 0.43056, 0.05653, 0, 0.46], // U+0063 c 100: [0, 0.69444, 0.10333, 0, 0.51111], // U+0064 d 101: [0, 0.43056, 0.07514, 0, 0.46], // U+0065 e 102: [0.19444, 0.69444, 0.21194, 0, 0.30667], // U+0066 f 103: M125, // U+0067 g 104: [0, 0.69444, 0.07671, 0, 0.51111], // U+0068 h 105: [0, 0.65536, 0.1019, 0, 0.30667], // U+0069 i 106: [0.19444, 0.65536, 0.14467, 0, 0.30667], // U+006a j 107: [0, 0.69444, 0.10764, 0, 0.46], // U+006b k 108: [0, 0.69444, 0.10333, 0, 0.25555], // U+006c l 109: [0, 0.43056, 0.07671, 0, 0.81777], // U+006d m 110: [0, 0.43056, 0.07671, 0, 0.56222], // U+006e n 111: [0, 0.43056, 0.06312, 0, 0.51111], // U+006f o 112: [0.19444, 0.43056, 0.06312, 0, 0.51111], // U+0070 p 113: M125, // U+0071 q 114: [0, 0.43056, 0.10764, 0, 0.42166], // U+0072 r 115: [0, 0.43056, 0.08208, 0, 0.40889], // U+0073 s 116: [0, 0.61508, 0.09486, 0, 0.33222], // U+0074 t 117: [0, 0.43056, 0.07671, 0, 0.53666], // U+0075 u 118: [0, 0.43056, 0.10764, 0, 0.46], // U+0076 v 119: [0, 0.43056, 0.10764, 0, 0.66444], // U+0077 w 120: [0, 0.43056, 0.12042, 0, 0.46389], // U+0078 x 121: [0.19444, 0.43056, 0.08847, 0, 0.48555], // U+0079 y 122: [0, 0.43056, 0.12292, 0, 0.40889], // U+007a z 126: [0.35, 0.31786, 0.11585, 0, 0.51111], // U+007e ~ 160: M7, // U+00a0 168: [0, 0.66786, 0.10474, 0, 0.51111], // U+00a8 ¨ 176: M128, // U+00b0 ° 184: [0.17014, 0, 0, 0, 0.46], // U+00b8 ¸ 198: [0, 0.68333, 0.12028, 0, 0.88277], // U+00c6 Æ 216: [0.04861, 0.73194, 0.09403, 0, 0.76666], // U+00d8 Ø 223: [0.19444, 0.69444, 0.10514, 0, 0.53666], // U+00df ß 230: M126, // U+00e6 æ 248: [0.09722, 0.52778, 0.09194, 0, 0.51111], // U+00f8 ø 338: [0, 0.68333, 0.12028, 0, 0.98499], // U+0152 Œ 339: M126, // U+0153 œ 710: M127, // U+02c6 ˆ 711: [0, 0.62847, 0.08295, 0, 0.51111], // U+02c7 ˇ 713: [0, 0.56167, 0.10333, 0, 0.51111], // U+02c9 ˉ 714: [0, 0.69444, 0.09694, 0, 0.51111], // U+02ca ˊ 715: [0, 0.69444, 0, 0, 0.51111], // U+02cb ˋ 728: [0, 0.69444, 0.10806, 0, 0.51111], // U+02d8 ˘ 729: [0, 0.66786, 0.11752, 0, 0.30667], // U+02d9 ˙ 730: M128, // U+02da ˚ 732: [0, 0.66786, 0.11585, 0, 0.51111], // U+02dc ˜ 733: M129, // U+02dd ˝ 915: [0, 0.68333, 0.13305, 0, 0.62722], // U+0393 Γ 916: [0, 0.68333, 0, 0, 0.81777], // U+0394 Δ 920: M130, // U+0398 Θ 923: [0, 0.68333, 0, 0, 0.69222], // U+039b Λ 926: [0, 0.68333, 0.15294, 0, 0.66444], // U+039e Ξ 928: M124, // U+03a0 Π 931: [0, 0.68333, 0.12028, 0, 0.71555], // U+03a3 Σ 933: M131, // U+03a5 Υ 934: [0, 0.68333, 0.05986, 0, 0.71555], // U+03a6 Φ 936: M131, // U+03a8 Ψ 937: [0, 0.68333, 0.10257, 0, 0.71555], // U+03a9 Ω 8211: [0, 0.43056, 0.09208, 0, 0.51111], // U+2013 – 8212: [0, 0.43056, 0.09208, 0, 1.02222], // U+2014 — 8216: M121, // U+2018 ‘ 8217: M121, // U+2019 ’ 8220: [0, 0.69444, 0.1685, 0, 0.51444], // U+201c “ 8221: M132, // U+201d ” 8463: M10 // U+210f ℏ }, "Main-Regular": { 32: M7, // U+0020 33: M133, // U+0021 ! 34: M143, // U+0022 " 35: M220, // U+0023 # 36: M161, // U+0024 $ 37: M221, // U+0025 % 38: M136, // U+0026 & 39: M133, // U+0027 ' 40: M134, // U+0028 ( 41: M134, // U+0029 ) 42: M222, // U+002a * 43: M149, // U+002b + 44: [0.19444, 0.10556, 0, 0, 0.27778], // U+002c , 45: [0, 0.43056, 0, 0, 0.33333], // U+002d - 46: [0, 0.10556, 0, 0, 0.27778], // U+002e . 47: M141, // U+002f / 48: M135, // U+0030 0 49: M135, // U+0031 1 50: M135, // U+0032 2 51: M135, // U+0033 3 52: M135, // U+0034 4 53: M135, // U+0035 5 54: M135, // U+0036 6 55: M135, // U+0037 7 56: M135, // U+0038 8 57: M135, // U+0039 9 58: M150, // U+003a : 59: [0.19444, 0.43056, 0, 0, 0.27778], // U+003b ; 60: M43, // U+003c < 61: M27, // U+003d = 62: M43, // U+003e > 63: M226, // U+003f ? 64: M136, // U+0040 @ 65: M137, // U+0041 A 66: [0, 0.68333, 0, 0, 0.70834], // U+0042 B 67: M140, // U+0043 C 68: [0, 0.68333, 0, 0, 0.76389], // U+0044 D 69: M139, // U+0045 E 70: [0, 0.68333, 0, 0, 0.65278], // U+0046 F 71: [0, 0.68333, 0, 0, 0.78472], // U+0047 G 72: M137, // U+0048 H 73: [0, 0.68333, 0, 0, 0.36111], // U+0049 I 74: [0, 0.68333, 0, 0, 0.51389], // U+004a J 75: M138, // U+004b K 76: M154, // U+004c L 77: [0, 0.68333, 0, 0, 0.91667], // U+004d M 78: M137, // U+004e N 79: M138, // U+004f O 80: M139, // U+0050 P 81: [0.19444, 0.68333, 0, 0, 0.77778], // U+0051 Q 82: [0, 0.68333, 0, 0, 0.73611], // U+0052 R 83: [0, 0.68333, 0, 0, 0.55556], // U+0053 S 84: M140, // U+0054 T 85: M137, // U+0055 U 86: [0, 0.68333, 0.01389, 0, 0.75], // U+0056 V 87: [0, 0.68333, 0.01389, 0, 1.02778], // U+0057 W 88: M137, // U+0058 X 89: [0, 0.68333, 0.025, 0, 0.75], // U+0059 Y 90: [0, 0.68333, 0, 0, 0.61111], // U+005a Z 91: M142, // U+005b [ 92: M141, // U+005c \ 93: M142, // U+005d ] 94: M143, // U+005e ^ 95: [0.31, 0.12056, 0.02778, 0, 0.5], // U+005f _ 97: M146, // U+0061 a 98: M144, // U+0062 b 99: M145, // U+0063 c 100: M144, // U+0064 d 101: M145, // U+0065 e 102: [0, 0.69444, 0.07778, 0, 0.30556], // U+0066 f 103: [0.19444, 0.43056, 0.01389, 0, 0.5], // U+0067 g 104: M144, // U+0068 h 105: M151, // U+0069 i 106: [0.19444, 0.66786, 0, 0, 0.30556], // U+006a j 107: [0, 0.69444, 0, 0, 0.52778], // U+006b k 108: M133, // U+006c l 109: [0, 0.43056, 0, 0, 0.83334], // U+006d m 110: M148, // U+006e n 111: M146, // U+006f o 112: M147, // U+0070 p 113: [0.19444, 0.43056, 0, 0, 0.52778], // U+0071 q 114: [0, 0.43056, 0, 0, 0.39167], // U+0072 r 115: [0, 0.43056, 0, 0, 0.39445], // U+0073 s 116: [0, 0.61508, 0, 0, 0.38889], // U+0074 t 117: M148, // U+0075 u 118: [0, 0.43056, 0.01389, 0, 0.52778], // U+0076 v 119: [0, 0.43056, 0.01389, 0, 0.72222], // U+0077 w 120: [0, 0.43056, 0, 0, 0.52778], // U+0078 x 121: [0.19444, 0.43056, 0.01389, 0, 0.52778], // U+0079 y 122: M145, // U+007a z 123: M141, // U+007b { 124: M142, // U+007c | 125: M141, // U+007d } 126: [0.35, 0.31786, 0, 0, 0.5], // U+007e ~ 160: M7, // U+00a0 163: [0, 0.69444, 0, 0, 0.76909], // U+00a3 £ 167: M155, // U+00a7 § 168: M153, // U+00a8 ¨ 172: [0, 0.43056, 0, 0, 0.66667], // U+00ac ¬ 176: M152, // U+00b0 ° 177: M149, // U+00b1 ± 182: M160, // U+00b6 ¶ 184: M213, // U+00b8 ¸ 198: [0, 0.68333, 0, 0, 0.90278], // U+00c6 Æ 215: M149, // U+00d7 × 216: [0.04861, 0.73194, 0, 0, 0.77778], // U+00d8 Ø 223: M143, // U+00df ß 230: [0, 0.43056, 0, 0, 0.72222], // U+00e6 æ 247: M149, // U+00f7 ÷ 248: [0.09722, 0.52778, 0, 0, 0.5], // U+00f8 ø 305: M150, // U+0131 ı 338: [0, 0.68333, 0, 0, 1.01389], // U+0152 Œ 339: M165, // U+0153 œ 567: [0.19444, 0.43056, 0, 0, 0.30556], // U+0237 ȷ 710: M143, // U+02c6 ˆ 711: [0, 0.62847, 0, 0, 0.5], // U+02c7 ˇ 713: [0, 0.56778, 0, 0, 0.5], // U+02c9 ˉ 714: M143, // U+02ca ˊ 715: M143, // U+02cb ˋ 728: M143, // U+02d8 ˘ 729: M151, // U+02d9 ˙ 730: M152, // U+02da ˚ 732: M153, // U+02dc ˜ 733: M143, // U+02dd ˝ 915: M154, // U+0393 Γ 916: M162, // U+0394 Δ 920: M138, // U+0398 Θ 923: [0, 0.68333, 0, 0, 0.69445], // U+039b Λ 926: [0, 0.68333, 0, 0, 0.66667], // U+039e Ξ 928: M137, // U+03a0 Π 931: M140, // U+03a3 Σ 933: M138, // U+03a5 Υ 934: M140, // U+03a6 Φ 936: M138, // U+03a8 Ψ 937: M140, // U+03a9 Ω 8211: [0, 0.43056, 0.02778, 0, 0.5], // U+2013 – 8212: [0, 0.43056, 0.02778, 0, 1], // U+2014 — 8216: M133, // U+2018 ‘ 8217: M133, // U+2019 ’ 8220: M143, // U+201c “ 8221: M143, // U+201d ” 8224: M155, // U+2020 † 8225: M155, // U+2021 ‡ 8230: [0, 0.12, 0, 0, 1.172], // U+2026 … 8242: [0, 0.55556, 0, 0, 0.275], // U+2032 ′ 8407: [0, 0.71444, 0.15382, 0, 0.5], // U+20d7 ⃗ 8463: M10, // U+210f ℏ 8465: M156, // U+2111 ℑ 8467: [0, 0.69444, 0, 0.11111, 0.41667], // U+2113 ℓ 8472: [0.19444, 0.43056, 0, 0.11111, 0.63646], // U+2118 ℘ 8476: M156, // U+211c ℜ 8501: M170, // U+2135 ℵ 8592: M12, // U+2190 ← 8593: M157, // U+2191 ↑ 8594: M12, // U+2192 → 8595: M157, // U+2193 ↓ 8596: M12, // U+2194 ↔ 8597: M141, // U+2195 ↕ 8598: M158, // U+2196 ↖ 8599: M158, // U+2197 ↗ 8600: M158, // U+2198 ↘ 8601: M158, // U+2199 ↙ 8614: [0.011, 0.511, 0, 0, 1], // U+21a6 ↦ 8617: M159, // U+21a9 ↩ 8618: M159, // U+21aa ↪ 8636: M12, // U+21bc ↼ 8637: M12, // U+21bd ↽ 8640: M12, // U+21c0 ⇀ 8641: M12, // U+21c1 ⇁ 8652: [0.011, 0.671, 0, 0, 1], // U+21cc ⇌ 8656: M12, // U+21d0 ⇐ 8657: M160, // U+21d1 ⇑ 8658: M12, // U+21d2 ⇒ 8659: M160, // U+21d3 ⇓ 8660: M12, // U+21d4 ⇔ 8661: [0.25, 0.75, 0, 0, 0.61111], // U+21d5 ⇕ 8704: M144, // U+2200 ∀ 8706: [0, 0.69444, 0.05556, 0.08334, 0.5309], // U+2202 ∂ 8707: M144, // U+2203 ∃ 8709: M161, // U+2205 ∅ 8711: M162, // U+2207 ∇ 8712: M163, // U+2208 ∈ 8715: M163, // U+220b ∋ 8722: M149, // U+2212 − 8723: M149, // U+2213 ∓ 8725: M141, // U+2215 ∕ 8726: M141, // U+2216 ∖ 8727: M171, // U+2217 ∗ 8728: M164, // U+2218 ∘ 8729: M164, // U+2219 ∙ 8730: [0.2, 0.8, 0, 0, 0.83334], // U+221a √ 8733: M165, // U+221d ∝ 8734: M17, // U+221e ∞ 8736: M25, // U+2220 ∠ 8739: M142, // U+2223 ∣ 8741: M141, // U+2225 ∥ 8743: M166, // U+2227 ∧ 8744: M166, // U+2228 ∨ 8745: M166, // U+2229 ∩ 8746: M166, // U+222a ∪ 8747: [0.19444, 0.69444, 0.11111, 0, 0.41667], // U+222b ∫ 8764: M27, // U+223c ∼ 8768: [0.19444, 0.69444, 0, 0, 0.27778], // U+2240 ≀ 8771: M167, // U+2243 ≃ 8773: [-0.022, 0.589, 0, 0, 1], // U+2245 ≅ 8776: M168, // U+2248 ≈ 8781: M167, // U+224d ≍ 8784: [-0.133, 0.67, 0, 0, 0.778], // U+2250 ≐ 8801: M167, // U+2261 ≡ 8804: M37, // U+2264 ≤ 8805: M37, // U+2265 ≥ 8810: M169, // U+226a ≪ 8811: M169, // U+226b ≫ 8826: M43, // U+227a ≺ 8827: M43, // U+227b ≻ 8834: M43, // U+2282 ⊂ 8835: M43, // U+2283 ⊃ 8838: M37, // U+2286 ⊆ 8839: M37, // U+2287 ⊇ 8846: M166, // U+228e ⊎ 8849: M37, // U+2291 ⊑ 8850: M37, // U+2292 ⊒ 8851: M166, // U+2293 ⊓ 8852: M166, // U+2294 ⊔ 8853: M149, // U+2295 ⊕ 8854: M149, // U+2296 ⊖ 8855: M149, // U+2297 ⊗ 8856: M149, // U+2298 ⊘ 8857: M149, // U+2299 ⊙ 8866: M170, // U+22a2 ⊢ 8867: M170, // U+22a3 ⊣ 8868: M136, // U+22a4 ⊤ 8869: M136, // U+22a5 ⊥ 8872: [0.249, 0.75, 0, 0, 0.867], // U+22a8 ⊨ 8900: M164, // U+22c4 ⋄ 8901: [-0.05555, 0.44445, 0, 0, 0.27778], // U+22c5 ⋅ 8902: M171, // U+22c6 ⋆ 8904: [5e-3, 0.505, 0, 0, 0.9], // U+22c8 ⋈ 8942: [0.03, 0.9, 0, 0, 0.278], // U+22ee ⋮ 8943: [-0.19, 0.31, 0, 0, 1.172], // U+22ef ⋯ 8945: [-0.1, 0.82, 0, 0, 1.282], // U+22f1 ⋱ 8968: M172, // U+2308 ⌈ 8969: M172, // U+2309 ⌉ 8970: M172, // U+230a ⌊ 8971: M172, // U+230b ⌋ 8994: M173, // U+2322 ⌢ 8995: M173, // U+2323 ⌣ 9136: M174, // U+23b0 ⎰ 9137: M174, // U+23b1 ⎱ 9651: M175, // U+25b3 △ 9657: M171, // U+25b9 ▹ 9661: M175, // U+25bd ▽ 9667: M171, // U+25c3 ◃ 9711: M158, // U+25ef ◯ 9824: M176, // U+2660 ♠ 9825: M176, // U+2661 ♡ 9826: M176, // U+2662 ♢ 9827: M176, // U+2663 ♣ 9837: [0, 0.75, 0, 0, 0.38889], // U+266d ♭ 9838: M177, // U+266e ♮ 9839: M177, // U+266f ♯ 10216: M134, // U+27e8 ⟨ 10217: M134, // U+27e9 ⟩ 10222: M174, // U+27ee ⟮ 10223: M174, // U+27ef ⟯ 10229: [0.011, 0.511, 0, 0, 1.609], // U+27f5 ⟵ 10230: M178, // U+27f6 ⟶ 10231: [0.011, 0.511, 0, 0, 1.859], // U+27f7 ⟷ 10232: [0.024, 0.525, 0, 0, 1.609], // U+27f8 ⟸ 10233: [0.024, 0.525, 0, 0, 1.638], // U+27f9 ⟹ 10234: [0.024, 0.525, 0, 0, 1.858], // U+27fa ⟺ 10236: M178, // U+27fc ⟼ 10815: M137, // U+2a3f ⨿ 10927: M37, // U+2aaf ⪯ 10928: M37, // U+2ab0 ⪰ 57376: M179 // U+e020  }, "Math-BoldItalic": { 32: M7, // U+0020 48: M180, // U+0030 0 49: M180, // U+0031 1 50: M180, // U+0032 2 51: M181, // U+0033 3 52: M181, // U+0034 4 53: M181, // U+0035 5 54: M68, // U+0036 6 55: M181, // U+0037 7 56: M68, // U+0038 8 57: M181, // U+0039 9 65: M72, // U+0041 A 66: [0, 0.68611, 0.04835, 0, 0.8664], // U+0042 B 67: [0, 0.68611, 0.06979, 0, 0.81694], // U+0043 C 68: [0, 0.68611, 0.03194, 0, 0.93812], // U+0044 D 69: [0, 0.68611, 0.05451, 0, 0.81007], // U+0045 E 70: [0, 0.68611, 0.15972, 0, 0.68889], // U+0046 F 71: [0, 0.68611, 0, 0, 0.88673], // U+0047 G 72: M185, // U+0048 H 73: [0, 0.68611, 0.07778, 0, 0.51111], // U+0049 I 74: [0, 0.68611, 0.10069, 0, 0.63125], // U+004a J 75: [0, 0.68611, 0.06979, 0, 0.97118], // U+004b K 76: M182, // U+004c L 77: [0, 0.68611, 0.11424, 0, 1.14201], // U+004d M 78: [0, 0.68611, 0.11424, 0, 0.95034], // U+004e N 79: [0, 0.68611, 0.03194, 0, 0.83666], // U+004f O 80: [0, 0.68611, 0.15972, 0, 0.72309], // U+0050 P 81: [0.19444, 0.68611, 0, 0, 0.86861], // U+0051 Q 82: [0, 0.68611, 421e-5, 0, 0.87235], // U+0052 R 83: [0, 0.68611, 0.05382, 0, 0.69271], // U+0053 S 84: [0, 0.68611, 0.15972, 0, 0.63663], // U+0054 T 85: [0, 0.68611, 0.11424, 0, 0.80027], // U+0055 U 86: [0, 0.68611, 0.25555, 0, 0.67778], // U+0056 V 87: [0, 0.68611, 0.15972, 0, 1.09305], // U+0057 W 88: [0, 0.68611, 0.07778, 0, 0.94722], // U+0058 X 89: [0, 0.68611, 0.25555, 0, 0.67458], // U+0059 Y 90: [0, 0.68611, 0.06979, 0, 0.77257], // U+005a Z 97: [0, 0.44444, 0, 0, 0.63287], // U+0061 a 98: [0, 0.69444, 0, 0, 0.52083], // U+0062 b 99: [0, 0.44444, 0, 0, 0.51342], // U+0063 c 100: [0, 0.69444, 0, 0, 0.60972], // U+0064 d 101: [0, 0.44444, 0, 0, 0.55361], // U+0065 e 102: [0.19444, 0.69444, 0.11042, 0, 0.56806], // U+0066 f 103: [0.19444, 0.44444, 0.03704, 0, 0.5449], // U+0067 g 104: M183, // U+0068 h 105: [0, 0.69326, 0, 0, 0.4048], // U+0069 i 106: [0.19444, 0.69326, 0.0622, 0, 0.47083], // U+006a j 107: [0, 0.69444, 0.01852, 0, 0.6037], // U+006b k 108: [0, 0.69444, 88e-4, 0, 0.34815], // U+006c l 109: [0, 0.44444, 0, 0, 1.0324], // U+006d m 110: [0, 0.44444, 0, 0, 0.71296], // U+006e n 111: M187, // U+006f o 112: [0.19444, 0.44444, 0, 0, 0.60092], // U+0070 p 113: [0.19444, 0.44444, 0.03704, 0, 0.54213], // U+0071 q 114: [0, 0.44444, 0.03194, 0, 0.5287], // U+0072 r 115: [0, 0.44444, 0, 0, 0.53125], // U+0073 s 116: [0, 0.63492, 0, 0, 0.41528], // U+0074 t 117: [0, 0.44444, 0, 0, 0.68102], // U+0075 u 118: [0, 0.44444, 0.03704, 0, 0.56666], // U+0076 v 119: [0, 0.44444, 0.02778, 0, 0.83148], // U+0077 w 120: [0, 0.44444, 0, 0, 0.65903], // U+0078 x 121: [0.19444, 0.44444, 0.03704, 0, 0.59028], // U+0079 y 122: [0, 0.44444, 0.04213, 0, 0.55509], // U+007a z 160: M7, // U+00a0 915: [0, 0.68611, 0.15972, 0, 0.65694], // U+0393 Γ 916: M94, // U+0394 Δ 920: [0, 0.68611, 0.03194, 0, 0.86722], // U+0398 Θ 923: M184, // U+039b Λ 926: [0, 0.68611, 0.07458, 0, 0.84125], // U+039e Ξ 928: M185, // U+03a0 Π 931: [0, 0.68611, 0.05451, 0, 0.88507], // U+03a3 Σ 933: [0, 0.68611, 0.15972, 0, 0.67083], // U+03a5 Υ 934: M186, // U+03a6 Φ 936: [0, 0.68611, 0.11653, 0, 0.71402], // U+03a8 Ψ 937: [0, 0.68611, 0.04835, 0, 0.8789], // U+03a9 Ω 945: [0, 0.44444, 0, 0, 0.76064], // U+03b1 α 946: [0.19444, 0.69444, 0.03403, 0, 0.65972], // U+03b2 β 947: [0.19444, 0.44444, 0.06389, 0, 0.59003], // U+03b3 γ 948: [0, 0.69444, 0.03819, 0, 0.52222], // U+03b4 δ 949: [0, 0.44444, 0, 0, 0.52882], // U+03b5 ε 950: [0.19444, 0.69444, 0.06215, 0, 0.50833], // U+03b6 ζ 951: [0.19444, 0.44444, 0.03704, 0, 0.6], // U+03b7 η 952: [0, 0.69444, 0.03194, 0, 0.5618], // U+03b8 θ 953: [0, 0.44444, 0, 0, 0.41204], // U+03b9 ι 954: [0, 0.44444, 0, 0, 0.66759], // U+03ba κ 955: [0, 0.69444, 0, 0, 0.67083], // U+03bb λ 956: [0.19444, 0.44444, 0, 0, 0.70787], // U+03bc μ 957: [0, 0.44444, 0.06898, 0, 0.57685], // U+03bd ν 958: [0.19444, 0.69444, 0.03021, 0, 0.50833], // U+03be ξ 959: M187, // U+03bf ο 960: [0, 0.44444, 0.03704, 0, 0.68241], // U+03c0 π 961: M188, // U+03c1 ρ 962: [0.09722, 0.44444, 0.07917, 0, 0.42361], // U+03c2 ς 963: [0, 0.44444, 0.03704, 0, 0.68588], // U+03c3 σ 964: [0, 0.44444, 0.13472, 0, 0.52083], // U+03c4 τ 965: [0, 0.44444, 0.03704, 0, 0.63055], // U+03c5 υ 966: [0.19444, 0.44444, 0, 0, 0.74722], // U+03c6 φ 967: [0.19444, 0.44444, 0, 0, 0.71805], // U+03c7 χ 968: [0.19444, 0.69444, 0.03704, 0, 0.75833], // U+03c8 ψ 969: [0, 0.44444, 0.03704, 0, 0.71782], // U+03c9 ω 977: [0, 0.69444, 0, 0, 0.69155], // U+03d1 ϑ 981: [0.19444, 0.69444, 0, 0, 0.7125], // U+03d5 ϕ 982: [0, 0.44444, 0.03194, 0, 0.975], // U+03d6 ϖ 1009: M188, // U+03f1 ϱ 1013: [0, 0.44444, 0, 0, 0.48333], // U+03f5 ϵ 57649: [0, 0.44444, 0, 0, 0.39352], // U+e131  57911: [0.19444, 0.44444, 0, 0, 0.43889] // U+e237  }, "Math-Italic": { 32: M7, // U+0020 48: M146, // U+0030 0 49: M146, // U+0031 1 50: M146, // U+0032 2 51: M189, // U+0033 3 52: M189, // U+0034 4 53: M189, // U+0035 5 54: M135, // U+0036 6 55: M189, // U+0037 7 56: M135, // U+0038 8 57: M189, // U+0039 9 65: [0, 0.68333, 0, 0.13889, 0.75], // U+0041 A 66: [0, 0.68333, 0.05017, 0.08334, 0.75851], // U+0042 B 67: [0, 0.68333, 0.07153, 0.08334, 0.71472], // U+0043 C 68: [0, 0.68333, 0.02778, 0.05556, 0.82792], // U+0044 D 69: [0, 0.68333, 0.05764, 0.08334, 0.7382], // U+0045 E 70: [0, 0.68333, 0.13889, 0.08334, 0.64306], // U+0046 F 71: [0, 0.68333, 0, 0.08334, 0.78625], // U+0047 G 72: M191, // U+0048 H 73: [0, 0.68333, 0.07847, 0.11111, 0.43958], // U+0049 I 74: [0, 0.68333, 0.09618, 0.16667, 0.55451], // U+004a J 75: [0, 0.68333, 0.07153, 0.05556, 0.84931], // U+004b K 76: [0, 0.68333, 0, 0.02778, 0.68056], // U+004c L 77: [0, 0.68333, 0.10903, 0.08334, 0.97014], // U+004d M 78: [0, 0.68333, 0.10903, 0.08334, 0.80347], // U+004e N 79: M190, // U+004f O 80: [0, 0.68333, 0.13889, 0.08334, 0.64201], // U+0050 P 81: [0.19444, 0.68333, 0, 0.08334, 0.79056], // U+0051 Q 82: [0, 0.68333, 773e-5, 0.08334, 0.75929], // U+0052 R 83: [0, 0.68333, 0.05764, 0.08334, 0.6132], // U+0053 S 84: [0, 0.68333, 0.13889, 0.08334, 0.58438], // U+0054 T 85: [0, 0.68333, 0.10903, 0.02778, 0.68278], // U+0055 U 86: [0, 0.68333, 0.22222, 0, 0.58333], // U+0056 V 87: [0, 0.68333, 0.13889, 0, 0.94445], // U+0057 W 88: [0, 0.68333, 0.07847, 0.08334, 0.82847], // U+0058 X 89: [0, 0.68333, 0.22222, 0, 0.58056], // U+0059 Y 90: [0, 0.68333, 0.07153, 0.08334, 0.68264], // U+005a Z 97: [0, 0.43056, 0, 0, 0.52859], // U+0061 a 98: [0, 0.69444, 0, 0, 0.42917], // U+0062 b 99: [0, 0.43056, 0, 0.05556, 0.43276], // U+0063 c 100: [0, 0.69444, 0, 0.16667, 0.52049], // U+0064 d 101: [0, 0.43056, 0, 0.05556, 0.46563], // U+0065 e 102: [0.19444, 0.69444, 0.10764, 0.16667, 0.48959], // U+0066 f 103: [0.19444, 0.43056, 0.03588, 0.02778, 0.47697], // U+0067 g 104: [0, 0.69444, 0, 0, 0.57616], // U+0068 h 105: [0, 0.65952, 0, 0, 0.34451], // U+0069 i 106: [0.19444, 0.65952, 0.05724, 0, 0.41181], // U+006a j 107: [0, 0.69444, 0.03148, 0, 0.5206], // U+006b k 108: [0, 0.69444, 0.01968, 0.08334, 0.29838], // U+006c l 109: [0, 0.43056, 0, 0, 0.87801], // U+006d m 110: [0, 0.43056, 0, 0, 0.60023], // U+006e n 111: M192, // U+006f o 112: [0.19444, 0.43056, 0, 0.08334, 0.50313], // U+0070 p 113: [0.19444, 0.43056, 0.03588, 0.08334, 0.44641], // U+0071 q 114: [0, 0.43056, 0.02778, 0.05556, 0.45116], // U+0072 r 115: [0, 0.43056, 0, 0.05556, 0.46875], // U+0073 s 116: [0, 0.61508, 0, 0.08334, 0.36111], // U+0074 t 117: [0, 0.43056, 0, 0.02778, 0.57246], // U+0075 u 118: [0, 0.43056, 0.03588, 0.02778, 0.48472], // U+0076 v 119: [0, 0.43056, 0.02691, 0.08334, 0.71592], // U+0077 w 120: [0, 0.43056, 0, 0.02778, 0.57153], // U+0078 x 121: [0.19444, 0.43056, 0.03588, 0.05556, 0.49028], // U+0079 y 122: [0, 0.43056, 0.04398, 0.05556, 0.46505], // U+007a z 160: M7, // U+00a0 915: [0, 0.68333, 0.13889, 0.08334, 0.61528], // U+0393 Γ 916: [0, 0.68333, 0, 0.16667, 0.83334], // U+0394 Δ 920: M190, // U+0398 Θ 923: [0, 0.68333, 0, 0.16667, 0.69445], // U+039b Λ 926: [0, 0.68333, 0.07569, 0.08334, 0.74236], // U+039e Ξ 928: M191, // U+03a0 Π 931: [0, 0.68333, 0.05764, 0.08334, 0.77986], // U+03a3 Σ 933: [0, 0.68333, 0.13889, 0.05556, 0.58333], // U+03a5 Υ 934: [0, 0.68333, 0, 0.08334, 0.66667], // U+03a6 Φ 936: [0, 0.68333, 0.11, 0.05556, 0.61222], // U+03a8 Ψ 937: [0, 0.68333, 0.05017, 0.08334, 0.7724], // U+03a9 Ω 945: [0, 0.43056, 37e-4, 0.02778, 0.6397], // U+03b1 α 946: [0.19444, 0.69444, 0.05278, 0.08334, 0.56563], // U+03b2 β 947: [0.19444, 0.43056, 0.05556, 0, 0.51773], // U+03b3 γ 948: [0, 0.69444, 0.03785, 0.05556, 0.44444], // U+03b4 δ 949: [0, 0.43056, 0, 0.08334, 0.46632], // U+03b5 ε 950: [0.19444, 0.69444, 0.07378, 0.08334, 0.4375], // U+03b6 ζ 951: [0.19444, 0.43056, 0.03588, 0.05556, 0.49653], // U+03b7 η 952: [0, 0.69444, 0.02778, 0.08334, 0.46944], // U+03b8 θ 953: [0, 0.43056, 0, 0.05556, 0.35394], // U+03b9 ι 954: [0, 0.43056, 0, 0, 0.57616], // U+03ba κ 955: [0, 0.69444, 0, 0, 0.58334], // U+03bb λ 956: [0.19444, 0.43056, 0, 0.02778, 0.60255], // U+03bc μ 957: [0, 0.43056, 0.06366, 0.02778, 0.49398], // U+03bd ν 958: [0.19444, 0.69444, 0.04601, 0.11111, 0.4375], // U+03be ξ 959: M192, // U+03bf ο 960: [0, 0.43056, 0.03588, 0, 0.57003], // U+03c0 π 961: M193, // U+03c1 ρ 962: [0.09722, 0.43056, 0.07986, 0.08334, 0.36285], // U+03c2 ς 963: [0, 0.43056, 0.03588, 0, 0.57141], // U+03c3 σ 964: [0, 0.43056, 0.1132, 0.02778, 0.43715], // U+03c4 τ 965: [0, 0.43056, 0.03588, 0.02778, 0.54028], // U+03c5 υ 966: [0.19444, 0.43056, 0, 0.08334, 0.65417], // U+03c6 φ 967: [0.19444, 0.43056, 0, 0.05556, 0.62569], // U+03c7 χ 968: [0.19444, 0.69444, 0.03588, 0.11111, 0.65139], // U+03c8 ψ 969: [0, 0.43056, 0.03588, 0, 0.62245], // U+03c9 ω 977: [0, 0.69444, 0, 0.08334, 0.59144], // U+03d1 ϑ 981: [0.19444, 0.69444, 0, 0.08334, 0.59583], // U+03d5 ϕ 982: [0, 0.43056, 0.02778, 0, 0.82813], // U+03d6 ϖ 1009: M193, // U+03f1 ϱ 1013: [0, 0.43056, 0, 0.05556, 0.4059], // U+03f5 ϵ 57649: [0, 0.43056, 0, 0.02778, 0.32246], // U+e131  57911: [0.19444, 0.43056, 0, 0.08334, 0.38403] // U+e237  }, "SansSerif-Bold": { 32: M7, // U+0020 33: [0, 0.69444, 0, 0, 0.36667], // U+0021 ! 34: M210, // U+0022 " 35: [0.19444, 0.69444, 0, 0, 0.91667], // U+0023 # 36: [0.05556, 0.75, 0, 0, 0.55], // U+0024 $ 37: [0.05556, 0.75, 0, 0, 1.02912], // U+0025 % 38: [0, 0.69444, 0, 0, 0.83056], // U+0026 & 39: M206, // U+0027 ' 40: M194, // U+0028 ( 41: M194, // U+0029 ) 42: [0, 0.75, 0, 0, 0.55], // U+002a * 43: [0.11667, 0.61667, 0, 0, 0.85556], // U+002b + 44: [0.10556, 0.13056, 0, 0, 0.30556], // U+002c , 45: [0, 0.45833, 0, 0, 0.36667], // U+002d - 46: [0, 0.13056, 0, 0, 0.30556], // U+002e . 47: [0.25, 0.75, 0, 0, 0.55], // U+002f / 48: M195, // U+0030 0 49: M195, // U+0031 1 50: M195, // U+0032 2 51: M195, // U+0033 3 52: M195, // U+0034 4 53: M195, // U+0035 5 54: M195, // U+0036 6 55: M195, // U+0037 7 56: M195, // U+0038 8 57: M195, // U+0039 9 58: [0, 0.45833, 0, 0, 0.30556], // U+003a : 59: [0.10556, 0.45833, 0, 0, 0.30556], // U+003b ; 61: [-0.09375, 0.40625, 0, 0, 0.85556], // U+003d = 63: M198, // U+003f ? 64: M196, // U+0040 @ 65: M196, // U+0041 A 66: M196, // U+0042 B 67: M199, // U+0043 C 68: M197, // U+0044 D 69: [0, 0.69444, 0, 0, 0.64167], // U+0045 E 70: M170, // U+0046 F 71: M196, // U+0047 G 72: M197, // U+0048 H 73: [0, 0.69444, 0, 0, 0.33056], // U+0049 I 74: M198, // U+004a J 75: M200, // U+004b K 76: M207, // U+004c L 77: [0, 0.69444, 0, 0, 0.97778], // U+004d M 78: M197, // U+004e N 79: M197, // U+004f O 80: M199, // U+0050 P 81: [0.10556, 0.69444, 0, 0, 0.79445], // U+0051 Q 82: M199, // U+0052 R 83: M170, // U+0053 S 84: M196, // U+0054 T 85: M200, // U+0055 U 86: [0, 0.69444, 0.01528, 0, 0.73334], // U+0056 V 87: [0, 0.69444, 0.01528, 0, 1.03889], // U+0057 W 88: M196, // U+0058 X 89: [0, 0.69444, 0.0275, 0, 0.73334], // U+0059 Y 90: M208, // U+005a Z 91: M201, // U+005b [ 93: M201, // U+005d ] 94: M195, // U+005e ^ 95: [0.35, 0.10833, 0.03056, 0, 0.55], // U+005f _ 97: [0, 0.45833, 0, 0, 0.525], // U+0061 a 98: M202, // U+0062 b 99: [0, 0.45833, 0, 0, 0.48889], // U+0063 c 100: M202, // U+0064 d 101: [0, 0.45833, 0, 0, 0.51111], // U+0065 e 102: [0, 0.69444, 0.07639, 0, 0.33611], // U+0066 f 103: [0.19444, 0.45833, 0.01528, 0, 0.55], // U+0067 g 104: M202, // U+0068 h 105: M203, // U+0069 i 106: [0.19444, 0.69444, 0, 0, 0.28611], // U+006a j 107: [0, 0.69444, 0, 0, 0.53056], // U+006b k 108: M203, // U+006c l 109: [0, 0.45833, 0, 0, 0.86667], // U+006d m 110: M205, // U+006e n 111: [0, 0.45833, 0, 0, 0.55], // U+006f o 112: M204, // U+0070 p 113: M204, // U+0071 q 114: [0, 0.45833, 0.01528, 0, 0.37222], // U+0072 r 115: [0, 0.45833, 0, 0, 0.42167], // U+0073 s 116: [0, 0.58929, 0, 0, 0.40417], // U+0074 t 117: M205, // U+0075 u 118: [0, 0.45833, 0.01528, 0, 0.5], // U+0076 v 119: [0, 0.45833, 0.01528, 0, 0.74445], // U+0077 w 120: [0, 0.45833, 0, 0, 0.5], // U+0078 x 121: [0.19444, 0.45833, 0.01528, 0, 0.5], // U+0079 y 122: [0, 0.45833, 0, 0, 0.47639], // U+007a z 126: [0.35, 0.34444, 0, 0, 0.55], // U+007e ~ 160: M7, // U+00a0 168: M195, // U+00a8 ¨ 176: M196, // U+00b0 ° 180: M195, // U+00b4 ´ 184: [0.17014, 0, 0, 0, 0.48889], // U+00b8 ¸ 305: [0, 0.45833, 0, 0, 0.25556], // U+0131 ı 567: [0.19444, 0.45833, 0, 0, 0.28611], // U+0237 ȷ 710: M195, // U+02c6 ˆ 711: [0, 0.63542, 0, 0, 0.55], // U+02c7 ˇ 713: [0, 0.63778, 0, 0, 0.55], // U+02c9 ˉ 728: M195, // U+02d8 ˘ 729: M206, // U+02d9 ˙ 730: M196, // U+02da ˚ 732: M195, // U+02dc ˜ 733: M195, // U+02dd ˝ 915: M207, // U+0393 Γ 916: [0, 0.69444, 0, 0, 0.91667], // U+0394 Δ 920: M209, // U+0398 Θ 923: M208, // U+039b Λ 926: M196, // U+039e Ξ 928: M197, // U+03a0 Π 931: M197, // U+03a3 Σ 933: M209, // U+03a5 Υ 934: M197, // U+03a6 Φ 936: M209, // U+03a8 Ψ 937: M197, // U+03a9 Ω 8211: [0, 0.45833, 0.03056, 0, 0.55], // U+2013 – 8212: [0, 0.45833, 0.03056, 0, 1.10001], // U+2014 — 8216: M206, // U+2018 ‘ 8217: M206, // U+2019 ’ 8220: M210, // U+201c “ 8221: M210 // U+201d ” }, "SansSerif-Italic": { 32: M7, // U+0020 33: [0, 0.69444, 0.05733, 0, 0.31945], // U+0021 ! 34: M219, // U+0022 " 35: [0.19444, 0.69444, 0.05087, 0, 0.83334], // U+0023 # 36: [0.05556, 0.75, 0.11156, 0, 0.5], // U+0024 $ 37: [0.05556, 0.75, 0.03126, 0, 0.83334], // U+0025 % 38: [0, 0.69444, 0.03058, 0, 0.75834], // U+0026 & 39: M218, // U+0027 ' 40: [0.25, 0.75, 0.13164, 0, 0.38889], // U+0028 ( 41: [0.25, 0.75, 0.02536, 0, 0.38889], // U+0029 ) 42: [0, 0.75, 0.11775, 0, 0.5], // U+002a * 43: [0.08333, 0.58333, 0.02536, 0, 0.77778], // U+002b + 44: M223, // U+002c , 45: [0, 0.44444, 0.01946, 0, 0.33333], // U+002d - 46: M224, // U+002e . 47: [0.25, 0.75, 0.13164, 0, 0.5], // U+002f / 48: M211, // U+0030 0 49: M211, // U+0031 1 50: M211, // U+0032 2 51: M211, // U+0033 3 52: M211, // U+0034 4 53: M211, // U+0035 5 54: M211, // U+0036 6 55: M211, // U+0037 7 56: M211, // U+0038 8 57: M211, // U+0039 9 58: [0, 0.44444, 0.02502, 0, 0.27778], // U+003a : 59: [0.125, 0.44444, 0.02502, 0, 0.27778], // U+003b ; 61: [-0.13, 0.37, 0.05087, 0, 0.77778], // U+003d = 63: [0, 0.69444, 0.11809, 0, 0.47222], // U+003f ? 64: [0, 0.69444, 0.07555, 0, 0.66667], // U+0040 @ 65: M227, // U+0041 A 66: [0, 0.69444, 0.08293, 0, 0.66667], // U+0042 B 67: [0, 0.69444, 0.11983, 0, 0.63889], // U+0043 C 68: [0, 0.69444, 0.07555, 0, 0.72223], // U+0044 D 69: [0, 0.69444, 0.11983, 0, 0.59722], // U+0045 E 70: [0, 0.69444, 0.13372, 0, 0.56945], // U+0046 F 71: [0, 0.69444, 0.11983, 0, 0.66667], // U+0047 G 72: M212, // U+0048 H 73: [0, 0.69444, 0.13372, 0, 0.27778], // U+0049 I 74: [0, 0.69444, 0.08094, 0, 0.47222], // U+004a J 75: [0, 0.69444, 0.11983, 0, 0.69445], // U+004b K 76: M229, // U+004c L 77: [0, 0.69444, 0.08094, 0, 0.875], // U+004d M 78: M212, // U+004e N 79: [0, 0.69444, 0.07555, 0, 0.73611], // U+004f O 80: [0, 0.69444, 0.08293, 0, 0.63889], // U+0050 P 81: [0.125, 0.69444, 0.07555, 0, 0.73611], // U+0051 Q 82: [0, 0.69444, 0.08293, 0, 0.64584], // U+0052 R 83: [0, 0.69444, 0.09205, 0, 0.55556], // U+0053 S 84: [0, 0.69444, 0.13372, 0, 0.68056], // U+0054 T 85: [0, 0.69444, 0.08094, 0, 0.6875], // U+0055 U 86: [0, 0.69444, 0.1615, 0, 0.66667], // U+0056 V 87: [0, 0.69444, 0.1615, 0, 0.94445], // U+0057 W 88: [0, 0.69444, 0.13372, 0, 0.66667], // U+0058 X 89: [0, 0.69444, 0.17261, 0, 0.66667], // U+0059 Y 90: [0, 0.69444, 0.11983, 0, 0.61111], // U+005a Z 91: [0.25, 0.75, 0.15942, 0, 0.28889], // U+005b [ 93: [0.25, 0.75, 0.08719, 0, 0.28889], // U+005d ] 94: M214, // U+005e ^ 95: [0.35, 0.09444, 0.08616, 0, 0.5], // U+005f _ 97: [0, 0.44444, 981e-5, 0, 0.48056], // U+0061 a 98: [0, 0.69444, 0.03057, 0, 0.51667], // U+0062 b 99: [0, 0.44444, 0.08336, 0, 0.44445], // U+0063 c 100: [0, 0.69444, 0.09483, 0, 0.51667], // U+0064 d 101: [0, 0.44444, 0.06778, 0, 0.44445], // U+0065 e 102: [0, 0.69444, 0.21705, 0, 0.30556], // U+0066 f 103: [0.19444, 0.44444, 0.10836, 0, 0.5], // U+0067 g 104: [0, 0.69444, 0.01778, 0, 0.51667], // U+0068 h 105: [0, 0.67937, 0.09718, 0, 0.23889], // U+0069 i 106: [0.19444, 0.67937, 0.09162, 0, 0.26667], // U+006a j 107: [0, 0.69444, 0.08336, 0, 0.48889], // U+006b k 108: [0, 0.69444, 0.09483, 0, 0.23889], // U+006c l 109: [0, 0.44444, 0.01778, 0, 0.79445], // U+006d m 110: [0, 0.44444, 0.01778, 0, 0.51667], // U+006e n 111: [0, 0.44444, 0.06613, 0, 0.5], // U+006f o 112: [0.19444, 0.44444, 0.0389, 0, 0.51667], // U+0070 p 113: [0.19444, 0.44444, 0.04169, 0, 0.51667], // U+0071 q 114: [0, 0.44444, 0.10836, 0, 0.34167], // U+0072 r 115: [0, 0.44444, 0.0778, 0, 0.38333], // U+0073 s 116: [0, 0.57143, 0.07225, 0, 0.36111], // U+0074 t 117: [0, 0.44444, 0.04169, 0, 0.51667], // U+0075 u 118: [0, 0.44444, 0.10836, 0, 0.46111], // U+0076 v 119: [0, 0.44444, 0.10836, 0, 0.68334], // U+0077 w 120: [0, 0.44444, 0.09169, 0, 0.46111], // U+0078 x 121: [0.19444, 0.44444, 0.10836, 0, 0.46111], // U+0079 y 122: [0, 0.44444, 0.08752, 0, 0.43472], // U+007a z 126: [0.35, 0.32659, 0.08826, 0, 0.5], // U+007e ~ 160: M7, // U+00a0 168: [0, 0.67937, 0.06385, 0, 0.5], // U+00a8 ¨ 176: M215, // U+00b0 ° 184: M213, // U+00b8 ¸ 305: [0, 0.44444, 0.04169, 0, 0.23889], // U+0131 ı 567: [0.19444, 0.44444, 0.04169, 0, 0.26667], // U+0237 ȷ 710: M214, // U+02c6 ˆ 711: [0, 0.63194, 0.08432, 0, 0.5], // U+02c7 ˇ 713: [0, 0.60889, 0.08776, 0, 0.5], // U+02c9 ˉ 714: M216, // U+02ca ˊ 715: M143, // U+02cb ˋ 728: [0, 0.69444, 0.09483, 0, 0.5], // U+02d8 ˘ 729: [0, 0.67937, 0.07774, 0, 0.27778], // U+02d9 ˙ 730: M215, // U+02da ˚ 732: [0, 0.67659, 0.08826, 0, 0.5], // U+02dc ˜ 733: M216, // U+02dd ˝ 915: [0, 0.69444, 0.13372, 0, 0.54167], // U+0393 Γ 916: M237, // U+0394 Δ 920: [0, 0.69444, 0.07555, 0, 0.77778], // U+0398 Θ 923: M170, // U+039b Λ 926: [0, 0.69444, 0.12816, 0, 0.66667], // U+039e Ξ 928: M212, // U+03a0 Π 931: [0, 0.69444, 0.11983, 0, 0.72222], // U+03a3 Σ 933: M217, // U+03a5 Υ 934: [0, 0.69444, 0.04603, 0, 0.72222], // U+03a6 Φ 936: M217, // U+03a8 Ψ 937: [0, 0.69444, 0.08293, 0, 0.72222], // U+03a9 Ω 8211: [0, 0.44444, 0.08616, 0, 0.5], // U+2013 – 8212: [0, 0.44444, 0.08616, 0, 1], // U+2014 — 8216: M218, // U+2018 ‘ 8217: M218, // U+2019 ’ 8220: [0, 0.69444, 0.14205, 0, 0.5], // U+201c “ 8221: M219 // U+201d ” }, "SansSerif-Regular": { 32: M7, // U+0020 33: [0, 0.69444, 0, 0, 0.31945], // U+0021 ! 34: M143, // U+0022 " 35: M220, // U+0023 # 36: M161, // U+0024 $ 37: M221, // U+0025 % 38: [0, 0.69444, 0, 0, 0.75834], // U+0026 & 39: M133, // U+0027 ' 40: M134, // U+0028 ( 41: M134, // U+0029 ) 42: M222, // U+002a * 43: M149, // U+002b + 44: M223, // U+002c , 45: [0, 0.44444, 0, 0, 0.33333], // U+002d - 46: M224, // U+002e . 47: M141, // U+002f / 48: M225, // U+0030 0 49: M225, // U+0031 1 50: M225, // U+0032 2 51: M225, // U+0033 3 52: M225, // U+0034 4 53: M225, // U+0035 5 54: M225, // U+0036 6 55: M225, // U+0037 7 56: M225, // U+0038 8 57: M225, // U+0039 9 58: [0, 0.44444, 0, 0, 0.27778], // U+003a : 59: [0.125, 0.44444, 0, 0, 0.27778], // U+003b ; 61: [-0.13, 0.37, 0, 0, 0.77778], // U+003d = 63: M226, // U+003f ? 64: M227, // U+0040 @ 65: M227, // U+0041 A 66: M227, // U+0042 B 67: M75, // U+0043 C 68: [0, 0.69444, 0, 0, 0.72223], // U+0044 D 69: M228, // U+0045 E 70: [0, 0.69444, 0, 0, 0.56945], // U+0046 F 71: M227, // U+0047 G 72: M230, // U+0048 H 73: M133, // U+0049 I 74: M226, // U+004a J 75: [0, 0.69444, 0, 0, 0.69445], // U+004b K 76: M229, // U+004c L 77: [0, 0.69444, 0, 0, 0.875], // U+004d M 78: M230, // U+004e N 79: [0, 0.69444, 0, 0, 0.73611], // U+004f O 80: M75, // U+0050 P 81: [0.125, 0.69444, 0, 0, 0.73611], // U+0051 Q 82: [0, 0.69444, 0, 0, 0.64584], // U+0052 R 83: M144, // U+0053 S 84: [0, 0.69444, 0, 0, 0.68056], // U+0054 T 85: [0, 0.69444, 0, 0, 0.6875], // U+0055 U 86: [0, 0.69444, 0.01389, 0, 0.66667], // U+0056 V 87: [0, 0.69444, 0.01389, 0, 0.94445], // U+0057 W 88: M227, // U+0058 X 89: [0, 0.69444, 0.025, 0, 0.66667], // U+0059 Y 90: M170, // U+005a Z 91: M231, // U+005b [ 93: M231, // U+005d ] 94: M143, // U+005e ^ 95: [0.35, 0.09444, 0.02778, 0, 0.5], // U+005f _ 97: [0, 0.44444, 0, 0, 0.48056], // U+0061 a 98: M232, // U+0062 b 99: M233, // U+0063 c 100: M232, // U+0064 d 101: M233, // U+0065 e 102: [0, 0.69444, 0.06944, 0, 0.30556], // U+0066 f 103: [0.19444, 0.44444, 0.01389, 0, 0.5], // U+0067 g 104: M232, // U+0068 h 105: [0, 0.67937, 0, 0, 0.23889], // U+0069 i 106: [0.19444, 0.67937, 0, 0, 0.26667], // U+006a j 107: [0, 0.69444, 0, 0, 0.48889], // U+006b k 108: [0, 0.69444, 0, 0, 0.23889], // U+006c l 109: [0, 0.44444, 0, 0, 0.79445], // U+006d m 110: M236, // U+006e n 111: [0, 0.44444, 0, 0, 0.5], // U+006f o 112: M234, // U+0070 p 113: M234, // U+0071 q 114: [0, 0.44444, 0.01389, 0, 0.34167], // U+0072 r 115: M235, // U+0073 s 116: [0, 0.57143, 0, 0, 0.36111], // U+0074 t 117: M236, // U+0075 u 118: [0, 0.44444, 0.01389, 0, 0.46111], // U+0076 v 119: [0, 0.44444, 0.01389, 0, 0.68334], // U+0077 w 120: [0, 0.44444, 0, 0, 0.46111], // U+0078 x 121: [0.19444, 0.44444, 0.01389, 0, 0.46111], // U+0079 y 122: [0, 0.44444, 0, 0, 0.43472], // U+007a z 126: [0.35, 0.32659, 0, 0, 0.5], // U+007e ~ 160: M7, // U+00a0 168: [0, 0.67937, 0, 0, 0.5], // U+00a8 ¨ 176: M227, // U+00b0 ° 184: M213, // U+00b8 ¸ 305: [0, 0.44444, 0, 0, 0.23889], // U+0131 ı 567: [0.19444, 0.44444, 0, 0, 0.26667], // U+0237 ȷ 710: M143, // U+02c6 ˆ 711: [0, 0.63194, 0, 0, 0.5], // U+02c7 ˇ 713: [0, 0.60889, 0, 0, 0.5], // U+02c9 ˉ 714: M143, // U+02ca ˊ 715: M143, // U+02cb ˋ 728: M143, // U+02d8 ˘ 729: [0, 0.67937, 0, 0, 0.27778], // U+02d9 ˙ 730: M227, // U+02da ˚ 732: [0, 0.67659, 0, 0, 0.5], // U+02dc ˜ 733: M143, // U+02dd ˝ 915: M229, // U+0393 Γ 916: M237, // U+0394 Δ 920: M136, // U+0398 Θ 923: M170, // U+039b Λ 926: M227, // U+039e Ξ 928: M230, // U+03a0 Π 931: M156, // U+03a3 Σ 933: M136, // U+03a5 Υ 934: M156, // U+03a6 Φ 936: M136, // U+03a8 Ψ 937: M156, // U+03a9 Ω 8211: [0, 0.44444, 0.02778, 0, 0.5], // U+2013 – 8212: [0, 0.44444, 0.02778, 0, 1], // U+2014 — 8216: M133, // U+2018 ‘ 8217: M133, // U+2019 ’ 8220: M143, // U+201c “ 8221: M143 // U+201d ” }, "Script-Regular": { 32: M7, // U+0020 65: [0, 0.7, 0.22925, 0, 0.80253], // U+0041 A 66: [0, 0.7, 0.04087, 0, 0.90757], // U+0042 B 67: [0, 0.7, 0.1689, 0, 0.66619], // U+0043 C 68: [0, 0.7, 0.09371, 0, 0.77443], // U+0044 D 69: [0, 0.7, 0.18583, 0, 0.56162], // U+0045 E 70: [0, 0.7, 0.13634, 0, 0.89544], // U+0046 F 71: [0, 0.7, 0.17322, 0, 0.60961], // U+0047 G 72: [0, 0.7, 0.29694, 0, 0.96919], // U+0048 H 73: [0, 0.7, 0.19189, 0, 0.80907], // U+0049 I 74: [0.27778, 0.7, 0.19189, 0, 1.05159], // U+004a J 75: [0, 0.7, 0.31259, 0, 0.91364], // U+004b K 76: [0, 0.7, 0.19189, 0, 0.87373], // U+004c L 77: [0, 0.7, 0.15981, 0, 1.08031], // U+004d M 78: [0, 0.7, 0.3525, 0, 0.9015], // U+004e N 79: [0, 0.7, 0.08078, 0, 0.73787], // U+004f O 80: [0, 0.7, 0.08078, 0, 1.01262], // U+0050 P 81: [0, 0.7, 0.03305, 0, 0.88282], // U+0051 Q 82: [0, 0.7, 0.06259, 0, 0.85], // U+0052 R 83: [0, 0.7, 0.19189, 0, 0.86767], // U+0053 S 84: [0, 0.7, 0.29087, 0, 0.74697], // U+0054 T 85: [0, 0.7, 0.25815, 0, 0.79996], // U+0055 U 86: [0, 0.7, 0.27523, 0, 0.62204], // U+0056 V 87: [0, 0.7, 0.27523, 0, 0.80532], // U+0057 W 88: [0, 0.7, 0.26006, 0, 0.94445], // U+0058 X 89: [0, 0.7, 0.2939, 0, 0.70961], // U+0059 Y 90: [0, 0.7, 0.24037, 0, 0.8212], // U+005a Z 160: M7 // U+00a0 }, "Size1-Regular": { 32: M7, // U+0020 40: M238, // U+0028 ( 41: M238, // U+0029 ) 47: M239, // U+002f / 91: M240, // U+005b [ 92: M239, // U+005c \ 93: M240, // U+005d ] 123: M241, // U+007b { 125: M241, // U+007d } 160: M7, // U+00a0 710: M242, // U+02c6 ˆ 732: M242, // U+02dc ˜ 770: M242, // U+0302 ̂ 771: M242, // U+0303 ̃ 8214: [-99e-5, 0.601, 0, 0, 0.77778], // U+2016 ‖ 8593: M243, // U+2191 ↑ 8595: M243, // U+2193 ↓ 8657: M244, // U+21d1 ⇑ 8659: M244, // U+21d3 ⇓ 8719: M245, // U+220f ∏ 8720: M245, // U+2210 ∐ 8721: [0.25001, 0.75, 0, 0, 1.05556], // U+2211 ∑ 8730: [0.35001, 0.85, 0, 0, 1], // U+221a √ 8739: [-599e-5, 0.606, 0, 0, 0.33333], // U+2223 ∣ 8741: [-599e-5, 0.606, 0, 0, 0.55556], // U+2225 ∥ 8747: M247, // U+222b ∫ 8748: M246, // U+222c ∬ 8749: M246, // U+222d ∭ 8750: M247, // U+222e ∮ 8896: M248, // U+22c0 ⋀ 8897: M248, // U+22c1 ⋁ 8898: M248, // U+22c2 ⋂ 8899: M248, // U+22c3 ⋃ 8968: M249, // U+2308 ⌈ 8969: M249, // U+2309 ⌉ 8970: M249, // U+230a ⌊ 8971: M249, // U+230b ⌋ 9168: M277, // U+23d0 ⏐ 10216: M249, // U+27e8 ⟨ 10217: M249, // U+27e9 ⟩ 10752: M250, // U+2a00 ⨀ 10753: M250, // U+2a01 ⨁ 10754: M250, // U+2a02 ⨂ 10756: M248, // U+2a04 ⨄ 10758: M248 // U+2a06 ⨆ }, "Size2-Regular": { 32: M7, // U+0020 40: M251, // U+0028 ( 41: M251, // U+0029 ) 47: M252, // U+002f / 91: M253, // U+005b [ 92: M252, // U+005c \ 93: M253, // U+005d ] 123: M254, // U+007b { 125: M254, // U+007d } 160: M7, // U+00a0 710: M255, // U+02c6 ˆ 732: M255, // U+02dc ˜ 770: M255, // U+0302 ̂ 771: M255, // U+0303 ̃ 8719: M256, // U+220f ∏ 8720: M256, // U+2210 ∐ 8721: [0.55001, 1.05, 0, 0, 1.44445], // U+2211 ∑ 8730: [0.65002, 1.15, 0, 0, 1], // U+221a √ 8747: M258, // U+222b ∫ 8748: M257, // U+222c ∬ 8749: M257, // U+222d ∭ 8750: M258, // U+222e ∮ 8896: M259, // U+22c0 ⋀ 8897: M259, // U+22c1 ⋁ 8898: M259, // U+22c2 ⋂ 8899: M259, // U+22c3 ⋃ 8968: M260, // U+2308 ⌈ 8969: M260, // U+2309 ⌉ 8970: M260, // U+230a ⌊ 8971: M260, // U+230b ⌋ 10216: M261, // U+27e8 ⟨ 10217: M261, // U+27e9 ⟩ 10752: M262, // U+2a00 ⨀ 10753: M262, // U+2a01 ⨁ 10754: M262, // U+2a02 ⨂ 10756: M259, // U+2a04 ⨄ 10758: M259 // U+2a06 ⨆ }, "Size3-Regular": { 32: M7, // U+0020 40: M263, // U+0028 ( 41: M263, // U+0029 ) 47: M264, // U+002f / 91: M265, // U+005b [ 92: M264, // U+005c \ 93: M265, // U+005d ] 123: M266, // U+007b { 125: M266, // U+007d } 160: M7, // U+00a0 710: M267, // U+02c6 ˆ 732: M267, // U+02dc ˜ 770: M267, // U+0302 ̂ 771: M267, // U+0303 ̃ 8730: [0.95003, 1.45, 0, 0, 1], // U+221a √ 8968: M268, // U+2308 ⌈ 8969: M268, // U+2309 ⌉ 8970: M268, // U+230a ⌊ 8971: M268, // U+230b ⌋ 10216: M266, // U+27e8 ⟨ 10217: M266 // U+27e9 ⟩ }, "Size4-Regular": { 32: M7, // U+0020 40: M269, // U+0028 ( 41: M269, // U+0029 ) 47: M270, // U+002f / 91: M271, // U+005b [ 92: M270, // U+005c \ 93: M271, // U+005d ] 123: M272, // U+007b { 125: M272, // U+007d } 160: M7, // U+00a0 710: M273, // U+02c6 ˆ 732: M273, // U+02dc ˜ 770: M273, // U+0302 ̂ 771: M273, // U+0303 ̃ 8730: [1.25003, 1.75, 0, 0, 1], // U+221a √ 8968: M274, // U+2308 ⌈ 8969: M274, // U+2309 ⌉ 8970: M274, // U+230a ⌊ 8971: M274, // U+230b ⌋ 9115: M275, // U+239b ⎛ 9116: M276, // U+239c ⎜ 9117: M275, // U+239d ⎝ 9118: M275, // U+239e ⎞ 9119: M276, // U+239f ⎟ 9120: M275, // U+23a0 ⎠ 9121: M278, // U+23a1 ⎡ 9122: M277, // U+23a2 ⎢ 9123: M278, // U+23a3 ⎣ 9124: M278, // U+23a4 ⎤ 9125: M277, // U+23a5 ⎥ 9126: M278, // U+23a6 ⎦ 9127: M279, // U+23a7 ⎧ 9128: M280, // U+23a8 ⎨ 9129: M281, // U+23a9 ⎩ 9130: [0, 0.3, 0, 0, 0.88889], // U+23aa ⎪ 9131: M279, // U+23ab ⎫ 9132: M280, // U+23ac ⎬ 9133: M281, // U+23ad ⎭ 9143: [0.88502, 0.915, 0, 0, 1.05556], // U+23b7 ⎷ 10216: M272, // U+27e8 ⟨ 10217: M272, // U+27e9 ⟩ 57344: M282, // U+e000  57345: M282, // U+e001  57680: M283, // U+e150  57681: M283, // U+e151  57682: M283, // U+e152  57683: M283 // U+e153  }, "Typewriter-Regular": { 32: M290, // U+0020 33: M284, // U+0021 ! 34: M284, // U+0022 " 35: M284, // U+0023 # 36: M285, // U+0024 $ 37: M285, // U+0025 % 38: M284, // U+0026 & 39: M284, // U+0027 ' 40: M285, // U+0028 ( 41: M285, // U+0029 ) 42: [0, 0.52083, 0, 0, 0.525], // U+002a * 43: M286, // U+002b + 44: [0.13889, 0.125, 0, 0, 0.525], // U+002c , 45: M286, // U+002d - 46: [0, 0.125, 0, 0, 0.525], // U+002e . 47: M285, // U+002f / 48: M284, // U+0030 0 49: M284, // U+0031 1 50: M284, // U+0032 2 51: M284, // U+0033 3 52: M284, // U+0034 4 53: M284, // U+0035 5 54: M284, // U+0036 6 55: M284, // U+0037 7 56: M284, // U+0038 8 57: M284, // U+0039 9 58: M288, // U+003a : 59: [0.13889, 0.43056, 0, 0, 0.525], // U+003b ; 60: M287, // U+003c < 61: [-0.19549, 0.41562, 0, 0, 0.525], // U+003d = 62: M287, // U+003e > 63: M284, // U+003f ? 64: M284, // U+0040 @ 65: M284, // U+0041 A 66: M284, // U+0042 B 67: M284, // U+0043 C 68: M284, // U+0044 D 69: M284, // U+0045 E 70: M284, // U+0046 F 71: M284, // U+0047 G 72: M284, // U+0048 H 73: M284, // U+0049 I 74: M284, // U+004a J 75: M284, // U+004b K 76: M284, // U+004c L 77: M284, // U+004d M 78: M284, // U+004e N 79: M284, // U+004f O 80: M284, // U+0050 P 81: [0.13889, 0.61111, 0, 0, 0.525], // U+0051 Q 82: M284, // U+0052 R 83: M284, // U+0053 S 84: M284, // U+0054 T 85: M284, // U+0055 U 86: M284, // U+0056 V 87: M284, // U+0057 W 88: M284, // U+0058 X 89: M284, // U+0059 Y 90: M284, // U+005a Z 91: M285, // U+005b [ 92: M285, // U+005c \ 93: M285, // U+005d ] 94: M284, // U+005e ^ 95: [0.09514, 0, 0, 0, 0.525], // U+005f _ 96: M284, // U+0060 ` 97: M288, // U+0061 a 98: M284, // U+0062 b 99: M288, // U+0063 c 100: M284, // U+0064 d 101: M288, // U+0065 e 102: M284, // U+0066 f 103: M289, // U+0067 g 104: M284, // U+0068 h 105: M284, // U+0069 i 106: [0.22222, 0.61111, 0, 0, 0.525], // U+006a j 107: M284, // U+006b k 108: M284, // U+006c l 109: M288, // U+006d m 110: M288, // U+006e n 111: M288, // U+006f o 112: M289, // U+0070 p 113: M289, // U+0071 q 114: M288, // U+0072 r 115: M288, // U+0073 s 116: [0, 0.55358, 0, 0, 0.525], // U+0074 t 117: M288, // U+0075 u 118: M288, // U+0076 v 119: M288, // U+0077 w 120: M288, // U+0078 x 121: M289, // U+0079 y 122: M288, // U+007a z 123: M285, // U+007b { 124: M285, // U+007c | 125: M285, // U+007d } 126: M284, // U+007e ~ 127: M284, // U+007f  160: M290, // U+00a0 176: M284, // U+00b0 ° 184: [0.19445, 0, 0, 0, 0.525], // U+00b8 ¸ 305: M288, // U+0131 ı 567: M289, // U+0237 ȷ 711: [0, 0.56597, 0, 0, 0.525], // U+02c7 ˇ 713: [0, 0.56555, 0, 0, 0.525], // U+02c9 ˉ 714: M284, // U+02ca ˊ 715: M284, // U+02cb ˋ 728: M284, // U+02d8 ˘ 730: M284, // U+02da ˚ 770: M284, // U+0302 ̂ 771: M284, // U+0303 ̃ 776: M284, // U+0308 ̈ 915: M284, // U+0393 Γ 916: M284, // U+0394 Δ 920: M284, // U+0398 Θ 923: M284, // U+039b Λ 926: M284, // U+039e Ξ 928: M284, // U+03a0 Π 931: M284, // U+03a3 Σ 933: M284, // U+03a5 Υ 934: M284, // U+03a6 Φ 936: M284, // U+03a8 Ψ 937: M284, // U+03a9 Ω 8216: M284, // U+2018 ‘ 8217: M284, // U+2019 ’ 8242: M284, // U+2032 ′ 9251: [0.11111, 0.21944, 0, 0, 0.525] // U+2423 ␣ } }; // src/core/font-metrics.ts var CJK_REGEX = /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/; var PT_PER_EM = 10; var AXIS_HEIGHT = 0.25; var BASELINE_SKIP = 1.2; var X_HEIGHT = 0.431; var FONT_METRICS = { slant: [0.25, 0.25, 0.25], space: [0, 0, 0], stretch: [0, 0, 0], shrink: [0, 0, 0], xHeight: [X_HEIGHT, X_HEIGHT, X_HEIGHT], quad: [1, 1.171, 1.472], extraSpace: [0, 0, 0], num1: [0.5, 0.732, 0.925], // Was num1: [0.677, 0.732, 0.925], num2: [0.394, 0.384, 0.5], // Was num2: [0.394, 0.384, 0.387], num3: [0.444, 0.471, 0.504], denom1: [0.686, 0.752, 1.025], denom2: [0.345, 0.344, 0.532], sup1: [0.413, 0.503, 0.504], sup2: [0.363, 0.431, 0.404], sup3: [0.289, 0.286, 0.294], sub1: [0.15, 0.143, 0.2], sub2: [0.247, 0.286, 0.4], supDrop: [0.386, 0.353, 0.494], subDrop: [0.05, 0.071, 0.1], delim1: [2.39, 1.7, 1.98], delim2: [1.01, 1.157, 1.42], axisHeight: [AXIS_HEIGHT, AXIS_HEIGHT, AXIS_HEIGHT], defaultRuleThickness: [0.04, 0.049, 0.049], bigOpSpacing1: [0.111, 0.111, 0.111], bigOpSpacing2: [0.166, 0.166, 0.166], bigOpSpacing3: [0.2, 0.2, 0.2], bigOpSpacing4: [0.6, 0.611, 0.611], bigOpSpacing5: [0.1, 0.143, 0.143], sqrtRuleThickness: [0.04, 0.04, 0.04] }; var FONT_SCALE = [ 0, // not used 0.5, // size 1 = scriptscriptstyle 0.7, // size 2 = scriptstyle 0.8, 0.9, 1, // size 5 = default 1.2, 1.44, 1.728, 2.074, 2.488 //size 10 ]; var DEFAULT_FONT_SIZE = 5; var EXTRA_CHARACTER_MAP = { "\xA0": " ", // NON-BREAKING SPACE is like space "\u200B": " ", // ZERO WIDTH SPACE is like space // Latin-1 "\xC5": "A", "\xC7": "C", "\xD0": "D", "\xDE": "o", "\xE5": "a", "\xE7": "c", "\xF0": "d", "\xFE": "o", // Cyrillic "\u0410": "A", "\u0411": "B", "\u0412": "B", "\u0413": "F", "\u0414": "A", "\u0415": "E", "\u0416": "K", "\u0417": "3", "\u0418": "N", "\u0419": "N", "\u041A": "K", "\u041B": "N", "\u041C": "M", "\u041D": "H", "\u041E": "O", "\u041F": "N", "\u0420": "P", "\u0421": "C", "\u0422": "T", "\u0423": "y", "\u0424": "O", "\u0425": "X", "\u0426": "U", "\u0427": "h", "\u0428": "W", "\u0429": "W", "\u042A": "B", "\u042B": "X", "\u042C": "B", "\u042D": "3", "\u042E": "X", "\u042F": "R", "\u0430": "a", "\u0431": "b", "\u0432": "a", "\u0433": "r", "\u0434": "y", "\u0435": "e", "\u0436": "m", "\u0437": "e", "\u0438": "n", "\u0439": "n", "\u043A": "n", "\u043B": "n", "\u043C": "m", "\u043D": "n", "\u043E": "o", "\u043F": "n", "\u0440": "p", "\u0441": "c", "\u0442": "o", "\u0443": "y", "\u0444": "b", "\u0445": "x", "\u0446": "n", "\u0447": "n", "\u0448": "w", "\u0449": "w", "\u044A": "a", "\u044B": "m", "\u044C": "a", "\u044D": "e", "\u044E": "m", "\u044F": "r" }; function getCharacterMetrics(codepoint, fontName) { if (codepoint === void 0) codepoint = 77; const metrics = font_metrics_data_default[fontName][codepoint]; if (metrics) { return { defaultMetrics: false, depth: metrics[0], height: metrics[1], italic: metrics[2], skew: metrics[3], width: metrics[4] }; } if (codepoint === 11034) { return { defaultMetrics: true, depth: 0.2, height: 0.8, italic: 0, skew: 0, width: 0.8 }; } const char = String.fromCodePoint(codepoint); if (char in EXTRA_CHARACTER_MAP) codepoint = EXTRA_CHARACTER_MAP[char].codePointAt(0); else if (CJK_REGEX.test(char)) { codepoint = 77; return { defaultMetrics: true, depth: 0.2, height: 0.9, italic: 0, skew: 0, width: 1 }; } return { defaultMetrics: true, depth: 0.2, height: 0.7, italic: 0, skew: 0, width: 0.8 }; } // src/core/svg-box.ts var SVG_BODY = { // Adapted from https://github.com/KaTeX/KaTeX/blob/master/src/stretchy.js overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"], underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"], xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], longrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"], xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], longleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"], Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"], xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"], xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"], overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"], xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"], xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"], overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"], xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"], xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"], xlongequal: [["longequal"], 0.888, 334, "xMinYMin"], xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"], xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"], overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548], underbrace: [ ["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548 ], underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522], xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], longleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522], xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560], xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716], longrightleftharpoons: [ ["leftharpoondownplus", "rightharpoonplus"], 1.75, 716 ], xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716], longleftrightharpoons: [ ["leftharpoonplus", "rightharpoondownplus"], 1.75, 716 ], xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522], xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522], overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522], overgroup: [["leftgroup", "rightgroup"], 0.888, 342], undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342], xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522], xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528], // The next three arrows are from the mhchem package. // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the // document as \xrightarrow or \xrightleftharpoons. Those have // min-length = 1.75em, so we set min-length on these next three to match. xleftrightarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], longleftrightarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901], xRightleftharpoons: [ ["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716 ], longRightleftharpoons: [ ["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716 ], xLeftrightharpoons: [ ["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716 ], longLeftrightharpoons: [ ["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716 ] }; var SVG_ACCENTS = { // ViewBoxWidth, viewBoxHeight, height widehat1: [1062, 239, 0.24], widehat2: [2364, 300, 0.3], widehat3: [2364, 360, 0.36], widehat4: [2364, 420, 0.42], widecheck1: [1062, 239, 0.24], widecheck2: [2364, 300, 0.3], widecheck3: [2364, 360, 0.36], widecheck4: [2364, 420, 0.42], widetilde1: [600, 260, 0.26], widetilde2: [1033, 286, 0.286], widetilde3: [2339, 306, 0.306], widetilde4: [2340, 312, 0.34], overarc: [1061, 159, 0.3], underarc: [1061, 159, 0.3] }; var PATHS = { // 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`, overarc: `M529 0c179 0 524 115 524 115 5 1 9 5 9 10 0 1-1 2-1 3l-4 22c-1 5-5 9-11 9h-2s-338-93-512-92c-174 0-513 92-513 92h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13 0 0 342-115 520-115z`, underarc: `m 529 160 c -179 0 -524 -115 -524 -115 c -5 -1 -9 -5 -9 -10 c 0 -1 1 -2 1 -3 l 4 -22 c 1 -5 5 -9 11 -9 h 2 s 338 93 512 92 c 174 0 513 -92 513 -92 h 2 c 5 0 9 4 11 9 l 5 22 c 1 6 -2 12 -8 13 c 0 0 -342 115 -520 115 z `, // 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 widetilde1: `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 widetilde2: `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`, widetilde3: `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`, widetilde4: `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` }; function svgBodyToMarkup(svgBodyName) { if (SVG_ACCENTS[svgBodyName]) { const [vbWidth, vbHeight, height2] = SVG_ACCENTS[svgBodyName]; const result = ``; return `${result}`; } const [paths, minWidth, viewBoxHeight, align2] = SVG_BODY[svgBodyName]; let widthClasses; let aligns; const height = viewBoxHeight / 1e3; if (paths.length === 3) { widthClasses = ["slice-1-of-3", "slice-2-of-3", "slice-3-of-3"]; aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"]; } else if (paths.length === 2) { widthClasses = ["slice-1-of-2", "slice-2-of-2"]; aligns = ["xMinYMin", "xMaxYMin"]; } else { widthClasses = ["slice-1-of-1"]; aligns = [align2]; } const body = paths.map( (path, i) => `` ).join(""); return `${body}`; } function svgBodyHeight(svgBodyName) { if (SVG_BODY[svgBodyName]) return SVG_BODY[svgBodyName][2] / 1e3; return SVG_ACCENTS[svgBodyName][2]; } // src/core/grapheme-splitter.ts function stringToCodepoints(string) { const result = []; for (let i = 0; i < string.length; i++) { let code = string.charCodeAt(i); if (code === 13 && string.charCodeAt(i + 1) === 10) { code = 10; i++; } if (code === 13 || code === 12) code = 10; if (code === 0) code = 65533; if (code >= 55296 && code <= 56319) { const nextCode = string.charCodeAt(i + 1); if (nextCode >= 56320 && nextCode <= 57343) { const lead = code - 55296; const trail = nextCode - 56320; code = 2 ** 16 + lead * 2 ** 10 + trail; i++; } } result.push(code); } return result; } var ZWJ = 8205; var EMOJI_COMBINATOR = [ [ZWJ, 1], [65038, 2], // VS-15: text presentation, VS-16: Emoji presentation [127995, 5], // EMOJI_MODIFIER_FITZPATRICK_TYPE 1-6 [129456, 4], // Red hair..white hair [917536, 96] // EMOJI_TAG ]; var emojiCombinator; var REGIONAL_INDICATOR = [127462, 127487]; function isEmojiCombinator(code) { var _a3; if (emojiCombinator === void 0) { emojiCombinator = {}; for (const x of EMOJI_COMBINATOR) for (let i = x[0]; i <= x[0] + x[1] - 1; i++) emojiCombinator[i] = true; } return (_a3 = emojiCombinator[code]) != null ? _a3 : false; } function isRegionalIndicator(code) { return code >= REGIONAL_INDICATOR[0] && code <= REGIONAL_INDICATOR[1]; } function splitGraphemes(string) { if (/^[\u0020-\u00FF]*$/.test(string)) return string; const result = []; const codePoints = stringToCodepoints(string); let index = 0; while (index < codePoints.length) { const code = codePoints[index++]; const next = codePoints[index]; if (next === ZWJ) { const baseIndex = index - 1; index += 2; while (codePoints[index] === ZWJ) index += 2; result.push( String.fromCodePoint( ...codePoints.slice(baseIndex, index - baseIndex + 1) ) ); } else if (isEmojiCombinator(next)) { const baseIndex = index - 1; while (isEmojiCombinator(codePoints[index])) index += codePoints[index] === ZWJ ? 2 : 1; result.push( String.fromCodePoint( ...codePoints.slice(baseIndex, 2 * index - baseIndex - 1) ) ); } else if (isRegionalIndicator(code)) { index += 1; result.push(String.fromCodePoint(...codePoints.slice(index - 2, 2))); } else result.push(String.fromCodePoint(code)); } return result; } // src/core/tokenizer.ts var Tokenizer = class { constructor(s) { this.obeyspaces = false; this.pos = 0; this.s = splitGraphemes(s); } /** * @return True if we reached the end of the stream */ end() { return this.pos >= this.s.length; } /** * Return the next char and advance */ get() { return this.pos < this.s.length ? this.s[this.pos++] : ""; } /** * Return the next char, but do not advance */ peek() { return this.s[this.pos]; } /** * Return the next substring matching regEx and advance. */ match(regEx) { const execResult = typeof this.s === "string" ? regEx.exec(this.s.slice(this.pos)) : regEx.exec(this.s.slice(this.pos).join("")); if (execResult == null ? void 0 : execResult[0]) { this.pos += execResult[0].length; return execResult[0]; } return ""; } /** * Return the next token, or null. */ next() { if (this.end()) return null; if (!this.obeyspaces && this.match(/^[ \f\n\r\t\v\u00A0\u2028\u2029]+/)) { return ""; } if (this.obeyspaces && this.match(/^[ \f\n\r\t\v\u00A0\u2028\u2029]/)) { return ""; } const next = this.get(); if (next === "\\") { if (!this.end()) { let command = this.match(/^[a-zA-Z\*]+/); if (command) { this.match(/^[ \f\n\r\t\v\u00A0\u2028\u2029]*/); } else { command = this.get(); } return "\\" + command; } } else if (next === "{") { return "<{>"; } else if (next === "}") { return "<}>"; } else if (next === "^") { if (this.peek() === "^") { this.get(); const hex = this.match( /^(\^(\^(\^(\^[\da-f])?[\da-f])?[\da-f])?[\da-f])?[\da-f]{2}/ ); if (hex) { return String.fromCodePoint( Number.parseInt(hex.slice(hex.lastIndexOf("^") + 1), 16) ); } } return next; } else if (next === "#") { if (!this.end()) { let isParameter = false; if (/[\d?@]/.test(this.peek())) { isParameter = true; if (this.pos + 1 < this.s.length) { const after = this.s[this.pos + 1]; isParameter = /[^\dA-Za-z]/.test(after); } } if (isParameter) return "#" + this.get(); return "#"; } } else if (next === "$") { if (this.peek() === "$") { this.get(); return "<$$>"; } return "<$>"; } return next; } }; function expand(lex, args) { var _a3, _b3, _c2, _d2; const result = []; let token = lex.next(); if (token) { if (token === "\\relax") { } else if (token === "\\noexpand") { token = lex.next(); if (token) result.push(token); } else if (token === "\\obeyspaces") lex.obeyspaces = true; else if (token === "\\bgroup") { result.push("<{>"); } else if (token === "\\egroup") { result.push("<}>"); } else if (token === "\\string") { token = lex.next(); if (token) { if (token.startsWith("\\")) for (const x of token) result.push(x === "\\" ? "\\backslash" : x); else if (token === "<{>") result.push("\\{"); else if (token === "") result.push("~"); else if (token === "<}>") result.push("\\}"); } } else if (token === "\\csname") { while (lex.peek() === "") lex.next(); let command = ""; let done = false; let tokens = []; do { if (tokens.length === 0) { if (/^#[\d?@]$/.test(lex.peek())) { const parameter = lex.get().slice(1); tokens = tokenize( (_b3 = (_a3 = args == null ? void 0 : args(parameter)) != null ? _a3 : args == null ? void 0 : args("?")) != null ? _b3 : "\\placeholder{}", args ); token = tokens[0]; } else { token = lex.next(); tokens = token ? [token] : []; } } done = tokens.length === 0; if (!done && token === "\\endcsname") { done = true; tokens.shift(); } if (!done) { done = token === "<$>" || token === "<$$>" || token === "<{>" || token === "<}>" || typeof token === "string" && token.length > 1 && token.startsWith("\\"); } if (!done) command += tokens.shift(); } while (!done); if (command) result.push("\\" + command); result.push(...tokens); } else if (token === "\\endcsname") { } else if (token.length > 1 && token.startsWith("#")) { const parameter = token.slice(1); result.push( ...tokenize((_d2 = (_c2 = args == null ? void 0 : args(parameter)) != null ? _c2 : args == null ? void 0 : args("?")) != null ? _d2 : "\\placeholder{}", args) ); } else result.push(token); } return result; } function tokenize(s, args = null) { const lines = []; let sep = ""; for (const line of s.toString().split(/\r?\n/)) { if (sep) lines.push(sep); sep = " "; const m = line.match(/((?:\\%)|[^%])*/); if (m !== null) lines.push(m[0]); } const tokenizer = new Tokenizer(unicodeToLatex(lines.join(""))); const result = []; do result.push(...expand(tokenizer, args)); while (!tokenizer.end()); return result; } function joinLatex(segments) { let sep = ""; const result = []; for (const segment of segments) { if (segment) { if (sep && /^[a-zA-Z\*]/.test(segment)) result.push(sep); result.push(segment); if (/^\\[a-zA-Z]+\*?[\"\'][^\ ]+$/.test(segment)) result.push(" "); sep = /\\[a-zA-Z]+\*?$/.test(segment) ? " " : ""; } } return result.join(""); } function latexCommand(command, ...args) { console.assert(command.startsWith("\\")); if (args.length === 0) return command; return joinLatex([command, ...args.map((x) => `{${x}}`)]); } function tokensToString(tokens) { return joinLatex( tokens.map( (token) => { var _a3; return (_a3 = { "": " ", "<$$>": "$$", "<$>": "$", "<{>": "{", "<}>": "}" }[token]) != null ? _a3 : token; } ) ); } // src/core/modes-utils.ts var _Mode = class _Mode { constructor(name) { _Mode._registry[name] = this; } static createAtom(mode, command, style) { return _Mode._registry[mode].createAtom( command, getDefinition(command, mode), style ); } static serialize(atoms, options) { var _a3; if (!atoms || atoms.length === 0) return ""; if ((_a3 = options.skipStyles) != null ? _a3 : false) { const body = []; for (const run of getModeRuns(atoms)) { const mode = _Mode._registry[run[0].mode]; body.push(...mode.serialize(run, options)); } return joinLatex(body); } return joinLatex(emitFontSizeRun(atoms, options)); } static getFont(mode, box, style) { return _Mode._registry[mode].getFont(box, style); } }; _Mode._registry = {}; var Mode = _Mode; function getModeRuns(atoms) { const result = []; let run = []; let currentMode = "NONE"; for (const atom of atoms) { if (atom.type !== "first") { if (atom.mode !== currentMode) { if (run.length > 0) result.push(run); run = [atom]; currentMode = atom.mode; } else run.push(atom); } } if (run.length > 0) result.push(run); return result; } function getPropertyRuns(atoms, property) { const result = []; let run = []; let currentValue = void 0; for (const atom of atoms) { if (atom.type !== "first" && atom.style) { let value; if (property === "variant") { value = atom.style.variant; if (atom.style.variantStyle && atom.style.variantStyle !== "up") value += "-" + atom.style.variantStyle; } else value = atom.style[property]; if (value === currentValue) { run.push(atom); } else { if (run.length > 0) result.push(run); run = [atom]; currentValue = value; } } } if (run.length > 0) result.push(run); return result; } function emitColorRun(run, options) { var _a3; const { parent } = run[0]; const parentColor = parent == null ? void 0 : parent.computedStyle.color; const result = []; for (const modeRun of getModeRuns(run)) { const mode = options.defaultMode; for (const colorRun of getPropertyRuns(modeRun, "color")) { const style = colorRun[0].computedStyle; const body = Mode._registry[colorRun[0].mode].serialize(colorRun, __spreadProps(__spreadValues({}, options), { defaultMode: mode === "text" ? "text" : "math" })); if (!options.skipStyles && style.color && style.color !== "none" && (!parent || parentColor !== style.color)) { result.push( latexCommand( "\\textcolor", (_a3 = style.verbatimColor) != null ? _a3 : style.color, joinLatex(body) ) ); } else result.push(joinLatex(body)); } } return result; } function emitBackgroundColorRun(run, options) { const { parent } = run[0]; const parentColor = parent == null ? void 0 : parent.computedStyle.backgroundColor; return getPropertyRuns(run, "backgroundColor").map((x) => { var _a3; if (x.length > 0 || x[0].type !== "box") { const style = x[0].computedStyle; if (style.backgroundColor && style.backgroundColor !== "none" && (!parent || parentColor !== style.backgroundColor)) { return latexCommand( "\\colorbox", (_a3 = style.verbatimBackgroundColor) != null ? _a3 : style.backgroundColor, joinLatex(emitColorRun(x, __spreadProps(__spreadValues({}, options), { defaultMode: "text" }))) ); } } return joinLatex(emitColorRun(x, options)); }); } function emitFontSizeRun(run, options) { if (run.length === 0) return []; const { parent } = run[0]; const contextFontsize = parent == null ? void 0 : parent.computedStyle.fontSize; const result = []; for (const sizeRun of getPropertyRuns(run, "fontSize")) { const fontsize = sizeRun[0].computedStyle.fontSize; const body = emitBackgroundColorRun(sizeRun, options); if (body) { if (fontsize && fontsize !== "auto" && (!parent || contextFontsize !== fontsize)) { result.push( [ "", "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge" ][fontsize], ...body ); } else result.push(...body); } } return result; } // src/core/box.ts function boxType(type) { if (!type) return void 0; const result = { mord: "ord", mbin: "bin", mop: "op", mrel: "rel", mopen: "open", mclose: "close", mpunct: "punct", minner: "inner", spacing: "ignore", latex: "latex", composition: "inner", error: "inner", placeholder: "ord", supsub: "ignore" }[type]; return result; } function atomsBoxType(atoms) { if (atoms.length === 0) return "ord"; const first = boxType(atoms[0].type); const last = boxType(atoms[atoms.length - 1].type); if (first && first === last) return first; return "ord"; } function toString(arg1, arg2) { if (typeof arg1 === "string") return arg1; if (typeof arg1 === "number") { console.assert(Number.isFinite(arg1)); const numValue = Math.ceil(100 * arg1) / 100; if (numValue === 0) return "0"; return numValue.toString() + (arg2 != null ? arg2 : ""); } return ""; } var Box = class _Box { constructor(content, options) { var _a3, _b3, _c2, _d2, _e; if (typeof content === "number") this.value = String.fromCodePoint(content); else if (typeof content === "string") this.value = content; else if (isArray(content)) this.children = content.filter((x) => x !== null); else if (content && content instanceof _Box) this.children = [content]; if (this.children) for (const child of this.children) child.parent = this; this.type = (_a3 = options == null ? void 0 : options.type) != null ? _a3 : "ignore"; this.isSelected = (options == null ? void 0 : options.isSelected) === true; if (options == null ? void 0 : options.caret) this.caret = options.caret; this.classes = (_b3 = options == null ? void 0 : options.classes) != null ? _b3 : ""; this.isTight = (_c2 = options == null ? void 0 : options.isTight) != null ? _c2 : false; if (options == null ? void 0 : options.attributes) this.attributes = options.attributes; let fontName = options == null ? void 0 : options.fontFamily; if ((options == null ? void 0 : options.style) && this.value) { fontName = (_e = Mode.getFont((_d2 = options.mode) != null ? _d2 : "math", this, __spreadProps(__spreadValues({ variant: "normal" }, options.style), { letterShapeStyle: options.letterShapeStyle }))) != null ? _e : void 0; } fontName || (fontName = "Main-Regular"); this._height = 0; this._depth = 0; this._width = 0; this.hasExplicitWidth = false; this.skew = 0; this.italic = 0; this.maxFontSize = 0; this.scale = 1; if ((options == null ? void 0 : options.maxFontSize) !== void 0) this.maxFontSize = options.maxFontSize; horizontalLayout(this, fontName); } set atomID(id) { if (id === void 0 || id.length === 0) return; this.id = id; } selected(isSelected) { if (this.isSelected === isSelected) return; this.isSelected = isSelected; if (this.children) for (const child of this.children) child.selected(isSelected); } setStyle(prop, value, unit) { if (value === void 0) return; const v = toString(value, unit); if (v.length > 0) { if (!this.cssProperties) this.cssProperties = {}; this.cssProperties[prop] = v; } } setTop(top) { if (Number.isFinite(top) && Math.abs(top) > 0.01) { if (!this.cssProperties) this.cssProperties = {}; this.cssProperties.top = toString(top, "em"); this.height -= top; this.depth += top; } } get left() { var _a3; if ((_a3 = this.cssProperties) == null ? void 0 : _a3["margin-left"]) return Number.parseFloat(this.cssProperties["margin-left"]); return 0; } set left(value) { if (!Number.isFinite(value)) return; if (value === 0) { if (this.cssProperties) delete this.cssProperties["margin-left"]; } else { if (!this.cssProperties) this.cssProperties = {}; this.cssProperties["margin-left"] = toString(value, "em"); } } set right(value) { if (!Number.isFinite(value)) return; if (value === 0) { if (this.cssProperties) delete this.cssProperties["margin-right"]; } else { if (!this.cssProperties) this.cssProperties = {}; this.cssProperties["margin-right"] = toString(value, "em"); } } set bottom(value) { if (!Number.isFinite(value)) return; if (value === 0) { if (this.cssProperties) delete this.cssProperties["margin-bottom"]; } else { if (!this.cssProperties) this.cssProperties = {}; this.cssProperties["margin-bottom"] = toString(value, "em"); } } get width() { return this._width * this.scale; } set width(value) { this._width = value; this.hasExplicitWidth = true; } set softWidth(_value) { } get height() { return this._height * this.scale; } set height(value) { this._height = value; } get depth() { return this._depth * this.scale; } set depth(value) { this._depth = value; } /** * Apply the context (color, backgroundColor, size) to the box. */ wrap(context) { const parent = context.parent; if (!parent) return this; if (context.isPhantom) this.setStyle("opacity", 0); const color = context.color; if (color && color !== parent.color) this.setStyle("color", color); let backgroundColor = context.backgroundColor; if (this.isSelected) backgroundColor = highlight(backgroundColor); if (backgroundColor && backgroundColor !== parent.backgroundColor) { this.setStyle("background-color", backgroundColor); this.setStyle("display", "inline-block"); } const scale = context.scalingFactor; this.scale = scale; this.skew *= scale; this.italic *= scale; return this; } /** * Generate the HTML markup to represent this box. */ toMarkup() { var _a3, _b3, _c2, _d2; let body = (_a3 = this.value) != null ? _a3 : ""; if (this.children) for (const box of this.children) body += box.toMarkup(); let svgMarkup = ""; if (this.svgBody) svgMarkup = svgBodyToMarkup(this.svgBody); else if (this.svgOverlay) { svgMarkup = '${this.svgOverlay}`; } let props = ""; const classes = this.classes.split(" "); classes.push( (_c2 = { latex: "ML__raw-latex", placeholder: "ML__placeholder", error: "ML__error" }[this.type]) != null ? _c2 : "" ); if (this.caret === "latex") classes.push("ML__latex-caret"); if (this.isSelected) classes.push("ML__selected"); const classList = classes.length === 1 ? classes[0] : classes.filter((x, e, a) => x.length > 0 && a.indexOf(x) === e).join(" "); if (classList.length > 0) props += ` class="${classList}"`; if (this.id) props += ` data-atom-id=${this.id}`; if (this.cssId) props += ` id="${this.cssId.replace(/ /g, "-")}" `; if (this.attributes) { props += " " + Object.keys(this.attributes).map((x) => `${x}="${this.attributes[x]}"`).join(" "); } if (this.htmlData) { const entries = this.htmlData.split(","); for (const entry of entries) { const matched = entry.match(/([^=]+)=(.+$)/); if (matched) { const key = matched[1].trim().replace(/ /g, "-"); if (key) props += ` data-${key}="${matched[2]}" `; } else { const key = entry.trim().replace(/ /g, "-"); if (key) props += ` data-${key} `; } } } const cssProps = (_d2 = this.cssProperties) != null ? _d2 : {}; if (this.hasExplicitWidth) { if (cssProps.width === void 0) cssProps.width = `${Math.ceil(this._width * 100) / 100}em`; } const styles = Object.keys(cssProps).map((x) => `${x}:${cssProps[x]}`); if (this.scale !== void 0 && this.scale !== 1 && (body.length > 0 || svgMarkup.length > 0)) styles.push(`font-size: ${Math.ceil(this.scale * 1e4) / 100}%`); if (this.htmlStyle) { const entries = this.htmlStyle.split(";"); let styleString = ""; for (const entry of entries) { const matched = entry.match(/([^=]+):(.+$)/); if (matched) { const key = matched[1].trim().replace(/ /g, "-"); if (key) styleString += `${key}:${matched[2]};`; } } if (styleString) props += ` style="${styleString}"`; } if (styles.length > 0) props += ` style="${styles.join(";")}"`; let result = ""; if (props.length > 0 || svgMarkup.length > 0) result = `${body}${svgMarkup}`; else result = body; if (this.caret === "text") result += ''; else if (this.caret === "math") result += ''; return result; } /** * Can this box be coalesced with 'box'? * This is used to 'coalesce' (i.e. group together) a series of boxes that are * identical except for their value, and to avoid generating redundant boxes. * That is: '12' -> * "12" * rather than: * "12" */ tryCoalesceWith(box) { if (this.svgBody || !this.value) return false; if (box.svgBody || !box.value) return false; const hasChildren = this.children && this.children.length > 0; const boxHasChildren = box.children && box.children.length > 0; if (hasChildren || boxHasChildren) return false; if (box.cssProperties || this.cssProperties) { for (const prop of [ "border", "border-left", "border-right", "border-right-width", "left", "margin", "margin-left", "margin-right", "padding", "position", "width" ]) { if (box.cssProperties && prop in box.cssProperties) return false; if (this.cssProperties && prop in this.cssProperties) return false; } } const thisStyleCount = this.cssProperties ? Object.keys(this.cssProperties).length : 0; const boxStyleCount = box.cssProperties ? Object.keys(box.cssProperties).length : 0; if (thisStyleCount !== boxStyleCount) return false; if (thisStyleCount > 0) { for (const prop of Object.keys(this.cssProperties)) { if (this.cssProperties[prop] !== box.cssProperties[prop]) return false; } } const classes = this.classes.trim().replace(/\s+/g, " ").split(" "); const boxClasses = box.classes.trim().replace(/\s+/g, " ").split(" "); if (classes.length !== boxClasses.length) return false; classes.sort(); boxClasses.sort(); for (const [i, class_] of classes.entries()) { if (class_ === "vertical-separator") return false; if (class_ !== boxClasses[i]) return false; } this.value += box.value; this.height = Math.max(this.height, box.height); this.depth = Math.max(this.depth, box.depth); this._width = this._width + box._width; this.maxFontSize = Math.max(this.maxFontSize, box.maxFontSize); this.italic = box.italic; return true; } }; function coalesceRecursive(boxes) { if (!boxes || boxes.length === 0) return []; boxes[0].children = coalesceRecursive(boxes[0].children); const result = [boxes[0]]; for (let i = 1; i < boxes.length; i++) { if (!result[result.length - 1].tryCoalesceWith(boxes[i])) { boxes[i].children = coalesceRecursive(boxes[i].children); result.push(boxes[i]); } } return result; } function coalesce(box) { if (box.children) box.children = coalesceRecursive(box.children); return box; } function makeStruts(content, options) { if (!content) return new Box(null, options); const topStrut = new Box(null, { classes: "ML__strut", type: "ignore" }); topStrut.setStyle("height", Math.max(0, content.height), "em"); const struts = [topStrut]; if (content.depth !== 0) { const bottomStrut = new Box(null, { classes: "ML__strut--bottom", type: "ignore" }); bottomStrut.setStyle("height", content.height + content.depth, "em"); bottomStrut.setStyle("vertical-align", -content.depth, "em"); struts.push(bottomStrut); } struts.push(content); return new Box(struts, __spreadProps(__spreadValues({}, options), { type: "lift" })); } function makeSVGBox(svgBodyName) { const height = svgBodyHeight(svgBodyName) / 2; const box = new Box(null, { maxFontSize: 0 }); box.height = height + 0.166; box.depth = height - 0.166; box.svgBody = svgBodyName; return box; } function horizontalLayout(box, fontName) { var _a3; if (box.type === "latex") { box.height = 0.9; box.depth = 0.2; box._width = 1; return; } if (box.value) { box.height = -Infinity; box.depth = -Infinity; box._width = 0; box.skew = -Infinity; box.italic = -Infinity; for (let i = 0; i < box.value.length; i++) { const metrics = getCharacterMetrics(box.value.codePointAt(i), fontName); box.height = Math.max(box.height, metrics.height); box.depth = Math.max(box.depth, metrics.depth); box._width += metrics.width; box.skew = metrics.skew; box.italic = metrics.italic; } return; } if (box.children && box.children.length > 0) { let height = -Infinity; let depth = -Infinity; let maxFontSize = 0; for (const child of box.children) { if (child.height > height) height = child.height; if (child.depth > depth) depth = child.depth; maxFontSize = Math.max(maxFontSize, (_a3 = child.maxFontSize) != null ? _a3 : 0); } box.height = height; box.depth = depth; box._width = box.children.reduce((acc, x) => acc + x.width, 0); box.maxFontSize = maxFontSize; } } // src/core/v-box.ts function getVListChildrenAndDepth(params) { if ("individualShift" in params) { const oldChildren = params.individualShift; let prevChild = oldChildren[0]; const children = [prevChild]; const depth = -prevChild.shift - prevChild.box.depth; let currPos = depth; for (let i = 1; i < oldChildren.length; i++) { const child = oldChildren[i]; const diff = -child.shift - currPos - child.box.depth; const size = diff - (prevChild.box.height + prevChild.box.depth); currPos = currPos + diff; children.push(size); children.push(child); prevChild = child; } return [children, depth]; } if ("top" in params) { let bottom = params.top; for (const child of params.children) { bottom -= typeof child === "number" ? child : child.box.height + child.box.depth; } return [params.children, bottom]; } else if ("bottom" in params) return [params.children, -params.bottom]; else if ("firstBaseline" in params) { const firstChild = params.firstBaseline[0]; if (typeof firstChild === "number") throw new Error("First child must be an element."); return [params.firstBaseline, -firstChild.box.depth]; } else if ("shift" in params) { const firstChild = params.children[0]; if (typeof firstChild === "number") throw new Error("First child must be an element."); return [params.children, -firstChild.box.depth - params.shift]; } return [null, 0]; } function makeRows(params) { var _a3; const [children, depth] = getVListChildrenAndDepth(params); if (!children) return [[], 0, 0]; const pstrut = new Box(null, { classes: "pstrut" }); let pstrutSize = 0; for (const child of children) { if (typeof child !== "number") { const box = child.box; pstrutSize = Math.max(pstrutSize, box.maxFontSize, box.height); } } pstrutSize += 2; pstrut.height = pstrutSize; pstrut.setStyle("height", pstrutSize, "em"); const realChildren = []; let minPos = depth; let maxPos = depth; let currPos = depth; let width = 0; for (const child of children) { if (typeof child === "number") currPos += child; else { const box = child.box; const classes = (_a3 = child.classes) != null ? _a3 : []; const childWrap = new Box([pstrut, box], { classes: classes.join(" "), style: child.style }); box.setStyle("height", box.height + box.depth, "em"); box.setStyle("display", "inline-block"); childWrap.setStyle("top", -pstrutSize - currPos - box.depth, "em"); if (child.marginLeft) childWrap.setStyle("margin-left", child.marginLeft, "em"); if (child.marginRight) childWrap.setStyle("margin-right", child.marginRight, "em"); realChildren.push(childWrap); currPos += box.height + box.depth; width = Math.max(width, childWrap.width); } minPos = Math.min(minPos, currPos); maxPos = Math.max(maxPos, currPos); } realChildren.forEach((child) => { child.softWidth = width; }); const vlist = new Box(realChildren, { classes: "vlist" }); vlist.softWidth = width; vlist.height = maxPos; vlist.setStyle("height", maxPos, "em"); if (minPos >= 0) return [[new Box(vlist, { classes: "vlist-r" })], maxPos, -minPos]; const depthStrut = new Box(new Box(null), { classes: "vlist" }); depthStrut.height = -minPos; depthStrut.setStyle("height", -minPos, "em"); const topStrut = new Box(8203, { classes: "vlist-s", maxFontSize: 0 }); topStrut.softWidth = 0; topStrut.height = 0; topStrut.depth = 0; return [ [ new Box([vlist, topStrut], { classes: "vlist-r" }), new Box(depthStrut, { classes: "vlist-r" }) ], maxPos, -minPos ]; } var VBox = class extends Box { constructor(content, options) { var _a3; const [rows, height, depth] = makeRows(content); super(rows.length === 1 ? rows[0] : rows, { type: options == null ? void 0 : options.type, classes: ((_a3 = options == null ? void 0 : options.classes) != null ? _a3 : "") + " vlist-t" + (rows.length === 2 ? " vlist-t2" : "") }); this.height = height; this.depth = depth; this.softWidth = rows.reduce((acc, row) => Math.max(acc, row.width), 0); } }; function makeLimitsStack(context, options) { var _a3, _b3, _c2, _d2, _e; const metrics = context.metrics; const base = new Box(options.base); const baseShift = (_a3 = options.baseShift) != null ? _a3 : 0; const slant = (_b3 = options.slant) != null ? _b3 : 0; let aboveShift = 0; let belowShift = 0; if (options.above) { aboveShift = (_c2 = options.aboveShift) != null ? _c2 : Math.max( metrics.bigOpSpacing1, metrics.bigOpSpacing3 - options.above.depth ); } if (options.below) { belowShift = (_d2 = options.belowShift) != null ? _d2 : Math.max( metrics.bigOpSpacing2, metrics.bigOpSpacing4 - options.below.height ); } let result = null; if (options.below && options.above) { const bottom = metrics.bigOpSpacing5 + options.below.height + options.below.depth + belowShift + base.depth + baseShift; result = new VBox({ bottom, children: [ metrics.bigOpSpacing5, { box: options.below, marginLeft: -slant, classes: ["ML__center"] }, belowShift, // We need to center the base to account for the case where the // above/below is wider { box: base, classes: ["ML__center"] }, aboveShift, { box: options.above, marginLeft: slant, classes: ["ML__center"] }, metrics.bigOpSpacing5 ] }).wrap(context); } else if (options.below && !options.above) { result = new VBox({ top: base.height - baseShift, children: [ metrics.bigOpSpacing5, { box: options.below, marginLeft: -slant, classes: ["ML__center"] }, belowShift, { box: base, classes: ["ML__center"] } ] }).wrap(context); } else if (!options.below && options.above) { const bottom = base.depth + baseShift; result = new VBox({ bottom, children: [ { box: base, classes: ["ML__center"] }, aboveShift, { box: options.above, marginLeft: slant, classes: ["ML__center"] }, metrics.bigOpSpacing5 ] }).wrap(context); } else { const bottom = base.depth + baseShift; result = new VBox({ bottom, children: [{ box: base }, metrics.bigOpSpacing5] }).wrap(context); } return new Box(result, { type: (_e = options.type) != null ? _e : "op" }); } // src/core/mathstyle.ts var D = 7; var Dc = 6; var T = 5; var Tc = 4; var S = 3; var Sc = 2; var SS = 1; var SSc = 0; var Mathstyle = class { constructor(id, sizeDelta, cramped) { this.id = id; this.sizeDelta = sizeDelta; this.cramped = cramped; const metricsIndex = { "-4": 2, "-3": 1, 0: 0 }[sizeDelta]; this.metrics = Object.keys(FONT_METRICS).reduce((acc, x) => { return __spreadProps(__spreadValues({}, acc), { [x]: FONT_METRICS[x][metricsIndex] }); }, {}); } getFontSize(size) { return Math.max(1, size + this.sizeDelta); } /** * Get the style of a superscript given a base in the current style. */ get sup() { return MATHSTYLES[[SSc, SS, SSc, SS, Sc, S, Sc, S][this.id]]; } /** * Get the style of a subscript given a base in the current style. */ get sub() { return MATHSTYLES[[SSc, SSc, SSc, SSc, Sc, Sc, Sc, Sc][this.id]]; } /** * Get the style of a fraction numerator given the fraction in the current * style. * See TeXBook p 141. */ get fracNum() { return MATHSTYLES[[SSc, SS, SSc, SS, Sc, S, Tc, T][this.id]]; } /** * Get the style of a fraction denominator given the fraction in the current * style. * See TeXBook p 141. */ get fracDen() { return MATHSTYLES[[SSc, SSc, SSc, SSc, Sc, Sc, Tc, Tc][this.id]]; } /** * Get the cramped version of a style (in particular, cramping a cramped style * doesn't change the style). */ get cramp() { return MATHSTYLES[[SSc, SSc, Sc, Sc, Tc, Tc, Dc, Dc][this.id]]; } /** * Return if this style is tightly spaced (scriptstyle/scriptscriptstyle) */ get isTight() { return this.sizeDelta < 0; } }; var NUMERIC_MATHSTYLES = { 7: new Mathstyle(D, 0, false), 6: new Mathstyle(Dc, 0, true), 5: new Mathstyle(T, 0, false), 4: new Mathstyle(Tc, 0, true), 3: new Mathstyle(S, -3, false), 2: new Mathstyle(Sc, -3, true), 1: new Mathstyle(SS, -4, false), 0: new Mathstyle(SSc, -4, true) }; var MATHSTYLES = __spreadProps(__spreadValues({}, NUMERIC_MATHSTYLES), { displaystyle: NUMERIC_MATHSTYLES[D], textstyle: NUMERIC_MATHSTYLES[T], scriptstyle: NUMERIC_MATHSTYLES[S], scriptscriptstyle: NUMERIC_MATHSTYLES[SS] }); // src/core/registers-utils.ts function convertDimensionToPt(value, precision) { var _a3; if (!value) return 0; const f = { pt: 1, mm: 7227 / 2540, cm: 7227 / 254, ex: 35271 / 8192, px: 3 / 4, em: PT_PER_EM, bp: 803 / 800, dd: 1238 / 1157, pc: 12, in: 72.27, mu: 10 / 18 }[(_a3 = value.unit) != null ? _a3 : "pt"]; if (Number.isFinite(precision)) { const factor = 10 ** precision; return Math.round(value.dimension / PT_PER_EM * f * factor) / factor; } return value.dimension * f; } function convertDimensionToEm(value, precision) { if (value === null) return 0; const result = convertDimensionToPt(value) / PT_PER_EM; if (Number.isFinite(precision)) { const factor = 10 ** precision; return Math.round(result * factor) / factor; } return result; } function serializeDimension(value) { var _a3; return `${value.dimension}${(_a3 = value.unit) != null ? _a3 : "pt"}`; } function serializeGlue(value) { let result = serializeDimension(value.glue); if (value.grow && value.grow.dimension !== 0) result += ` plus ${serializeDimension(value.grow)}`; if (value.shrink && value.shrink.dimension !== 0) result += ` minus ${serializeDimension(value.shrink)}`; return result; } function serializeLatexValue(value) { var _a3, _b3; if (value === null || value === void 0) return null; let result = ""; if ("dimension" in value) result = `${value.dimension}${(_a3 = value.unit) != null ? _a3 : "pt"}`; if ("glue" in value) result = serializeGlue(value); if ("number" in value) { if (!("base" in value) || value.base === "decimal") result = Number(value.number).toString(); else if (value.base === "alpha") result = `\`${String.fromCodePoint(value.number)}`; else { const i = Math.round(value.number) >>> 0; if (value.base === "hexadecimal") { result = Number(i).toString(16).toUpperCase(); if (i <= 255) result = result.padStart(2, "0"); else if (i <= 65535) result = result.padStart(4, "0"); else if (i <= 16777215) result = result.padStart(6, "0"); else result = result.padStart(8, "0"); result = `"${result}`; } else if (value.base === "octal") { result = Number(i).toString(8); if (i <= 63) result = result.padStart(2, "0"); else if (i <= 30583) result = result.padStart(4, "0"); else result = result.padStart(8, "0"); result = `'${result}`; } } } if ("register" in value) { if ("factor" in value) { if (value.factor === -1) result = "-"; else if (value.factor !== 1) result = Number(value.factor).toString(); } if ("global" in value && value.global) result += "\\global"; result += `\\${value.register}`; } if ("string" in value) result = value.string; if ((_b3 = value.relax) != null ? _b3 : false) result += "\\relax"; return result; } function multiplyLatexValue(value, factor) { if (value === null || value === void 0) return null; if ("number" in value) return __spreadProps(__spreadValues({}, value), { number: value.number * factor }); if ("register" in value) { if ("factor" in value && value.factor) return __spreadProps(__spreadValues({}, value), { factor: value.factor * factor }); return __spreadProps(__spreadValues({}, value), { factor }); } if ("dimension" in value) return __spreadProps(__spreadValues({}, value), { dimension: value.dimension * factor }); if ("glue" in value) { if (value.shrink && value.grow) { return { glue: multiplyLatexValue(value.glue, factor), shrink: multiplyLatexValue(value.shrink, factor), grow: multiplyLatexValue(value.grow, factor) }; } if (value.shrink) { return { glue: multiplyLatexValue(value.glue, factor), shrink: multiplyLatexValue(value.shrink, factor) }; } if (value.grow) { return { glue: multiplyLatexValue(value.glue, factor), grow: multiplyLatexValue(value.grow, factor) }; } return { glue: multiplyLatexValue(value.glue, factor) }; } return null; } // src/core/registers.ts var DEFAULT_REGISTERS = { "p@": { dimension: 1 }, "z@": { dimension: 0 }, "maxdimen": { dimension: 16383.99999 }, "hfuzz": { dimension: 0.1 }, "vfuzz": { dimension: 0.1 }, "overfullrule": { dimension: 5 }, "hsize": { dimension: 6.5, unit: "in" }, "vsize": { dimension: 8.9, unit: "in" }, "parindent": { dimension: 20 }, "maxdepth": { dimension: 4 }, "splitmaxdepth": { register: "maxdimen" }, "boxmaxdepth": { register: "maxdimen" }, "delimitershortfall": { dimension: 5 }, // @todo used in makeLeftRightDelim() "nulldelimiterspace": { dimension: 1.2, unit: "pt" }, "scriptspace": { dimension: 0.5 }, // In pt. "topskip": { dimension: 10 }, "splittopskip": { dimension: 10 }, "normalbaselineskip": { dimension: 12 }, "normallineskip": { dimension: 1 }, "normallineskiplimit": { dimension: 0 }, // The vertical space between the lines for all math expressions which // allow multiple lines (see array, multline) "jot": { dimension: 3 }, // The space between adjacent `|` columns in an array definition. // From article.cls.txt:455 "doublerulesep": { dimension: 2 }, // The width of separator lines in {array} environments. "arrayrulewidth": { dimension: 0.4 }, "arraycolsep": { dimension: 5 }, // Two values from LaTeX source2e: "fboxsep": { dimension: 3 }, // From letter.dtx:1626 "fboxrule": { dimension: 0.4 }, // From letter.dtx:1627 "z@skip": { glue: { dimension: 0 }, shrink: { dimension: 0 }, grow: { dimension: 0 } }, "hideskip": { glue: { dimension: -1e3 }, grow: { dimension: 1, unit: "fill" } }, // LaTeX "@flushglue": { glue: { dimension: 0 }, grow: { dimension: 1, unit: "fill" } }, // LaTeX "parskip": { glue: { dimension: 0 }, grow: { dimension: 1 } }, // @todo the "shortskip" are used if the formula starts to the right of the // line before (i.e. centered and short line before) "abovedisplayskip": { glue: { dimension: 12 }, grow: { dimension: 3 }, shrink: { dimension: 9 } }, "abovedisplayshortskip": { glue: { dimension: 0 }, grow: { dimension: 3 } }, "belowdisplayskip": { glue: { dimension: 12 }, grow: { dimension: 3 }, shrink: { dimension: 9 } }, "belowdisplayshortskip": { glue: { dimension: 7 }, grow: { dimension: 3 }, shrink: { dimension: 4 } }, "parfillskip": { glue: { dimension: 0 }, grow: { dimension: 1, unit: "fil" } }, "thinmuskip": { glue: { dimension: 3, unit: "mu" } }, "medmuskip": { glue: { dimension: 4, unit: "mu" }, grow: { dimension: 2, unit: "mu" }, shrink: { dimension: 4, unit: "mu" } }, "thickmuskip": { glue: { dimension: 5, unit: "mu" }, grow: { dimension: 5, unit: "mu" } }, "smallskipamount": { glue: { dimension: 3 }, grow: { dimension: 1 }, shrink: { dimension: 1 } }, "medskipamount": { glue: { dimension: 6 }, grow: { dimension: 2 }, shrink: { dimension: 3 } }, "bigskipamount": { glue: { dimension: 12 }, grow: { dimension: 2 }, shrink: { dimension: 4 } }, // From TeXBook p.348 // See also https://ctan.math.washington.edu/tex-archive/info/macros2e/macros2e.pdf // 'voidb@x' "pretolerance": 100, "tolerance": 200, "hbadness": 1e3, "vbadness": 1e3, "linepenalty": 10, "hyphenpenalty": 50, "exhyphenpenalty": 50, "binoppenalty": 700, "relpenalty": 500, "clubpenalty": 150, "widowpenalty": 150, "displaywidowpenalty": 50, "brokenpenalty": 100, "predisplaypenalty": 1e4, "doublehyphendemerits": 1e4, "finalhyphendemerits": 5e3, "adjdemerits": 1e4, "tracinglostchars": 1, "uchyph": 1, "delimiterfactor": 901, "defaulthyphenchar": "\\-", "defaultskewchar": -1, "newlinechar": -1, "showboxbreadth": 5, "showboxdepth": 3, "errorcontextlines": 5, "interdisplaylinepenalty": 100, "interfootnotelinepenalty": 100, "baselineSkip": 1.2, "arraystretch": 1, "month": (/* @__PURE__ */ new Date()).getMonth() + 1, "day": (/* @__PURE__ */ new Date()).getDate(), "year": (/* @__PURE__ */ new Date()).getFullYear() }; function getDefaultRegisters() { return __spreadValues({}, DEFAULT_REGISTERS); } // src/core/context-utils.ts function getDefaultContext() { return { registers: getDefaultRegisters(), smartFence: false, renderPlaceholder: void 0, placeholderSymbol: "\u25A2", letterShapeStyle: l10n.locale.startsWith("fr") ? "french" : "tex", minFontScale: 0, colorMap: defaultColorMap, backgroundColorMap: defaultBackgroundColorMap, getMacro: (token) => getMacroDefinition(token, getMacros()) }; } // src/core/context.ts var Context = class _Context { constructor(options, style) { var _a3, _b3, _c2, _d2, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o; let template; if (options == null ? void 0 : options.parent) { this.parent = options.parent; template = options.parent; this.registers = {}; } else { template = __spreadValues(__spreadValues({}, getDefaultContext()), (_a3 = options == null ? void 0 : options.from) != null ? _a3 : {}); this.registers = template.registers; } if (template.atomIdsSettings) this.atomIdsSettings = __spreadValues({}, template.atomIdsSettings); this.renderPlaceholder = template.renderPlaceholder; this.isPhantom = (_d2 = (_c2 = options == null ? void 0 : options.isPhantom) != null ? _c2 : (_b3 = this.parent) == null ? void 0 : _b3.isPhantom) != null ? _d2 : false; this.letterShapeStyle = template.letterShapeStyle; this.minFontScale = template.minFontScale; if ((style == null ? void 0 : style.color) && style.color !== "none") this.color = style.color; else this.color = (_f = (_e = this.parent) == null ? void 0 : _e.color) != null ? _f : ""; if ((style == null ? void 0 : style.backgroundColor) && style.backgroundColor !== "none") this.backgroundColor = style.backgroundColor; else this.backgroundColor = (_h = (_g = this.parent) == null ? void 0 : _g.backgroundColor) != null ? _h : ""; if ((style == null ? void 0 : style.fontSize) && style.fontSize !== "auto" && style.fontSize !== ((_i = this.parent) == null ? void 0 : _i.size)) this.size = style.fontSize; else this.size = (_k = (_j = this.parent) == null ? void 0 : _j.size) != null ? _k : DEFAULT_FONT_SIZE; let mathstyle = (_m = (_l = this.parent) == null ? void 0 : _l.mathstyle) != null ? _m : MATHSTYLES.displaystyle; if (typeof (options == null ? void 0 : options.mathstyle) === "string") { if (template instanceof _Context) { switch (options.mathstyle) { case "cramp": mathstyle = mathstyle.cramp; break; case "superscript": mathstyle = mathstyle.sup; break; case "subscript": mathstyle = mathstyle.sub; break; case "numerator": mathstyle = mathstyle.fracNum; break; case "denominator": mathstyle = mathstyle.fracDen; break; } } switch (options.mathstyle) { case "textstyle": mathstyle = MATHSTYLES.textstyle; break; case "displaystyle": mathstyle = MATHSTYLES.displaystyle; break; case "scriptstyle": mathstyle = MATHSTYLES.scriptstyle; break; case "scriptscriptstyle": mathstyle = MATHSTYLES.scriptscriptstyle; break; case "": case "auto": break; } } this.mathstyle = mathstyle; this.smartFence = template.smartFence; this.placeholderSymbol = template.placeholderSymbol; this.colorMap = (_n = template.colorMap) != null ? _n : (x) => x; this.backgroundColorMap = (_o = template.backgroundColorMap) != null ? _o : (x) => x; this.getMacro = template.getMacro; console.assert(this.parent !== void 0 || this.registers !== void 0); } makeID() { if (!this.atomIdsSettings) return void 0; if (this.atomIdsSettings.overrideID) return this.atomIdsSettings.overrideID; if (typeof this.atomIdsSettings.seed !== "number") { return `${Date.now().toString(36).slice(-2)}${Math.floor( Math.random() * 1e5 ).toString(36)}`; } const result = this.atomIdsSettings.seed.toString(36); this.atomIdsSettings.seed += 1; return result; } // Scale a value, in em, to account for the fontsize and mathstyle // of this context scale(value) { return value * this.effectiveFontSize; } get scalingFactor() { if (!this.parent) return 1; return this.effectiveFontSize / this.parent.effectiveFontSize; } get isDisplayStyle() { return this.mathstyle.id === D || this.mathstyle.id === Dc; } get isCramped() { return this.mathstyle.cramped; } get isTight() { return this.mathstyle.isTight; } get metrics() { return this.mathstyle.metrics; } // Return the font size, in em relative to the mathfield fontsize, // accounting both for the base font size and the mathstyle get effectiveFontSize() { return Math.max( FONT_SCALE[Math.max(1, this.size + this.mathstyle.sizeDelta)], this.minFontScale ); } getRegister(name) { var _a3; if ((_a3 = this.registers) == null ? void 0 : _a3[name]) return this.registers[name]; if (this.parent) return this.parent.getRegister(name); return void 0; } getRegisterAsNumber(name) { const val = this.getRegister(name); if (typeof val === "number") return val; if (typeof val === "string") return Number(val); return void 0; } getRegisterAsGlue(name) { var _a3; if ((_a3 = this.registers) == null ? void 0 : _a3[name]) { const value = this.registers[name]; if (typeof value === "object" && "glue" in value) return value; else if (typeof value === "object" && "dimension" in value) return { glue: { dimension: value.dimension } }; else if (typeof value === "number") return { glue: { dimension: value } }; return void 0; } if (this.parent) return this.parent.getRegisterAsGlue(name); return void 0; } getRegisterAsEm(name, precision) { return convertDimensionToEm(this.getRegisterAsDimension(name), precision); } getRegisterAsDimension(name) { var _a3; if ((_a3 = this.registers) == null ? void 0 : _a3[name]) { const value = this.registers[name]; if (typeof value === "object" && "glue" in value) return value.glue; else if (typeof value === "object" && "dimension" in value) return value; else if (typeof value === "number") return { dimension: value }; return void 0; } if (this.parent) return this.parent.getRegisterAsDimension(name); return void 0; } setRegister(name, value) { if (value === void 0) { delete this.registers[name]; return; } this.registers[name] = value; } evaluate(value) { if (!value || !("register" in value)) return value; let context = this; if ("global" in value && value.global) while (context.parent) context = context.parent; let factor = 1; if ("factor" in value && value.factor !== 1 && value.factor !== void 0) factor = value.factor; const val = context.getRegister(value.register); if (val === void 0) return void 0; if (typeof val === "string") return { string: Number(val).toString() + val }; if (typeof val === "number") return { number: factor * val }; const result = context.evaluate(val); if (result === void 0) return void 0; if ("string" in result) return { string: Number(val).toString() + result.string }; if ("number" in result) return { number: factor * result.number }; if ("dimension" in result) return __spreadProps(__spreadValues({}, result), { dimension: factor * result.dimension }); if ("glue" in result) { return __spreadProps(__spreadValues({}, result), { glue: __spreadProps(__spreadValues({}, result.glue), { dimension: factor * result.glue.dimension }), shrink: result.shrink ? __spreadProps(__spreadValues({}, result.shrink), { dimension: factor * result.shrink.dimension }) : void 0, grow: result.grow ? __spreadProps(__spreadValues({}, result.grow), { dimension: factor * result.grow.dimension }) : void 0 }); } return value; } toDimension(value) { const val = this.evaluate(value); if (val === void 0) return null; if ("dimension" in val) return val; if ("glue" in val) return val.glue; if ("number" in val) return { dimension: val.number }; return null; } toEm(value, precision) { if (value === null) return 0; const dimen = this.toDimension(value); if (dimen === null) return 0; return convertDimensionToPt(dimen, precision) / PT_PER_EM; } toNumber(value) { if (value === null) return null; const val = this.evaluate(value); if (val === void 0) return null; if ("number" in val) return val.number; if ("dimension" in val) return val.dimension; if ("glue" in val) return val.glue.dimension; if ("string" in val) return Number(val.string); return null; } toColor(value) { var _a3, _b3; if (value === null) return null; const val = this.evaluate(value); if (val === void 0) return null; if ("string" in val) return (_b3 = (_a3 = this.colorMap) == null ? void 0 : _a3.call(this, val.string)) != null ? _b3 : val.string; return null; } toBackgroundColor(value) { var _a3, _b3; if (value === null) return null; const val = this.evaluate(value); if (val === void 0) return null; if ("string" in val) return (_b3 = (_a3 = this.backgroundColorMap) == null ? void 0 : _a3.call(this, val.string)) != null ? _b3 : val.string; return null; } }; // src/core/atom-class.ts var NAMED_BRANCHES = [ "body", "above", "below", "superscript", "subscript" ]; function isNamedBranch(branch) { return typeof branch === "string" && NAMED_BRANCHES.includes(branch); } function isCellBranch(branch) { return branch !== void 0 && Array.isArray(branch) && branch.length === 2; } var Atom = class _Atom { constructor(options) { var _a3, _b3, _c2, _d2, _e, _f; this.type = options.type; if (typeof options.value === "string") this.value = options.value; this.command = (_b3 = (_a3 = options.command) != null ? _a3 : this.value) != null ? _b3 : ""; this.mode = (_c2 = options.mode) != null ? _c2 : "math"; if (options.isFunction) this.isFunction = true; if (options.limits) this.subsupPlacement = options.limits; this.style = __spreadValues({}, options.style); this.displayContainsHighlight = (_d2 = options.displayContainsHighlight) != null ? _d2 : false; this.captureSelection = (_e = options.captureSelection) != null ? _e : false; this.skipBoundary = (_f = options.skipBoundary) != null ? _f : false; if (options.verbatimLatex !== void 0 && options.verbatimLatex !== null) this.verbatimLatex = options.verbatimLatex; if (options.args) this.args = options.args; if (options.body) this.body = options.body; this._changeCounter = 0; } /** * Return a list of boxes equivalent to atoms. * * While an atom represent an abstract element (for example 'genfrac'), * a box corresponds to something to draw on screen (a character, a line, * etc...). * * @param context Font family, variant, size, color, and other info useful * to render an expression */ static createBox(context, atoms, options) { var _a3; if (!atoms) return null; const runs = getStyleRuns(atoms); const boxes = []; for (const run of runs) { const style = run[0].style; const box = renderStyleRun(context, run, { style: { color: style.color, backgroundColor: style.backgroundColor, fontSize: style.fontSize } }); if (box) boxes.push(box); } if (boxes.length === 0) return null; const classes = ((_a3 = options == null ? void 0 : options.classes) != null ? _a3 : "").trim(); if (boxes.length === 1 && !classes && !(options == null ? void 0 : options.type)) return boxes[0].wrap(context); return new Box(boxes, { classes, type: options == null ? void 0 : options.type }).wrap(context); } /** * Given an atom or an array of atoms, return a LaTeX string representation */ static serialize(value, options) { return Mode.serialize(value, options); } /** * The common ancestor between two atoms */ static commonAncestor(a, b) { if (a === b) return a.parent; if (a.parent === b.parent) return a.parent; const parents = /* @__PURE__ */ new WeakSet(); let { parent } = a; while (parent) { parents.add(parent); parent = parent.parent; } parent = b.parent; while (parent) { if (parents.has(parent)) return parent; parent = parent.parent; } console.assert(Boolean(parent)); return void 0; } static fromJson(json) { if (typeof json === "string") return new _Atom({ type: "mord", value: json, mode: "math" }); return new _Atom(json); } get latexMode() { if (this.mode === "math") return "math"; return "text"; } toJson() { const result = {}; if (this.type) result.type = this.type; if (this.mode !== "math") result.mode = this.mode; if (this.command && this.command !== this.value) result.command = this.command; if (this.value !== void 0) result.value = this.value; if (this.style && Object.keys(this.style).length > 0) result.style = __spreadValues({}, this.style); if (this.verbatimLatex !== void 0) result.verbatimLatex = this.verbatimLatex; if (this.subsupPlacement) result.subsupPlacement = this.subsupPlacement; if (this.explicitSubsupPlacement) result.explicitSubsupPlacement = true; if (this.isFunction) result.isFunction = true; if (this.displayContainsHighlight) result.displayContainsHighlight = true; if (this.isExtensibleSymbol) result.isExtensibleSymbol = true; if (this.skipBoundary) result.skipBoundary = true; if (this.captureSelection) result.captureSelection = true; if (this.args) result.args = argumentsToJson(this.args); if (this._branches) { for (const branch of Object.keys(this._branches)) { if (this._branches[branch]) { result[branch] = this._branches[branch].filter( (x) => x.type !== "first" ).map((x) => x.toJson()); } } } if (result.type === "mord") { if (Object.keys(result).length === 2 && "value" in result) return result.value; } return result; } // Used to detect changes and send appropriate notifications get changeCounter() { if (this.parent) return this.parent.changeCounter; return this._changeCounter; } set isDirty(dirty) { if (dirty) { if (!this.parent) this._changeCounter++; if ("verbatimLatex" in this) this.verbatimLatex = void 0; this._children = void 0; let { parent: atom } = this; while (atom) { if (!atom.parent) atom._changeCounter++; if ("verbatimLatex" in atom) atom.verbatimLatex = void 0; atom._children = void 0; atom = atom.parent; } } } /** * Serialize the atom to LaTeX. * Used internally by Mode: does not serialize styling. To serialize * one or more atoms, use `Atom.serialize()` */ _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); if (this.body && this.command) { return joinLatex([ latexCommand(this.command, this.bodyToLatex(options)), this.supsubToLatex(options) ]); } if (this.body) { return joinLatex([ this.bodyToLatex(options), this.supsubToLatex(options) ]); } if (!this.value || this.value === "\u200B") return ""; return this.command; } bodyToLatex(options) { var _a3; return Mode.serialize(this.body, __spreadProps(__spreadValues({}, options), { defaultMode: (_a3 = options.defaultMode) != null ? _a3 : this.latexMode })); } aboveToLatex(options) { return Mode.serialize(this.above, options); } belowToLatex(options) { return Mode.serialize(this.below, options); } supsubToLatex(options) { let result = ""; options = __spreadProps(__spreadValues({}, options), { defaultMode: "math" }); if (this.branch("subscript") !== void 0) { const sub = Mode.serialize(this.subscript, options); if (sub.length === 0) result += "_{}"; else if (sub.length === 1) { if (/^[0-9]$/.test(sub)) result += `_${sub}`; else result += `_{${sub}}`; } else result += `_{${sub}}`; } if (this.branch("superscript") !== void 0) { const sup = Mode.serialize(this.superscript, options); if (sup.length === 0) result += "^{}"; else if (sup.length === 1) { if (sup === "\u2032") result += "^\\prime "; else if (sup === "\u2033") result += "^\\doubleprime "; else if (/^[0-9]$/.test(sup)) result += `^${sup}`; else result += `^{${sup}}`; } else result += `^{${sup}}`; } return result; } get treeDepth() { let result = 1; let atom = this.parent; while (atom) { atom = atom.parent; result += 1; } return result; } get inCaptureSelection() { let atom = this; while (atom) { if (atom.captureSelection) return true; atom = atom.parent; } return false; } /** Return the parent editable prompt, if it exists */ get parentPrompt() { let atom = this.parent; while (atom) { if (atom.type === "prompt" && !atom.captureSelection) return atom; atom = atom.parent; } return null; } /** * Return the atoms in the branch, if it exists, otherwise null */ branch(name) { if (!isNamedBranch(name)) return void 0; if (!this._branches) return void 0; return this._branches[name]; } /** * Return all the branches that exist. * Some of them may be empty. */ get branches() { if (!this._branches) return []; const result = []; for (const branch of NAMED_BRANCHES) if (this._branches[branch]) result.push(branch); return result; } /** * Return the atoms in the branch, if it exists, otherwise create it */ createBranch(name) { console.assert(isNamedBranch(name)); if (!isNamedBranch(name)) return []; if (!this._branches) { this._branches = { [name]: [this.makeFirstAtom(name)] }; } else if (!this._branches[name]) this._branches[name] = [this.makeFirstAtom(name)]; this.isDirty = true; return this._branches[name]; } get row() { if (!isCellBranch(this.parentBranch)) return -1; return this.parentBranch[0]; } get col() { if (!isCellBranch(this.parentBranch)) return -1; return this.parentBranch[1]; } get body() { var _a3; return (_a3 = this._branches) == null ? void 0 : _a3.body; } set body(atoms) { this.setChildren(atoms, "body"); } get superscript() { var _a3; return (_a3 = this._branches) == null ? void 0 : _a3.superscript; } set superscript(atoms) { this.setChildren(atoms, "superscript"); } get subscript() { var _a3; return (_a3 = this._branches) == null ? void 0 : _a3.subscript; } set subscript(atoms) { this.setChildren(atoms, "subscript"); } get above() { var _a3; return (_a3 = this._branches) == null ? void 0 : _a3.above; } set above(atoms) { this.setChildren(atoms, "above"); } get below() { var _a3; return (_a3 = this._branches) == null ? void 0 : _a3.below; } set below(atoms) { this.setChildren(atoms, "below"); } get computedStyle() { var _a3, _b3; const hadVerbatimColor = typeof this.style.verbatimColor === "string"; const hadVerbatimBackgroundColor = typeof this.style.verbatimBackgroundColor === "string"; const result = __spreadValues(__spreadValues({}, (_b3 = (_a3 = this.parent) == null ? void 0 : _a3.computedStyle) != null ? _b3 : {}), this.style); delete result.variant; delete result.variantStyle; if (!hadVerbatimBackgroundColor) delete result.verbatimBackgroundColor; if (!hadVerbatimColor) delete result.verbatimColor; return result; } applyStyle(style) { this.isDirty = true; this.style = __spreadValues(__spreadValues({}, this.style), style); if (this.style.fontFamily === "none") delete this.style.fontFamily; if (this.style.fontShape === "auto") delete this.style.fontShape; if (this.style.fontSeries === "auto") delete this.style.fontSeries; if (this.style.color === "none") { delete this.style.color; delete this.style.verbatimColor; } if (this.style.backgroundColor === "none") { delete this.style.backgroundColor; delete this.style.verbatimBackgroundColor; } if (this.style.fontSize === "auto") delete this.style.fontSize; for (const child of this.children) child.applyStyle(style); } getInitialBaseElement() { var _a3, _b3, _c2; if (this.hasEmptyBranch("body")) return this; console.assert(((_a3 = this.body) == null ? void 0 : _a3[0].type) === "first"); return (_c2 = (_b3 = this.body[1]) == null ? void 0 : _b3.getInitialBaseElement()) != null ? _c2 : this; } getFinalBaseElement() { if (this.hasEmptyBranch("body")) return this; return this.body[this.body.length - 1].getFinalBaseElement(); } isCharacterBox() { if (this.type === "leftright" || this.type === "genfrac" || this.type === "subsup" || this.type === "delim" || this.type === "array" || this.type === "surd") return false; return this.getFinalBaseElement().type === "mord"; } hasEmptyBranch(branch) { const atoms = this.branch(branch); if (!atoms) return true; console.assert(atoms.length > 0); console.assert(atoms[0].type === "first"); return atoms.length === 1; } /* * Setting `null` does nothing * Setting `[]` adds an empty list (the branch is created) * The children should *not* start with a `"first"` atom: * the `first` atom will be added if necessary */ setChildren(children, branch) { var _a3; if (!children) return; console.assert(isNamedBranch(branch)); if (!isNamedBranch(branch)) return; console.assert(((_a3 = children[0]) == null ? void 0 : _a3.type) !== "first"); const newBranch = [this.makeFirstAtom(branch), ...children]; if (this._branches) this._branches[branch] = newBranch; else this._branches = { [branch]: newBranch }; for (const child of children) { child.parent = this; child.parentBranch = branch; } this.isDirty = true; } makeFirstAtom(branch) { const result = new _Atom({ type: "first", mode: this.mode }); result.parent = this; result.parentBranch = branch; return result; } addChild(child, branch) { console.assert(child.type !== "first"); this.createBranch(branch).push(child); this.isDirty = true; child.parent = this; child.parentBranch = branch; } addChildBefore(child, before) { console.assert(before.parentBranch !== void 0); const branch = this.createBranch(before.parentBranch); branch.splice(branch.indexOf(before), 0, child); this.isDirty = true; child.parent = this; child.parentBranch = before.parentBranch; } addChildAfter(child, after) { console.assert(after.parentBranch !== void 0); const branch = this.createBranch(after.parentBranch); branch.splice(branch.indexOf(after) + 1, 0, child); this.isDirty = true; child.parent = this; child.parentBranch = after.parentBranch; } addChildren(children, branchName) { const branch = this.createBranch(branchName); for (const child of children) { child.parent = this; child.parentBranch = branchName; branch.push(child); } this.isDirty = true; } /** * Return the last atom that was added */ addChildrenAfter(children, after) { console.assert(children.length === 0 || children[0].type !== "first"); console.assert(after.parentBranch !== void 0); const branch = this.createBranch(after.parentBranch); branch.splice(branch.indexOf(after) + 1, 0, ...children); this.isDirty = true; for (const child of children) { child.parent = this; child.parentBranch = after.parentBranch; } return children[children.length - 1]; } removeBranch(name) { const children = this.branch(name); if (isNamedBranch(name)) this._branches[name] = void 0; if (!children) return []; for (const child of children) { child.parent = void 0; child.parentBranch = void 0; } console.assert(children[0].type === "first"); children.shift(); this.isDirty = true; return children; } removeChild(child) { console.assert(child.parent === this); if (child.type === "first") return; const branch = this.branch(child.parentBranch); const index = branch.indexOf(child); console.assert(index >= 0); branch.splice(index, 1); this.isDirty = true; child.parent = void 0; child.parentBranch = void 0; } get siblings() { if (!this.parent) return []; return this.parent.branch(this.parentBranch); } get firstSibling() { return this.siblings[0]; } get lastSibling() { const { siblings } = this; return siblings[siblings.length - 1]; } get isFirstSibling() { return this === this.firstSibling; } get isLastSibling() { return this === this.lastSibling; } get hasNoSiblings() { return this.siblings.length === 1; } get leftSibling() { console.assert(this.parent !== void 0); const siblings = this.parent.branch(this.parentBranch); return siblings[siblings.indexOf(this) - 1]; } get rightSibling() { console.assert(this.parent !== void 0); const siblings = this.parent.branch(this.parentBranch); return siblings[siblings.indexOf(this) + 1]; } get hasChildren() { return Boolean(this._branches && this.children.length > 0); } get firstChild() { console.assert(this.hasChildren); return this.children[0]; } get lastChild() { console.assert(this.hasChildren); const { children } = this; return children[children.length - 1]; } /** * All the children of this atom. * * The order of the atoms is the order in which they * are navigated using the keyboard. */ get children() { if (this._children) return this._children; if (!this._branches) return []; const result = []; for (const branchName of NAMED_BRANCHES) { if (this._branches[branchName]) { for (const x of this._branches[branchName]) { result.push(...x.children); result.push(x); } } } this._children = result; return result; } /** * Render this atom as a box. * * The parent context (color, size...) will be applied * to the result. * */ render(parentContext) { if (this.type === "first" && !parentContext.atomIdsSettings) return null; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.render) return def.render(this, parentContext); const context = new Context({ parent: parentContext }, this.style); let result = this.createBox(context, { classes: !this.parent ? "ML__base" : "" }); if (!result) return null; if (!this.subsupPlacement && (this.superscript || this.subscript)) { result = this.attachSupsub(context, { base: result }); } return result.wrap(context); } attachSupsub(parentContext, options) { var _a3; const base = options.base; const superscript = this.superscript; const subscript = this.subscript; if (!superscript && !subscript) return base; let supBox = null; let subBox = null; const isCharacterBox = (_a3 = options.isCharacterBox) != null ? _a3 : this.isCharacterBox(); let supShift = 0; if (superscript) { const context = new Context({ parent: parentContext, mathstyle: "superscript" }); supBox = _Atom.createBox(context, superscript); if (!isCharacterBox) { supShift = base.height - parentContext.metrics.supDrop * context.scalingFactor; } } let subShift = 0; if (subscript) { const context = new Context({ parent: parentContext, mathstyle: "subscript" }); subBox = _Atom.createBox(context, subscript); if (!isCharacterBox) { subShift = base.depth + parentContext.metrics.subDrop * context.scalingFactor; } } let minSupShift; if (parentContext.isDisplayStyle) minSupShift = parentContext.metrics.sup1; else if (parentContext.isCramped) minSupShift = parentContext.metrics.sup3; else minSupShift = parentContext.metrics.sup2; const scriptspace = 0.5 / PT_PER_EM / parentContext.scalingFactor; let supsub = null; if (subBox && supBox) { supShift = Math.max( supShift, minSupShift, supBox.depth + 0.25 * parentContext.metrics.xHeight ); subShift = Math.max(subShift, parentContext.metrics.sub2); const ruleWidth = parentContext.metrics.defaultRuleThickness; if (supShift - supBox.depth - (subBox.height - subShift) < 4 * ruleWidth) { subShift = 4 * ruleWidth - (supShift - supBox.depth) + subBox.height; const psi = 0.8 * parentContext.metrics.xHeight - (supShift - supBox.depth); if (psi > 0) { supShift += psi; subShift -= psi; } } const slant = this.isExtensibleSymbol && base.italic ? -base.italic : 0; supsub = new VBox({ individualShift: [ { box: subBox, shift: subShift, marginLeft: slant }, { box: supBox, shift: -supShift } ] }).wrap(parentContext); } else if (subBox && !supBox) { subShift = Math.max( subShift, parentContext.metrics.sub1, subBox.height - 0.8 * X_HEIGHT ); supsub = new VBox({ shift: subShift, children: [ { box: subBox, marginRight: scriptspace, marginLeft: this.isCharacterBox() ? -base.italic : 0 } ] }); } else if (!subBox && supBox) { supShift = Math.max( supShift, minSupShift, supBox.depth + 0.25 * X_HEIGHT ); supsub = new VBox({ shift: -supShift, children: [{ box: supBox, marginRight: scriptspace }] }); } return new Box( [ base, new Box(supsub, { caret: this.caret, isSelected: this.isSelected, classes: "msubsup" }) ], { type: options.type } ); } attachLimits(ctx, options) { const above = this.superscript ? _Atom.createBox( new Context({ parent: ctx, mathstyle: "superscript" }, this.style), this.superscript ) : null; const below = this.subscript ? _Atom.createBox( new Context({ parent: ctx, mathstyle: "subscript" }, this.style), this.subscript ) : null; if (!above && !below) return options.base.wrap(ctx); return makeLimitsStack(ctx, __spreadProps(__spreadValues({}, options), { above, below })); } bind(context, box) { if (!box || context.isPhantom || this.value === "\u200B") return box; let parent = this.parent; while (parent && !parent.captureSelection) parent = parent.parent; if (parent == null ? void 0 : parent.captureSelection) return box; if (!this.id) this.id = context.makeID(); box.atomID = this.id; return box; } /** * Create a box with the specified body. */ createBox(context, options) { var _a3, _b3, _c2, _d2; const value = (_a3 = this.value) != null ? _a3 : this.body; const type = (_b3 = options == null ? void 0 : options.boxType) != null ? _b3 : boxType(this.type); let classes = (_c2 = options == null ? void 0 : options.classes) != null ? _c2 : ""; if (this.mode === "text") classes += " ML__text"; const result = typeof value === "string" || value === void 0 ? new Box(value != null ? value : null, { type, isSelected: this.isSelected, mode: this.mode, maxFontSize: context.scalingFactor, style: __spreadProps(__spreadValues({ variant: "normal" }, this.style), { fontSize: Math.max( 1, context.size + context.mathstyle.sizeDelta ) }), letterShapeStyle: context.letterShapeStyle, classes }) : (_d2 = _Atom.createBox(context, value, { type, classes })) != null ? _d2 : new Box(null); if (context.isTight) result.isTight = true; if (this.mode !== "math" || this.style.variant === "main") result.italic = 0; result.right = result.italic; this.bind(context, result); if (this.caret) { if (!this.superscript && !this.subscript) result.caret = this.caret; } return result; } /** Return true if a digit, or a decimal point, or a french decimal `{,}` */ isDigit() { var _a3; if (this.type === "mord" && this.value) return /^[\d,\.]$/.test(this.value); if (this.type === "group" && ((_a3 = this.body) == null ? void 0 : _a3.length) === 2) return this.body[0].type === "first" && this.body[1].value === ","; return false; } asDigit() { var _a3; if (this.type === "mord" && this.value && /^[\d,\.]$/.test(this.value)) return this.value; if (this.type === "group" && ((_a3 = this.body) == null ? void 0 : _a3.length) === 2) { if (this.body[0].type === "first" && this.body[1].value === ",") return "."; } return ""; } }; function getStyleRuns(atoms) { let style = void 0; const runs = []; let run = []; for (const atom of atoms) { if (!style && !atom.style) run.push(atom); else { const atomStyle = atom.computedStyle; if (style && atomStyle.color === style.color && atomStyle.backgroundColor === style.backgroundColor && atomStyle.fontSize === style.fontSize) { run.push(atom); } else { if (run.length > 0) runs.push(run); run = [atom]; style = atomStyle; } } } if (run.length > 0) runs.push(run); return runs; } function renderStyleRun(parentContext, atoms, options) { var _a3, _b3, _c2, _d2, _e; if (!atoms || atoms.length === 0) return null; const context = new Context({ parent: parentContext }, options.style); const displaySelection = !((_a3 = context.atomIdsSettings) == null ? void 0 : _a3.groupNumbers); let boxes = []; if (atoms.length === 1) { const atom = atoms[0]; const box = atom.render(context); if (box) { if (displaySelection && atom.isSelected) box.selected(true); boxes = [box]; } } else { let digitOrTextStringID = ""; let lastWasDigit = true; for (const atom of atoms) { if (((_b3 = context.atomIdsSettings) == null ? void 0 : _b3.groupNumbers) && digitOrTextStringID && (lastWasDigit && atom.isDigit() || !lastWasDigit && isText(atom))) context.atomIdsSettings.overrideID = digitOrTextStringID; const box = atom.render(context); if (context.atomIdsSettings) context.atomIdsSettings.overrideID = void 0; if (box) { if ((_c2 = context.atomIdsSettings) == null ? void 0 : _c2.groupNumbers) { if (atom.isDigit() || isText(atom)) { if (!digitOrTextStringID || lastWasDigit !== atom.isDigit()) { lastWasDigit = atom.isDigit(); digitOrTextStringID = (_d2 = atom.id) != null ? _d2 : ""; } } if (digitOrTextStringID && (!(atom.isDigit() || isText(atom)) || !atom.hasEmptyBranch("superscript") || !atom.hasEmptyBranch("subscript"))) { digitOrTextStringID = ""; } } if (displaySelection && atom.isSelected) box.selected(true); boxes.push(box); } } } if (boxes.length === 0) return null; const result = new Box(boxes, __spreadProps(__spreadValues({ isTight: context.isTight }, options), { type: (_e = options.type) != null ? _e : "lift" })); result.isSelected = boxes.every((x) => x.isSelected); return result.wrap(context); } function isText(atom) { return atom.mode === "text"; } function argumentsToJson(args) { return args.map((arg) => { if (arg === null) return ""; if (Array.isArray(arg) && arg[0] instanceof Atom) return { atoms: arg.map((x) => x.toJson()) }; if (typeof arg === "object" && "group" in arg) return { group: arg.group.map((x) => x.toJson()) }; return arg; }); } // src/atoms/text.ts var TextAtom = class _TextAtom extends Atom { constructor(command, value, style) { super({ type: "text", command, mode: "text", displayContainsHighlight: true }); this.value = value; this.verbatimLatex = value; this.applyStyle(style); } static fromJson(json) { return new _TextAtom(json.command, json.value, json.style); } render(context) { const result = this.createBox(context); if (this.caret) result.caret = this.caret; return result; } _serialize(_options) { var _a3; return (_a3 = this.verbatimLatex) != null ? _a3 : charToLatex("text", this.value.codePointAt(0)); } }; // src/editor-model/selection-utils.ts function compareSelection(a, b) { if (a.direction === b.direction) { const l = a.ranges.length; if (b.ranges.length === l) { let i = 0; while (i < l && compareRange(a.ranges[i], b.ranges[i]) === "equal") i++; return i === l ? "equal" : "different"; } } return "different"; } function compareRange(a, b) { if (a[0] === b[0] && a[1] === b[1]) return "equal"; return "different"; } function range(selection) { let first = Infinity; let last = -Infinity; for (const range2 of selection.ranges) { first = Math.min(first, range2[0], range2[1]); last = Math.max(last, range2[0], range2[1]); } return [first, last]; } function isOffset(value) { return typeof value === "number" && !Number.isNaN(value); } function isRange(value) { return Array.isArray(value) && value.length === 2; } function isSelection(value) { return value !== void 0 && value !== null && typeof value === "object" && "ranges" in value && Array.isArray(value.ranges); } function getMode(model, offset) { const atom = model.at(offset); let result; if (atom) { result = atom.mode; let ancestor = atom.parent; while (!result && ancestor) { if (ancestor) result = ancestor.mode; ancestor = ancestor.parent; } } return result; } // src/editor/shortcuts.ts function validateShortcut(siblings, shortcut) { if (!shortcut) return ""; if (typeof shortcut === "string") return shortcut; if (!siblings || shortcut.after === void 0) return shortcut.value; let nothing = false; let letter = false; let digit = false; let isFunction = false; let frac = false; let surd = false; let binop = false; let relop = false; let operator = false; let punct = false; let array = false; let openfence = false; let closefence = false; let text = false; let space = false; let sibling = siblings[0]; let index = 0; while ((sibling == null ? void 0 : sibling.type) && /^(subsup|placeholder)$/.test(sibling.type)) { index += 1; sibling = siblings[index]; } nothing = !sibling || sibling.type === "first"; if (sibling) { text = sibling.mode === "text"; letter = !text && sibling.type === "mord" && LETTER.test(sibling.value); digit = !text && sibling.type === "mord" && /\d+$/.test(sibling.value); isFunction = !text && sibling.isFunction; frac = sibling.type === "genfrac"; surd = sibling.type === "surd"; binop = sibling.type === "mbin"; relop = sibling.type === "mrel"; operator = sibling.type === "mop" || sibling.type === "operator" || sibling.type === "extensible-symbol"; punct = sibling.type === "mpunct" || sibling.type === "minner"; array = sibling.type === "array"; openfence = sibling.type === "mopen"; closefence = sibling.type === "mclose" || sibling.type === "leftright"; space = sibling.type === "space"; } if (shortcut.after.includes("nothing") && nothing || shortcut.after.includes("letter") && letter || shortcut.after.includes("digit") && digit || shortcut.after.includes("function") && isFunction || shortcut.after.includes("frac") && frac || shortcut.after.includes("surd") && surd || shortcut.after.includes("binop") && binop || shortcut.after.includes("relop") && relop || shortcut.after.includes("operator") && operator || shortcut.after.includes("punct") && punct || shortcut.after.includes("array") && array || shortcut.after.includes("openfence") && openfence || shortcut.after.includes("closefence") && closefence || shortcut.after.includes("text") && text || shortcut.after.includes("space") && space) return shortcut.value; return ""; } function getInlineShortcut(context, s, shortcuts) { if (!shortcuts) return ""; return validateShortcut(context, shortcuts[s]); } // src/editor/shortcuts-definitions.ts var INLINE_SHORTCUTS = { "&": "\\&", "%": "\\%", "$": "\\$", // Primes "''": "^{\\doubleprime}", "'''": "^{\\prime\\prime\\prime}", "''''": "^{\\prime\\prime\\prime\\prime}", // Greek letters "alpha": "\\alpha", "delta": "\\delta", "Delta": "\\Delta", "pi": "\\pi", "Pi": "\\Pi", "theta": "\\theta", "Theta": "\\Theta", // Letter-like "ii": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\imaginaryI" }, "jj": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\imaginaryJ" }, "ee": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\exponentialE" }, "nabla": "\\nabla", "grad": "\\nabla", "del": "\\partial", "deg": { after: "digit+space", value: "\\degree" }, "infty": "\\infty", "\u221E": "\\infty", // @TODO: doesn't work // '∞': '\\infty', // '∞': '\\infty', "oo": { after: "nothing+digit+frac+surd+binop+relop+punct+array+openfence+closefence+space", value: "\\infty" }, // Big operators "\u2211": "\\sum", "sum": "\\sum_{#?}^{#?}", "int": "\\int_{#?}^{#?}", "prod": "\\prod_{#?}^{#?}", "sqrt": "\\sqrt{#?}", // '∫': '\\int', // There's a alt-B command for this "\u2206": "\\differentialD", // @TODO: is \\diffD most common? "\u2202": "\\differentialD", // Functions "arcsin": "\\arcsin", "arccos": "\\arccos", "arctan": "\\arctan", "arcsec": "\\arcsec", "arccsc": "\\arccsc", "arsinh": "\\arsinh", "arcosh": "\\arcosh", "artanh": "\\artanh", "arcsech": "\\arcsech", "arccsch": "\\arccsch", "arg": "\\arg", "ch": "\\ch", "cosec": "\\cosec", "cosh": "\\cosh", "cot": "\\cot", "cotg": "\\cotg", "coth": "\\coth", "csc": "\\csc", "ctg": "\\ctg", "cth": "\\cth", "sec": "\\sec", "sinh": "\\sinh", "sh": "\\sh", "tanh": "\\tanh", "tg": "\\tg", "th": "\\th", "sin": "\\sin", "cos": "\\cos", "tan": "\\tan", "lg": "\\lg", "lb": "\\lb", "log": "\\log", "ln": "\\ln", "exp": "\\exp", "lim": "\\lim_{#?}", // Differentials // According to ISO31/XI (ISO 80000-2), differentials should be upright "dx": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\differentialD x" }, "dy": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\differentialD y" }, "dt": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\differentialD t" }, // Logic "AA": "\\forall", "EE": "\\exists", "!EE": "\\nexists", "&&": "\\land", // The shortcut for the greek letter "xi" is interfering with "x in" "xin": { after: "nothing+text+relop+punct+openfence+space", value: "x \\in" }, // The shortcut for `\int` is interfering with `\sin x` "sint": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\sin t" }, "in": { after: "nothing+letter+closefence", value: "\\in" }, "!in": "\\notin", // Sets "NN": "\\mathbb{N}", // Natural numbers "ZZ": "\\Z", // Integers "QQ": "\\Q", // Rational numbers "RR": "\\R", // Real numbers "CC": "\\C", // Complex numbers // Operators "xx": "\\times", "+-": "\\pm", // Relational operators "\u2260": "\\ne", "!=": "\\ne", "\u2265": "\\ge", ">=": "\\ge", "\u2264": "\\le", "<=": "\\le", "<<": "\\ll", ">>": "\\gg", "~~": "\\approx", // More operators "\u2248": "\\approx", "?=": "\\questeq", "\xF7": "\\div", "\xAC": "\\neg", ":=": "\\coloneq", "::": "\\Colon", // Fences "(:": "\\langle", ":)": "\\rangle", // More Greek letters "beta": "\\beta", "chi": "\\chi", "epsilon": "\\epsilon", "varepsilon": "\\varepsilon", "eta": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\eta" }, "gamma": "\\gamma", "Gamma": "\\Gamma", "iota": "\\iota", "kappa": "\\kappa", "lambda": "\\lambda", "Lambda": "\\Lambda", "mu": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\mu" }, "nu": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\nu" }, "\xB5": "\\mu", // @TODO: or micro? "phi": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\phi" }, "Phi": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\Phi" }, "varphi": "\\varphi", "psi": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\psi" }, "Psi": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\Psi" }, "rho": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\rho" }, "sigma": "\\sigma", "Sigma": "\\Sigma", "tau": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\tau" }, "vartheta": "\\vartheta", "upsilon": "\\upsilon", "xi": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space", value: "\\xi" }, "Xi": { after: "nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text", value: "\\Xi" }, "zeta": "\\zeta", "omega": "\\omega", "Omega": "\\Omega", "\u03A9": "\\omega", // @TODO: or ohm? // More Logic "forall": "\\forall", "exists": "\\exists", "!exists": "\\nexists", ":.": "\\therefore", // MORE FUNCTIONS // 'arg': '\\arg', "liminf": "\\liminf_{#?}", "limsup": "\\limsup_{#?}", "argmin": "\\operatorname*{arg~min}_{#?}", "argmax": "\\operatorname*{arg~max}_{#?}", "det": "\\det", "mod": "\\bmod{#?}", "(mod": "\\pmod{#?}", "max": "\\max", "min": "\\min", "erf": "\\operatorname{erf}", "erfc": "\\operatorname{erfc}", "bessel": "\\operatorname{bessel}", "mean": "\\operatorname{mean}", "median": "\\operatorname{median}", "fft": "\\operatorname{fft}", "lcm": "\\operatorname{lcm}", "gcd": "\\operatorname{gcd}", "randomReal": "\\operatorname{randomReal}", "randomInteger": "\\operatorname{randomInteger}", "Re": "\\operatorname{Re}", "Im": "\\operatorname{Im}", // UNITS "mm": { after: "nothing+digit+operator", value: "\\operatorname{mm}" // Millimeter }, "cm": { after: "nothing+digit+operator", value: "\\operatorname{cm}" // Centimeter }, "km": { after: "nothing+digit+operator", value: "\\operatorname{km}" // Kilometer }, "kg": { after: "nothing+digit+operator", value: "\\operatorname{kg}" // Kilogram }, // '||': '\\lor', "...": "\\ldots", // In general, use \ldots "+...": "+\\cdots", // ... but use \cdots after + ... "-...": "-\\cdots", // ... - and ... "->...": "\\to\\cdots", // -> "-->...": "\\longrightarrow\\cdots", "->": "\\to", "|->": "\\mapsto", "-->": "\\longrightarrow", // '<-': '\\leftarrow', "<--": "\\longleftarrow", "=>": "\\Rightarrow", "==>": "\\Longrightarrow", // '<=': '\\Leftarrow', // CONFLICTS WITH LESS THAN OR EQUAL "<=>": "\\Leftrightarrow", "<->": "\\leftrightarrow", "(.)": "\\odot", "(+)": "\\oplus", "(/)": "\\oslash", "(*)": "\\otimes", "(-)": "\\ominus", // '(-)': '\\circleddash', "||": "\\Vert", "*": "\\cdot", // // ASCIIIMath // // Binary operation symbols // "**": "\\star", "***": "\\ast", "//": "\\slash", "\\\\": "\\backslash", "setminus": "\\backslash", "|><": "\\ltimes", "><|": "\\rtimes", "|><|": "\\bowtie", "-:": "\\div", "divide": "\\div", "@": "\\circ", // 'o+': '\\oplus', // 'ox': '\\otimes', // 'o.': '\\odot', "^^": "\\wedge", "^^^": "\\bigwedge", "vv": "\\vee", "vvv": "\\bigvee", "nn": "\\cap", "nnn": "\\bigcap", "uu": "\\cup", "uuu": "\\bigcup", // Binary relation symbols "-=": "\\equiv", "~=": "\\cong", "lt": "<", "lt=": "\\leq", "gt": ">", "gt=": "\\geq", "-<": "\\prec", "-lt": "\\prec", "-<=": "\\preceq", // '>-': '\\succ', ">-=": "\\succeq", "prop": "\\propto", "diamond": "\\diamond", "square": "\\square", "iff": "\\iff", "sub": "\\subset", "sup": "\\supset", "sube": "\\subseteq", "supe": "\\supseteq", "uarr": "\\uparrow", "darr": "\\downarrow", "rarr": "\\rightarrow", "rArr": "\\Rightarrow", "larr": "\\leftarrow", "lArr": "\\Leftarrow", "harr": "\\leftrightarrow", "hArr": "\\Leftrightarrow", "aleph": "\\aleph", // Logic "and": "\\land", "or": "\\lor", "not": "\\neg", "_|_": "\\bot", "TT": "\\top", "|--": "\\vdash", "|==": "\\models", // Other functions "|__": "\\lfloor", "__|": "\\rfloor", "|~": "\\lceil", "~|": "\\rceil", // Arrows ">->": "\\rightarrowtail", "->>": "\\twoheadrightarrow", // \char"21A0 ">->>": "\\twoheadrightarrowtail", // \char"2916 // // Desmos Graphing Calculator // "frac": "\\frac{#?}{#?}", "cbrt": "\\sqrt[3]{#?}", "nthroot": "\\sqrt[#?]{#?}" }; // src/formats/parse-math-string.ts function parseMathString(s, options) { var _a3; let format = (_a3 = options == null ? void 0 : options.format) != null ? _a3 : "auto"; if (format === "auto") [format, s] = inferFormat(s); if (format === "ascii-math") { s = s.replace(/\u2061/gu, ""); s = s.replace(/\u3016/gu, "{"); s = s.replace(/\u3017/gu, "}"); s = s.replace(/([^\\])sinx/g, "$1\\sin x"); s = s.replace(/([^\\])cosx/g, "$1\\cos x "); s = s.replace(/\u2013/g, "-"); return [ "ascii-math", parseMathExpression(s, { inlineShortcuts: options == null ? void 0 : options.inlineShortcuts }) ]; } return ["latex", s]; } function parseMathExpression(s, options) { var _a3, _b3, _c2; if (!s) return ""; let done = false; let m; const inlineShortcuts = (_a3 = options.inlineShortcuts) != null ? _a3 : INLINE_SHORTCUTS; if (!done && (s.startsWith("^") || s.startsWith("_"))) { m = parseMathArgument(s.slice(1), { inlineShortcuts, noWrap: true }); s = s[0] + "{" + m.match + "}"; s += parseMathExpression(m.rest, options); done = true; } if (!done) { m = s.match(/^(sqrt|\u221A)(.*)/); if (m) { m = parseMathArgument(m[2], { inlineShortcuts, noWrap: true }); const sqrtArgument = (_b3 = m.match) != null ? _b3 : "\\placeholder{}"; s = "\\sqrt{" + sqrtArgument + "}"; s += parseMathExpression(m.rest, options); done = true; } } if (!done) { m = s.match(/^(\\cbrt|\u221B)(.*)/); if (m) { m = parseMathArgument(m[2], { inlineShortcuts, noWrap: true }); const sqrtArgument = (_c2 = m.match) != null ? _c2 : "\\placeholder{}"; s = "\\sqrt[3]{" + sqrtArgument + "}"; s += parseMathExpression(m.rest, options); done = true; } } if (!done) { m = s.match(/^abs(.*)/); if (m) { m = parseMathArgument(m[1], { inlineShortcuts, noWrap: true }); s = "\\left|" + m.match + "\\right|"; s += parseMathExpression(m.rest, options); done = true; } } if (!done) { m = s.match(/^["”“](.*?)["”“](.*)/); if (m) { s = "\\text{" + m[1] + "}"; s += parseMathExpression(m[2], options); done = true; } } if (!done) { m = s.match(/^([^a-zA-Z\(\{\[\_\^\\\s"]+)(.*)/); if (m) { s = paddedShortcut(m[1], inlineShortcuts); s += parseMathExpression(m[2], options); done = true; } } if (!done && /^([fgh])[^a-zA-Z]/.test(s)) { m = parseMathArgument(s.slice(1), { inlineShortcuts, noWrap: true }); s = s[1] === "(" ? s[0] + "\\left(" + m.match + "\\right)" : s[0] + m.match; s += parseMathExpression(m.rest, options); done = true; } if (!done) { m = s.match(/^([a-zA-Z]+)(.*)/); if (m) { s = paddedShortcut(m[1], inlineShortcuts); s += parseMathExpression(m[2], options); done = true; } } if (!done) { m = parseMathArgument(s, { inlineShortcuts, noWrap: true }); if (m.match && m.rest[0] === "/") { const m2 = parseMathArgument(m.rest.slice(1), { inlineShortcuts, noWrap: true }); if (m2.match) { s = "\\frac{" + m.match + "}{" + m2.match + "}" + parseMathExpression(m2.rest, options); } done = true; } else if (m.match) { s = s.startsWith("(") ? "\\left(" + m.match + "\\right)" + parseMathExpression(m.rest, options) : m.match + parseMathExpression(m.rest, options); done = true; } } if (!done) { m = s.match(/^(\s+)(.*)$/); if (m) { s = " " + parseMathExpression(m[2], options); done = true; } } return s; } function parseMathArgument(s, options) { let match = ""; s = s.trim(); let rest = s; let lFence = s.charAt(0); let rFence = { "(": ")", "{": "}", "[": "]" }[lFence]; if (rFence) { let level = 1; let i = 1; while (i < s.length && level > 0) { if (s[i] === lFence) level++; if (s[i] === rFence) level--; i++; } if (level === 0) { if (options.noWrap && lFence === "(") match = parseMathExpression(s.substring(1, i - 1), options); else { if (lFence === "{" && rFence === "}") { lFence = "\\{"; rFence = "\\}"; } match = "\\left" + lFence + parseMathExpression(s.substring(1, i - 1), options) + "\\right" + rFence; } rest = s.slice(Math.max(0, i)); } else { match = s.substring(1, i); rest = ""; } } else { let m = s.match(/^([a-zA-Z]+)/); if (m) { let shortcut = getInlineShortcut(null, s, options.inlineShortcuts); if (shortcut) { shortcut = shortcut.replace("_{#?}", ""); shortcut = shortcut.replace("^{#?}", ""); return { match: shortcut, rest: s.slice(shortcut.length) }; } } m = s.match(/^([a-zA-Z])/); if (m) { return { match: m[1], rest: s.slice(1) }; } m = s.match(/^(-)?\d+(\.\d*)?/); if (m) { return { match: m[0], rest: s.slice(m[0].length) }; } if (!/^\\(left|right)/.test(s)) { m = s.match(/^(\\[a-zA-Z]+)/); if (m) { rest = s.slice(m[1].length); match = m[1]; } } } return { match, rest }; } function paddedShortcut(s, shortcuts) { let result = getInlineShortcut(null, s, shortcuts); if (result) { result = result.replace("_{#?}", ""); result = result.replace("^{#?}", ""); result += " "; } else result = s; return result; } var MODE_SHIFT_COMMANDS = [ ["\\[", "\\]"], ["\\(", "\\)"], ["$$", "$$"], ["$", "$"], // Must be *after* $$..$$ ["\\begin{math}", "\\end{math}"], ["\\begin{displaymath}", "\\end{displaymath}"], ["\\begin{equation}", "\\end{equation}"], ["\\begin{equation*}", "\\end{equation*}"] ]; function trimModeShiftCommand(s) { const trimedString = s.trim(); for (const mode of MODE_SHIFT_COMMANDS) { if (trimedString.startsWith(mode[0]) && trimedString.endsWith(mode[1])) { return [ true, trimedString.substring( mode[0].length, trimedString.length - mode[1].length ) ]; } } return [false, s]; } function inferFormat(s) { s = s.trim(); if (s.length <= 1) return ["latex", s]; let hasLatexModeShiftCommand; [hasLatexModeShiftCommand, s] = trimModeShiftCommand(s); if (hasLatexModeShiftCommand) return ["latex", s]; if (s.startsWith("`") && s.endsWith("`")) { s = s.substring(1, s.length - 1); return ["ascii-math", s]; } if (s.includes("\\")) { return ["latex", s]; } if (/\$.+\$/.test(s)) { return ["latex", `\\text{${s}}`]; } return [void 0, s]; } // src/editor-mathfield/mode-editor.ts var CLIPBOARD_LATEX_BEGIN = "$$"; var CLIPBOARD_LATEX_END = "$$"; var defaultExportHook = (_from, latex, _range) => { if (!MODE_SHIFT_COMMANDS.some( (x) => latex.startsWith(x[0]) && latex.endsWith(x[1]) )) latex = `${CLIPBOARD_LATEX_BEGIN} ${latex} ${CLIPBOARD_LATEX_END}`; return latex; }; var _ModeEditor = class _ModeEditor { constructor(name) { _ModeEditor._modes[name] = this; } static onPaste(mode, mathfield, data) { var _a3; if (!mathfield.contentEditable && mathfield.userSelect === "none") { mathfield.model.announce("plonk"); return false; } if (typeof data === "string") { const dataTransfer = new DataTransfer(); dataTransfer.setData("text/plain", data); data = dataTransfer; } const redispatchedEvent = new ClipboardEvent("paste", { clipboardData: data, cancelable: true }); if (!((_a3 = mathfield.host) == null ? void 0 : _a3.dispatchEvent(redispatchedEvent))) return false; return _ModeEditor._modes[mode].onPaste(mathfield, data); } /** Call this method from a menu */ static copyToClipboard(mathfield, format) { if (!mathfield.contentEditable && mathfield.userSelect === "none") { mathfield.model.announce("plonk"); return; } const model = mathfield.model; const exportRange = model.selectionIsCollapsed ? [0, model.lastOffset] : range(model.selection); const latex = model.getValue(exportRange, format); navigator.clipboard.writeText(latex).then( () => { }, () => mathfield.model.announce("plonk") ); } /** Call this method in response to a clipboard event */ static onCopy(mathfield, ev) { var _a3; if (!ev.clipboardData) return; if (!mathfield.contentEditable && mathfield.userSelect === "none") { mathfield.model.announce("plonk"); return; } const model = mathfield.model; const exportRange = model.selectionIsCollapsed ? [0, model.lastOffset] : range(model.selection); let atoms = model.getAtoms(exportRange); if (atoms.every((x) => x.mode === "text" || !x.mode)) { ev.clipboardData.setData( "text/plain", atoms.filter((x) => x instanceof TextAtom).map((x) => x.value).join("") ); } else if (atoms.every((x) => x.mode === "latex")) { ev.clipboardData.setData( "text/plain", model.getAtoms(exportRange, { includeChildren: true }).map((x) => { var _a4; return (_a4 = x.value) != null ? _a4 : ""; }).join("") ); } else { let latex; if (atoms.length === 1 && atoms[0].verbatimLatex !== void 0) latex = atoms[0].verbatimLatex; else latex = model.getValue(exportRange, "latex-expanded"); ev.clipboardData.setData("application/x-latex", latex); try { ev.clipboardData.setData( "text/plain", mathfield.options.onExport(mathfield, latex, exportRange) ); } catch (e) { } if (atoms.length === 1) { const atom = atoms[0]; if (atom.type === "root" || atom.type === "group") atoms = atom.body.filter((x) => x.type !== "first"); } try { ev.clipboardData.setData( "application/json+mathlive", JSON.stringify(atoms.map((x) => x.toJson())) ); } catch (e) { } if ((_a3 = window[Symbol.for("io.cortexjs.compute-engine")]) == null ? void 0 : _a3.ComputeEngine) { const ce = window.MathfieldElement.computeEngine; if (ce) { try { const options = ce.jsonSerializationOptions; ce.jsonSerializationOptions = { metadata: ["latex"] }; const expr = ce.parse( model.getValue(exportRange, "latex-unstyled") ); ce.jsonSerializationOptions = options; const mathJson = JSON.stringify(expr.json); if (mathJson) ev.clipboardData.setData("application/json", mathJson); } catch (e) { } } } } ev.preventDefault(); } static insert(model, text, options = {}) { var _a3; const mode = options.mode === "auto" ? model.mode : (_a3 = options.mode) != null ? _a3 : model.mode; return _ModeEditor._modes[mode].insert(model, text, options); } onPaste(_mathfield, _data) { return false; } insert(_model, _text, _options) { return false; } }; _ModeEditor._modes = {}; var ModeEditor = _ModeEditor; // src/editor/keybindings-definitions.ts var DEFAULT_KEYBINDINGS = [ { key: "left", command: "moveToPreviousChar" }, { key: "right", command: "moveToNextChar" }, { key: "up", command: "moveUp" }, { key: "down", command: "moveDown" }, { key: "shift+[ArrowLeft]", command: "extendSelectionBackward" }, { key: "shift+[ArrowRight]", command: "extendSelectionForward" }, { key: "shift+[ArrowUp]", command: "extendSelectionUpward" }, { key: "shift+[ArrowDown]", command: "extendSelectionDownward" }, { key: "[Backspace]", command: "deleteBackward" }, { key: "alt+[Delete]", command: "deleteBackward" }, { key: "[Delete]", command: "deleteForward" }, { key: "alt+[Backspace]", command: "deleteForward" }, { key: "alt+[ArrowLeft]", command: "moveToPreviousWord" }, { key: "alt+[ArrowRight]", command: "moveToNextWord" }, { key: "shift+alt+[ArrowLeft]", command: "extendToPreviousWord" }, { key: "shift+alt+[ArrowRight]", command: "extendToNextWord" }, { key: "ctrl+[ArrowLeft]", command: "moveToGroupStart" }, { key: "ctrl+[ArrowRight]", command: "moveToGroupEnd" }, { key: "shift+ctrl+[ArrowLeft]", command: "extendToGroupStart" }, { key: "shift+ctrl+[ArrowRight]", command: "extendToGroupEnd" }, { key: "[Home]", command: "moveToMathfieldStart" }, { key: "cmd+[ArrowLeft]", command: "moveToMathfieldStart" }, { key: "shift+[Home]", command: "extendToMathFieldStart" }, { key: "shift+cmd+[ArrowLeft]", command: "extendToMathFieldStart" }, { key: "[End]", command: "moveToMathfieldEnd" }, { key: "cmd+[ArrowRight]", command: "moveToMathfieldEnd" }, { key: "shift+[End]", command: "extendToMathFieldEnd" }, { key: "shift+cmd+[ArrowRight]", command: "extendToMathFieldEnd" }, { key: "[Pageup]", command: "moveToGroupStart" }, { key: "[Pagedown]", command: "moveToGroupEnd" }, { key: "[Tab]", command: "moveToNextGroup" }, { key: "shift+[Tab]", command: "moveToPreviousGroup" }, { key: "[Escape]", ifMode: "math", command: ["switchMode", "latex"] }, { key: "[Escape]", ifMode: "text", command: ["switchMode", "latex"] }, { key: "[Escape]", ifMode: "latex", command: ["complete", "complete", { selectItem: "true" }] }, // Accept the entry (without the suggestion) and select { key: "\\", ifMode: "math", command: ["switchMode", "latex", "\\"] }, // { key: '[Backslash]', ifMode: 'math', command: ['switchMode', 'latex'] }, { key: "[IntlBackslash]", ifMode: "math", command: ["switchMode", "latex", "\\"] }, // On UK QWERTY keyboards { key: "[Tab]", ifMode: "latex", command: ["complete", "accept-suggestion"] }, // Complete the suggestion { key: "[Return]", ifMode: "latex", command: "complete" }, { key: "[Enter]", ifMode: "latex", command: "complete" }, { key: "shift+[Escape]", ifMode: "latex", command: ["complete", "reject"] }, // Some keyboards can't generate // this combination, for example in 60% keyboards it is mapped to ~ { key: "[ArrowDown]", ifMode: "latex", command: "nextSuggestion" }, // { key: 'ios:command:[Tab]', ifMode: 'latex',command: 'nextSuggestion' }, { key: "[ArrowUp]", ifMode: "latex", command: "previousSuggestion" }, { key: "ctrl+a", ifPlatform: "!macos", command: "selectAll" }, { key: "cmd+a", command: "selectAll" }, // Rare keys on some extended keyboards { key: "[Cut]", command: "cutToClipboard" }, { key: "[Copy]", command: "copyToClipboard" }, { key: "[Paste]", command: "pasteFromClipboard" }, { key: "[Clear]", command: "deleteBackward" }, { key: "[Undo]", command: "undo" }, { key: "[Redo]", command: "redo" }, { key: "[EraseEof]", command: "deleteToGroupEnd" }, // Safari on iOS does not send cut/copy/paste commands when the mathfield // is focused, so intercept the keyboard shortcuts. // This is less desirable because the full clipboard API is not accessible // by this path, and user authorization is required. { key: "ctrl+x", ifPlatform: "ios", command: "cutToClipboard" }, { key: "cmd+x", ifPlatform: "ios", command: "cutToClipboard" }, { key: "ctrl+c", ifPlatform: "ios", command: "copyToClipboard" }, { key: "cmd+c", ifPlatform: "ios", command: "copyToClipboard" }, { key: "ctrl+v", ifPlatform: "ios", command: "pasteFromClipboard" }, { key: "cmd+v", ifPlatform: "ios", command: "pasteFromClipboard" }, { key: "ctrl+z", ifPlatform: "!macos", command: "undo" }, { key: "cmd+z", command: "undo" }, { key: "ctrl+y", ifPlatform: "!macos", command: "redo" }, // ARIA recommendation { key: "shift+cmd+y", command: "redo" }, { key: "shift+ctrl+z", ifPlatform: "!macos", command: "redo" }, { key: "shift+cmd+z", command: "redo" }, // EMACS/MACOS BINDINGS { key: "ctrl+b", ifPlatform: "macos", command: "moveToPreviousChar" }, { key: "ctrl+f", ifPlatform: "macos", command: "moveToNextChar" }, { key: "ctrl+p", ifPlatform: "macos", command: "moveUp" }, { key: "ctrl+n", ifPlatform: "macos", command: "moveDown" }, { key: "ctrl+a", ifPlatform: "macos", command: "moveToMathfieldStart" }, { key: "ctrl+e", ifPlatform: "macos", command: "moveToMathfieldEnd" }, { key: "shift+ctrl+b", ifPlatform: "macos", command: "extendSelectionBackward" }, { key: "shift+ctrl+f", ifPlatform: "macos", command: "extendSelectionForward" }, { key: "shift+ctrl+p", ifPlatform: "macos", command: "extendSelectionUpward" }, { key: "shift+ctrl+n", ifPlatform: "macos", command: "extendSelectionDownward" }, { key: "shift+ctrl+a", ifPlatform: "macos", command: "extendToMathFieldStart" }, { key: "shift+ctrl+e", ifPlatform: "macos", command: "extendToMathFieldEnd" }, { key: "alt+ctrl+b", ifPlatform: "macos", command: "moveToPreviousWord" }, { key: "alt+ctrl+f", ifPlatform: "macos", command: "moveToNextWord" }, { key: "shift+alt+ctrl+b", ifPlatform: "macos", command: "extendToPreviousWord" }, { key: "shift+alt+ctrl+f", ifPlatform: "macos", command: "extendToNextWord" }, { key: "ctrl+h", ifPlatform: "macos", command: "deleteBackward" }, { key: "ctrl+d", ifPlatform: "macos", command: "deleteForward" }, { key: "ctrl+l", ifPlatform: "macos", command: "scrollIntoView" }, // { key: 'ctrl+t', ifPlatform: 'macos', command: 'transpose' }, // WOLFRAM MATHEMATICA BINDINGS { key: "ctrl+[Digit2]", ifMode: "math", command: ["insert", "\\sqrt{#0}"] }, { key: "ctrl+[Digit5]", ifMode: "math", command: "moveToOpposite" }, { key: "ctrl+[Digit6]", ifMode: "math", command: "moveToSuperscript" }, { key: "ctrl+[Return]", ifMode: "math", command: "addRowAfter" }, { key: "ctrl+[Enter]", ifMode: "math", command: "addRowAfter" }, { key: "cmd+[Return]", ifMode: "math", command: "addRowAfter" }, { key: "cmd+[Enter]", ifMode: "math", command: "addRowAfter" }, // Excel keybindings: // shift+space: select entire row, ctrl+space: select an entire column // shift+ctrl++ or ctrl+numpad+ // ctrl+- to delete a row or columns // MATHLIVE BINDINGS { key: "alt+p", ifMode: "math", command: ["insert", "\\pi"] }, { key: "alt+v", ifMode: "math", command: ["insert", "\\sqrt{#0}"] }, { key: "alt+o", ifMode: "math", command: ["insert", "\\emptyset"] }, { key: "alt+d", ifMode: "math", command: ["insert", "\\differentialD"] }, { key: "shift+alt+o", ifMode: "math", command: ["insert", "\\varnothing"] }, { key: "shift+alt+d", ifMode: "math", command: ["insert", "\\partial"] }, { key: "alt+[Backslash]", ifMode: "math", command: ["insert", "\\backslash"] }, // "|" key} override command mode { key: "[NumpadDivide]", ifMode: "math", command: ["insert", "\\frac{#@}{#?}"] }, // ?? { key: "alt+[NumpadDivide]", ifMode: "math", command: ["insert", "\\frac{#?}{#@}"] }, // ?? // Accessibility { key: "shift+alt+k", command: "toggleKeystrokeCaption" }, { key: "alt+[Space]", command: "toggleContextMenu" }, { key: "alt+shift+[Space]", command: "toggleVirtualKeyboard" }, // Note: On Mac OS (as of 10.12), there is a bug/behavior that causes // a beep to be generated with certain command+control key combinations. // The workaround is to create a default binding file to silence them. // In ~/Library/KeyBindings/DefaultKeyBinding.dict add these entries: // // { // "^@\UF701" = "noop:"; // "^@\UF702" = "noop:"; // "^@\UF703" = "noop:"; // } { key: "alt+ctrl+[ArrowUp]", command: ["speak", "all", { withHighlighting: false }] }, { key: "alt+ctrl+[ArrowDown]", command: ["speak", "selection", { withHighlighting: false }] }, // // Punctuations and some non-alpha key combinations // only work with specific keyboard layouts // { key: "shift+[Quote]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["switchMode", "text", "", ""] }, { key: "shift+alt+[KeyT]", ifMode: "math", command: ["switchMode", "text", "", ""] }, { key: "shift+[Quote]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "text", command: ["switchMode", "math", "", ""] }, { key: "shift+alt+[KeyT]", ifMode: "text", command: ["switchMode", "math", "", ""] }, { key: "/", ifMode: "math", command: ["insert", "\\frac{#@}{#?}"] }, { key: "alt+/", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "/"] }, { key: "alt+shift+/", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "/"] }, { key: "alt+[BracketLeft]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "\\left\\lbrack #0 \\right\\rbrack"] }, // ?? { key: "ctrl+[Minus]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: "moveToSubscript" }, // ?? { key: "shift+alt+[BracketLeft]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "\\left\\lbrace #0 \\right\\rbrace"] }, // ?? { key: "ctrl+;", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: "addRowAfter" }, { key: "cmd+;", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: "addRowAfter" }, { key: "shift+ctrl+;", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: "addRowBefore" }, { key: "shift+cmd+;", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: "addRowBefore" }, { key: "ctrl+[Backspace]", ifMode: "math", command: "removeRow" }, { key: "cmd+[Backspace]", ifMode: "math", command: "removeRow" }, // { // key: 'ctrl+[Comma]', // ifLayout: ['apple.en-intl', 'windows.en-intl', 'linux.en'], // ifMode: 'math', // command: 'addColumnAfter', // }, // { // key: 'cmd+[Comma]', // ifLayout: ['apple.en-intl', 'windows.en-intl', 'linux.en'], // ifMode: 'math', // command: 'addColumnAfter', // }, // { // key: 'shift+ctrl+[Comma]', // ifLayout: ['apple.en-intl', 'windows.en-intl', 'linux.en'], // ifMode: 'math', // command: 'addColumnBefore', // }, // { // key: 'shift+cmd+[Comma]', // ifLayout: ['apple.en-intl', 'windows.en-intl', 'linux.en'], // ifMode: 'math', // command: 'addColumnBefore', // }, { key: "alt+[Tab]", ifMode: "math", command: "addColumnAfter" }, { key: "shift+alt+[Tab]", ifMode: "math", command: "addColumnBefore" }, { key: "alt+[Enter]", ifMode: "math", command: "addRowAfter" }, { key: "shift+alt+[Enter]", ifMode: "math", command: "addRowBefore" }, { key: "alt+[Return]", ifMode: "math", command: "addRowAfter" }, { key: "shift+alt+[Return]", ifMode: "math", command: "addRowBefore" }, { key: "shift+[Backspace]", ifMode: "math", command: "removeColumn" }, { key: "alt+[Digit5]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "$\\infty"] }, // "%" key { key: "alt+[Digit9]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "("] }, // "(" key} override smartFence { key: "alt+[Digit0]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", ")"] }, // ")" key} override smartFence { key: "alt+|", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "|"] }, // "|" key} override smartFence { key: "shift+[Backquote]", ifLayout: ["apple.en-intl", "windows.en-intl", "linux.en"], ifMode: "math", command: ["insert", "\\~"] }, // ?? { key: "[Backquote]", ifLayout: ["windows.french", "linux.french"], ifMode: "math", command: ["insert", "^2"] }, { key: "[Backquote]", ifLayout: ["windows.german", "linux.german"], ifMode: "math", command: ["insert", "^"] }, { key: "[IntlBackslash]", ifLayout: ["apple.german"], ifMode: "math", command: ["insert", "^"] } ]; var REVERSE_KEYBINDINGS = { "\\sqrt": ["alt+v", "ctrl+[Digit2]"], "\\pi": "alt+p", "\\infty": "alt+[Digit5]", "\\differentialD": "alt+d", "\\partial": "shift+alt+d", "\\frac": "Slash", "\\emptyset": "alt+o", "\\varnothing": "shift+alt+o", "\\~": "~" }; // src/editor-mathfield/utils.ts function isValidMathfield(mf) { var _a3; return ((_a3 = mf.element) == null ? void 0 : _a3.mathfield) === mf; } function findElementWithCaret(element) { var _a3, _b3; return (_b3 = (_a3 = element.querySelector(".ML__caret")) != null ? _a3 : element.querySelector(".ML__text-caret")) != null ? _b3 : element.querySelector(".ML__latex-caret"); } function getCaretPoint(element) { const caret = findElementWithCaret(element); if (!caret) return null; const bounds = caret.getBoundingClientRect(); return { x: bounds.right, y: bounds.bottom, height: bounds.height }; } function branchId(atom) { var _a3; if (!atom.parent) return "root"; let result = (_a3 = atom.parent.id) != null ? _a3 : ""; result += typeof atom.parentBranch === "string" ? "-" + atom.parentBranch : `-${atom.parentBranch[0]}/${atom.parentBranch[0]}`; return result; } function adjustForScrolling(mathfield, rect, scaleFactor) { if (!rect) return null; const fieldRect = mathfield.field.getBoundingClientRect(); const w = rect.right - rect.left; const h = rect.bottom - rect.top; const left = Math.ceil( rect.left - fieldRect.left + mathfield.field.scrollLeft * scaleFactor ); const top = Math.ceil(rect.top - fieldRect.top); return { left, right: left + w, top, bottom: top + h }; } function getNodeBounds(node) { const bounds = node.getBoundingClientRect(); const marginRight = parseInt(getComputedStyle(node).marginRight); const result = { top: bounds.top - 1, bottom: bounds.bottom, left: bounds.left, right: bounds.right - 1 + marginRight }; if (node.children.length === 0 || node.tagName.toUpperCase() === "SVG") return result; for (const child of node.children) { if (child.nodeType === 1 && "atomId" in child.dataset && !child.classList.contains("pstrut")) { const r = getNodeBounds(child); result.left = Math.min(result.left, r.left); result.right = Math.max(result.right, r.right); result.top = Math.min(result.top, r.top); result.bottom = Math.max(result.bottom, r.bottom); } } return result; } function getAtomBounds(mathfield, atom) { var _a3, _b3; if (!atom.id) return null; let result = (_b3 = (_a3 = mathfield.atomBoundsCache) == null ? void 0 : _a3.get(atom.id)) != null ? _b3 : null; if (result !== null) return result; const node = mathfield.field.querySelector(`[data-atom-id="${atom.id}"]`); result = node ? getNodeBounds(node) : null; if (mathfield.atomBoundsCache) { if (result) mathfield.atomBoundsCache.set(atom.id, result); else mathfield.atomBoundsCache.delete(atom.id); } return result != null ? result : null; } function getRangeBounds(mathfield, range2, options) { const rects = /* @__PURE__ */ new Map(); for (const atom of mathfield.model.getAtoms(range2, { includeChildren: true })) { if ((options == null ? void 0 : options.excludeAtomsWithBackground) && atom.style.backgroundColor) continue; const field = mathfield.field; const offsetWidth = field.offsetWidth; const actualWidth = Math.floor(field.getBoundingClientRect().width); let scaleFactor = actualWidth / offsetWidth; scaleFactor = isNaN(scaleFactor) ? 1 : scaleFactor; const bounds = adjustForScrolling( mathfield, getAtomBounds(mathfield, atom), scaleFactor ); if (bounds) { const id = branchId(atom); if (rects.has(id)) { const r = rects.get(id); rects.set(id, { left: Math.min(r.left, bounds.left), right: Math.max(r.right, bounds.right), top: Math.min(r.top, bounds.top), bottom: Math.max(r.bottom, bounds.bottom) }); } else rects.set(id, bounds); } } return [...rects.values()]; } function getSelectionBounds(mathfield, options) { return mathfield.model.selection.ranges.reduce( (acc, x) => acc.concat(...getRangeBounds(mathfield, x, options)), [] ); } function validateOrigin(origin, originValidator) { if (origin === "*" || originValidator === "none") return true; if (originValidator === "same-origin") return !window.origin || origin === window.origin; if (typeof originValidator === "function") return originValidator(origin); return false; } function getLocalDOMRect(el) { let offsetTop = 0; let offsetLeft = 0; const width = el.offsetWidth; const height = el.offsetHeight; while (el instanceof HTMLElement) { offsetTop += el.offsetTop; offsetLeft += el.offsetLeft; el = el.offsetParent; } return new DOMRect(offsetLeft, offsetTop, width, height); } // css/mathfield.less var mathfield_default = `@keyframes ML__caret-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } } .ML__container { display: inline-flex; flex-flow: row; justify-content: space-between; align-items: flex-end; min-height: 39px; /* Need some room for the virtual keyboard toggle */ width: 100%; /* Encourage browsers to consider allocating a hardware accelerated layer for this element. */ isolation: isolate; /* Prevent the browser from trying to interpret touch gestures in the field */ /* "Disabling double-tap to zoom removes the need for browsers to delay the generation of click events when the user taps the screen." */ touch-action: none; --_caret-color: var(--caret-color, hsl(var(--_hue), 40%, 49%)); --_selection-color: var(--selection-color, #000); --_selection-background-color: var(--selection-background-color, hsl(var(--_hue), 70%, 85%)); --_text-highlight-background-color: var(--highlight-text, hsla(var(--_hue), 40%, 50%, 0.1)); --_contains-highlight-background-color: var(--contains-highlight-background-color, hsl(var(--_hue), 40%, 95%)); --_smart-fence-color: var(--smart-fence-color, currentColor); --_smart-fence-opacity: var(--smart-fence-opacity, 0.5); --_latex-color: var(--latex-color, hsl(var(--_hue), 80%, 40%)); --_correct-color: var(--correct-color, #10a000); --_incorrect-color: var(--incorrect-color, #a01b00); --_composition-background-color: var(--composition-background-color, #fff1c2); --_composition-text-color: var(--composition-text-color, black); --_composition-underline-color: var(--composition-underline-color, transparent); } /* This is the actual field content (formula) */ .ML__content { display: flex; align-items: center; align-self: center; position: relative; overflow: hidden; padding: 2px 3px 2px 1px; width: 100%; } .ML__virtual-keyboard-toggle, .ML__menu-toggle { box-sizing: border-box; display: flex; align-self: center; align-items: center; flex-shrink: 0; flex-direction: column; justify-content: center; width: 34px; height: 34px; padding: 0; margin-right: 4px; cursor: pointer; /* Avoid some weird blinking with :hover */ border-radius: 8px; border: 1px solid transparent; transition: background 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); color: hsl(var(--_hue), 40%, 50%); fill: currentColor; background: transparent; } .ML__virtual-keyboard-toggle:hover, .ML__menu-toggle:hover { background: hsla(0, 0%, 70%, 0.3); color: #333; fill: currentColor; } .ML__virtual-keyboard-toggle > span, .ML__menu-toggle > span { display: flex; align-self: center; align-items: center; } /* The invisible element used to capture keyboard events. We're just trying really hard to make sure it doesn't show. */ .ML__keyboard-sink { display: inline-block; resize: none; outline: none; border: none; /* Need these for Microsoft Edge */ position: fixed; clip: rect(0 0 0 0); /* Need this to prevent iOS Safari from auto-zooming */ font-size: 1em; font-family: KaTeX_Main; line-height: 0.5; /* On Chromium, if this is 0, no keyboard events are received */ } [part="placeholder"] { color: var(--neutral-400); } .ML__composition { background: var(--_composition-background-color); color: var(--_composition-text-color); text-decoration: underline var(--_composition-underline-color); } .ML__caret::after { content: ''; visibility: hidden; width: 0; display: inline-block; height: 0.76em; --_caret-width: clamp(2px, 0.08em, 10px); border: none; border-radius: calc(var(--_caret-width) / 2); border-right: var(--_caret-width) solid var(--_caret-color); margin-right: calc(-1 * var(--_caret-width)); position: relative; left: -0.045em; bottom: -0.05em; animation: ML__caret-blink 1.05s step-end forwards infinite; } .ML__text-caret::after { content: ''; visibility: hidden; width: 0; display: inline-block; height: 0.76em; --_caret-width: clamp(2px, 0.08em, 10px); border: none; border-radius: calc(var(--_caret-width) / 2); border-right: var(--_caret-width) solid var(--_caret-color); margin-right: calc(-1 * var(--_caret-width)); position: relative; left: -0.045em; bottom: -0.05em; animation: ML__caret-blink 1.05s step-end forwards infinite; } .ML__latex-caret::after { content: ''; visibility: hidden; --_caret-width: clamp(2px, 0.08em, 10px); border: none; border-radius: calc(var(--_caret-width) / 2); border-right: var(--_caret-width) solid var(--_latex-color); margin-right: calc(-1 * var(--_caret-width)); position: relative; left: -0.019em; animation: ML__caret-blink 1.05s step-end forwards infinite; } .ML__focused .ML__latex-caret::after, .ML__focused .ML__text-caret::after, .ML__focused .ML__caret::after { visibility: visible; } .ML__focused .ML__text { background: var(--_text-highlight-background-color); } /* When using smartFence, the anticipated closing fence is displayed with this style */ .ML__smart-fence__close { opacity: var(--_smart-fence-opacity); color: var(--_smart-fence-color); } .ML__selected, .ML__focused .ML__selected .ML__contains-caret, .ML__focused .ML__selected .ML__smart-fence__close, .ML__focused .ML__selected .ML__placeholder { color: var(--_selection-color); opacity: 1; } .ML__selection { box-sizing: border-box; background: var(--_selection-background-color) !important; } .ML__contains-caret.ML__close, .ML__contains-caret.ML__open, .ML__contains-caret > .ML__close, .ML__contains-caret > .ML__open, .ML__contains-caret .ML__sqrt-sign, .ML__contains-caret .ML__sqrt-line { color: var(--_caret-color); } .ML__contains-highlight { box-sizing: border-box; background: transparent; } .ML__focused .ML__contains-highlight { background: var(--_contains-highlight-background-color); } .ML__raw-latex { font-family: 'Berkeley Mono', 'IBM Plex Mono', 'Source Code Pro', Consolas, 'Roboto Mono', Menlo, 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Courier, monospace; font-weight: 400; font-size: 0.8em; letter-spacing: -0.05em; color: var(--_latex-color); } .ML__suggestion { color: var(--neutral-500); } .ML__virtual-keyboard-toggle.is-visible.is-pressed:hover { background: hsl(var(--_hue), 25%, 35%); color: #fafafa; fill: currentColor; } .ML__virtual-keyboard-toggle:focus { outline: none; border-radius: 8px; border: 2px solid hsl(var(--_hue), 40%, 50%); } .ML__virtual-keyboard-toggle.is-pressed, .ML__virtual-keyboard-toggle.is-active:hover, .ML__virtual-keyboard-toggle.is-active { background: hsl(var(--_hue), 25%, 35%); color: #fafafa; fill: currentColor; } /* Add an attribute 'data-tooltip' to automatically show a tooltip over a element on hover. */ [data-tooltip] { position: relative; } [data-tooltip]::after { content: attr(data-tooltip); position: absolute; display: block; z-index: 2; pointer-events: none; right: auto; top: calc(-100% - 4px); width: max-content; max-width: 200px; padding: 8px 8px; border-radius: 4px; background: #616161; color: #fff; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); text-align: center; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-style: normal; font-weight: 400; font-size: 13px; /* Phone */ opacity: 0; transform: scale(0.5); } @media only screen and (max-width: 767px) { [data-tooltip]::after { padding: 8px 16px; font-size: 16px; } } menu [data-tooltip]::after { left: 100%; top: 0%; } menu .ML__base { cursor: default; } /** Don't display if we're tracking, i.e. have the pointer down */ .tracking [data-tooltip]:hover::after { /* Use visibility, not display. Display will remove the after from the DOM, and the override below will not work */ visibility: hidden; } /** But do display if tracking and inside a menu */ .tracking menu li[data-tooltip]:hover::after, [data-tooltip]:hover::after { visibility: visible; opacity: 1; transform: scale(1); transition-property: opacity, scale; transition-duration: 0.15s; transition-delay: 1s; transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } .ML__prompt { border-radius: 2px; } .ML__editablePromptBox { outline: 1px solid #acacac; border-radius: 2px; z-index: -1; } .ML__focusedPromptBox { outline: highlight auto 1px; } .ML__lockedPromptBox { background-color: rgba(142, 142, 141, 0.4); z-index: -1; } .ML__correctPromptBox { outline: 1px solid var(--_correct-color); box-shadow: 0 0 5px var(--_correct-color); } .ML__incorrectPromptBox { outline: 1px solid var(--_incorrect-color); box-shadow: 0 0 5px var(--_incorrect-color); } .variant-submenu { display: flex; flex-direction: column; padding: 8px; } .variant-submenu [part=menu-item] { font-size: 2rem; text-align: center; margin: 0; } .insert-matrix-submenu { display: grid; padding: 8px; align-content: center; justify-content: center; grid-template-columns: repeat(5, minmax(0, 1fr)); } .insert-matrix-submenu [part=menu-item] { font-size: 21px; border: none; border-radius: 0; line-height: 21px; text-align: center; padding: 0; margin: 0; } .border-submenu [part=menu-item] { font-size: 2rem; line-height: 1.2; text-align: center; } .swatches-submenu { --_swatch-size: 2rem; --_columns: 4; display: flex; flex-flow: wrap; padding: 8px; max-width: calc(var(--_columns) * (var(--_swatch-size) + 18px) + 16px); box-sizing: border-box; } .menu-swatch { display: flex; align-items: center; justify-content: center; box-sizing: border-box; width: fit-content; height: fit-content; margin: 2px; padding: 0; background: var(--neutral-200); } .menu-swatch > .label { padding: 0; margin: 0; line-height: 0; } .menu-swatch > .label > span { display: inline-block; margin: 6px; min-width: var(--_swatch-size); min-height: var(--_swatch-size); border-radius: 50%; } .menu-swatch.active { background: var(--neutral-100); scale: 1.4; } .menu-swatch.active > .label > span { border-radius: 2px; } .menu-swatch .ui-checkmark, .menu-swatch .ui-mixedmark { position: absolute; margin: 0; padding: 0; color: white; } .menu-swatch.dark-contrast .ui-checkmark, .menu-swatch.dark-contrast .ui-mixedmark { color: #000; } `; // css/core.less var core_default = ".ML__container {\n min-height: auto !important;\n --_hue: var(--hue, 212);\n --_placeholder-color: var(--placeholder-color, hsl(var(--_hue), 40%, 49%));\n --_placeholder-opacity: var(--placeholder-opacity, 0.4);\n --_text-font-family: var(--text-font-family, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif);\n}\n.ML__sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n.ML__is-inline {\n display: inline-block;\n}\n.ML__base {\n visibility: inherit;\n display: inline-block;\n position: relative;\n cursor: text;\n padding: 0;\n margin: 0;\n box-sizing: content-box;\n border: 0;\n outline: 0;\n vertical-align: baseline;\n font-weight: inherit;\n font-family: inherit;\n font-style: inherit;\n text-decoration: none;\n width: min-content;\n}\n.ML__strut,\n.ML__strut--bottom {\n display: inline-block;\n min-height: 0.5em;\n}\n.ML__small-delim {\n font-family: KaTeX_Main;\n}\n/* Text mode */\n.ML__text {\n font-family: var(--_text-font-family);\n white-space: pre;\n}\n/* Use cmr for 'math upright' */\n.ML__cmr {\n font-family: KaTeX_Main;\n font-style: normal;\n}\n.ML__mathit {\n font-family: KaTeX_Math;\n /* The KaTeX_Math font is italic by default, so the font-style below is only \n useful when a fallback font is used\n */\n font-style: italic;\n}\n.ML__mathbf {\n font-family: KaTeX_Main;\n font-weight: bold;\n}\n/* Lowercase greek symbols should stick to math font when \\mathbf is applied \n to match TeX idiosyncratic behavior */\n.lcGreek.ML__mathbf {\n font-family: KaTeX_Math;\n font-weight: normal;\n}\n.ML__mathbfit {\n font-family: KaTeX_Math;\n font-weight: bold;\n font-style: italic;\n}\n.ML__ams {\n font-family: KaTeX_AMS;\n}\n/* Blackboard */\n.ML__bb {\n font-family: KaTeX_AMS;\n}\n.ML__cal {\n font-family: KaTeX_Caligraphic;\n}\n.ML__frak {\n font-family: KaTeX_Fraktur;\n}\n.ML__tt {\n font-family: KaTeX_Typewriter;\n}\n.ML__script {\n font-family: KaTeX_Script;\n}\n.ML__sans {\n font-family: KaTeX_SansSerif;\n}\n.ML__series_ul {\n font-weight: 100;\n}\n.ML__series_el {\n font-weight: 100;\n}\n.ML__series_l {\n font-weight: 200;\n}\n.ML__series_sl {\n font-weight: 300;\n}\n.ML__series_sb {\n font-weight: 500;\n}\n.ML__bold,\n.ML__boldsymbol {\n font-weight: 700;\n}\n.ML__series_eb {\n font-weight: 800;\n}\n.ML__series_ub {\n font-weight: 900;\n}\n.ML__series_uc {\n font-stretch: ultra-condensed;\n}\n.ML__series_ec {\n font-stretch: extra-condensed;\n}\n.ML__series_c {\n font-stretch: condensed;\n}\n.ML__series_sc {\n font-stretch: semi-condensed;\n}\n.ML__series_sx {\n font-stretch: semi-expanded;\n}\n.ML__series_x {\n font-stretch: expanded;\n}\n.ML__series_ex {\n font-stretch: extra-expanded;\n}\n.ML__series_ux {\n font-stretch: ultra-expanded;\n}\n.ML__it {\n font-style: italic;\n}\n.ML__shape_ol {\n -webkit-text-stroke: 1px black;\n text-stroke: 1px black;\n color: transparent;\n}\n.ML__shape_sc {\n font-variant: small-caps;\n}\n.ML__shape_sl {\n font-style: oblique;\n}\n/* First level emphasis */\n.ML__emph {\n color: #bc2612;\n}\n/* Second level emphasis */\n.ML__emph .ML__emph {\n color: #0c7f99;\n}\n.ML__highlight {\n color: #007cb2;\n background: #edd1b0;\n}\n.ML__center {\n text-align: center;\n}\n.ML__label_padding {\n padding: 0 0.5em;\n}\n.ML__frac-line {\n width: 100%;\n min-height: 1px;\n}\n.ML__frac-line:after {\n content: '';\n display: block;\n margin-top: max(-1px, -0.04em);\n min-height: max(1px, 0.04em);\n /* Ensure the line is visible when printing even if \"turn off background images\" is on*/\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n /* There's a bug since Chrome 62 where \n sub-pixel border lines don't draw at some zoom \n levels (110%, 90%). \n Setting the min-height used to work around it, but that workaround\n broke in Chrome 84 or so.\n Setting the background (and the min-height) seems to work for now.\n */\n background: currentColor;\n box-sizing: content-box;\n /* Vuetify sets the box-sizing to inherit \n causes the fraction line to not draw at all sizes (see #26) */\n /* On some versions of Firefox on Windows, the line fails to \n draw at some zoom levels, but setting the transform triggers\n the hardware accelerated path, which works */\n transform: translate(0, 0);\n}\n.ML__sqrt {\n display: inline-block;\n}\n.ML__sqrt-sign {\n display: inline-block;\n position: relative;\n}\n.ML__sqrt-line {\n display: inline-block;\n height: max(1px, 0.04em);\n width: 100%;\n}\n.ML__sqrt-line:before {\n content: '';\n display: block;\n margin-top: min(-1px, -0.04em);\n min-height: max(1px, 0.04em);\n /* Ensure the line is visible when printing even if \"turn off background images\" is on*/\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n background: currentColor;\n /* On some versions of Firefox on Windows, the line fails to \n draw at some zoom levels, but setting the transform triggers\n the hardware accelerated path, which works */\n transform: translate(0, 0);\n}\n.ML__sqrt-line:after {\n border-bottom-width: 1px;\n content: ' ';\n display: block;\n margin-top: -0.1em;\n}\n.ML__sqrt-index {\n margin-left: 0.27777778em;\n margin-right: -0.55555556em;\n}\n.ML__delim-size1 {\n font-family: KaTeX_Size1;\n}\n.ML__delim-size2 {\n font-family: KaTeX_Size2;\n}\n.ML__delim-size3 {\n font-family: KaTeX_Size3;\n}\n.ML__delim-size4 {\n font-family: KaTeX_Size4;\n}\n.ML__delim-mult .delim-size1 > span {\n font-family: KaTeX_Size1;\n}\n.ML__delim-mult .delim-size4 > span {\n font-family: KaTeX_Size4;\n}\n.ML__accent-body > span {\n font-family: KaTeX_Main;\n width: 0;\n}\n.ML__accent-vec {\n position: relative;\n left: 0.24em;\n}\n/** The markup for a LaTeX formula, either in an editable mathfield or \n in a static display.\n*/\n.ML__latex {\n display: inline-block;\n direction: ltr;\n text-align: left;\n text-indent: 0;\n text-rendering: auto;\n font-family: KaTeX_Main, 'Times New Roman', serif;\n font-style: normal;\n font-size-adjust: none;\n font-stretch: normal;\n font-variant-caps: normal;\n letter-spacing: normal;\n line-height: 1.2;\n word-wrap: normal;\n word-spacing: normal;\n white-space: nowrap;\n text-shadow: none;\n -webkit-user-select: none;\n user-select: none;\n width: min-content;\n}\n.ML__latex .style-wrap {\n position: relative;\n}\n.ML__latex .mfrac {\n display: inline-block;\n}\n.ML__latex .left-right {\n display: inline-block;\n}\n.ML__latex .vlist-t {\n display: inline-table;\n table-layout: fixed;\n border-collapse: collapse;\n}\n.ML__latex .vlist-r {\n display: table-row;\n}\n.ML__latex .vlist {\n display: table-cell;\n vertical-align: bottom;\n position: relative;\n}\n.ML__latex .vlist > span {\n display: block;\n height: 0;\n position: relative;\n}\n.ML__latex .vlist > span > span {\n display: inline-block;\n}\n.ML__latex .vlist > span > .pstrut {\n overflow: hidden;\n width: 0;\n}\n.ML__latex .vlist-t2 {\n margin-right: -2px;\n}\n.ML__latex .vlist-s {\n display: table-cell;\n vertical-align: bottom;\n font-size: 1px;\n width: 2px;\n min-width: 2px;\n}\n.ML__latex .msubsup {\n text-align: left;\n}\n.ML__latex .negativethinspace {\n display: inline-block;\n margin-left: -0.16667em;\n height: 0.71em;\n}\n.ML__latex .thinspace {\n display: inline-block;\n width: 0.16667em;\n height: 0.71em;\n}\n.ML__latex .mediumspace {\n display: inline-block;\n width: 0.22222em;\n height: 0.71em;\n}\n.ML__latex .thickspace {\n display: inline-block;\n width: 0.27778em;\n height: 0.71em;\n}\n.ML__latex .enspace {\n display: inline-block;\n width: 0.5em;\n height: 0.71em;\n}\n.ML__latex .quad {\n display: inline-block;\n width: 1em;\n height: 0.71em;\n}\n.ML__latex .qquad {\n display: inline-block;\n width: 2em;\n height: 0.71em;\n}\n.ML__latex .llap,\n.ML__latex .rlap {\n width: 0;\n position: relative;\n display: inline-block;\n}\n.ML__latex .llap > .inner,\n.ML__latex .rlap > .inner {\n position: absolute;\n}\n.ML__latex .llap > .fix,\n.ML__latex .rlap > .fix {\n display: inline-block;\n}\n.ML__latex .llap > .inner {\n right: 0;\n}\n.ML__latex .rlap > .inner {\n left: 0;\n}\n.ML__latex .rule {\n display: inline-block;\n border: solid 0;\n position: relative;\n box-sizing: border-box;\n}\n.ML__latex .overline .overline-line,\n.ML__latex .underline .underline-line {\n width: 100%;\n}\n.ML__latex .overline .overline-line:before,\n.ML__latex .underline .underline-line:before {\n content: '';\n border-bottom-style: solid;\n border-bottom-width: max(1px, 0.04em);\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n display: block;\n}\n.ML__latex .overline .overline-line:after,\n.ML__latex .underline .underline-line:after {\n border-bottom-style: solid;\n border-bottom-width: max(1px, 0.04em);\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n content: '';\n display: block;\n margin-top: -1px;\n}\n.ML__latex .stretchy {\n display: block;\n position: absolute;\n width: 100%;\n left: 0;\n overflow: hidden;\n}\n.ML__latex .stretchy:before,\n.ML__latex .stretchy:after {\n content: '';\n}\n.ML__latex .stretchy svg {\n display: block;\n position: absolute;\n width: 100%;\n height: inherit;\n fill: currentColor;\n stroke: currentColor;\n fill-rule: nonzero;\n fill-opacity: 1;\n stroke-width: 1;\n stroke-linecap: butt;\n stroke-linejoin: miter;\n stroke-miterlimit: 4;\n stroke-dasharray: none;\n stroke-dashoffset: 0;\n stroke-opacity: 1;\n}\n.ML__latex .slice-1-of-2 {\n display: inline-flex;\n position: absolute;\n left: 0;\n width: 50.2%;\n overflow: hidden;\n}\n.ML__latex .slice-2-of-2 {\n display: inline-flex;\n position: absolute;\n right: 0;\n width: 50.2%;\n overflow: hidden;\n}\n.ML__latex .slice-1-of-3 {\n display: inline-flex;\n position: absolute;\n left: 0;\n width: 25.1%;\n overflow: hidden;\n}\n.ML__latex .slice-2-of-3 {\n display: inline-flex;\n position: absolute;\n left: 25%;\n width: 50%;\n overflow: hidden;\n}\n.ML__latex .slice-3-of-3 {\n display: inline-flex;\n position: absolute;\n right: 0;\n width: 25.1%;\n overflow: hidden;\n}\n.ML__latex .slice-1-of-1 {\n display: inline-flex;\n position: absolute;\n width: 100%;\n left: 0;\n overflow: hidden;\n}\n.ML__latex .nulldelimiter {\n display: inline-block;\n}\n.ML__latex .op-group {\n display: inline-block;\n}\n.ML__latex .op-symbol {\n position: relative;\n}\n.ML__latex .op-symbol.small-op {\n font-family: KaTeX_Size1;\n}\n.ML__latex .op-symbol.large-op {\n font-family: KaTeX_Size2;\n}\n.ML__latex .mtable .vertical-separator {\n display: inline-block;\n min-width: 1px;\n box-sizing: border-box;\n}\n.ML__latex .mtable .arraycolsep {\n display: inline-block;\n}\n.ML__latex .mtable .col-align-m > .vlist-t {\n text-align: center;\n}\n.ML__latex .mtable .col-align-c > .vlist-t {\n text-align: center;\n}\n.ML__latex .mtable .col-align-l > .vlist-t {\n text-align: left;\n}\n.ML__latex .mtable .col-align-r > .vlist-t {\n text-align: right;\n}\n.ML__error {\n display: inline-block;\n background-image: radial-gradient(ellipse at center, hsl(341, 100%, 40%), rgba(0, 0, 0, 0) 70%);\n background-color: hsla(341, 100%, 40%, 0.1);\n background-repeat: repeat-x;\n background-size: 3px 3px;\n padding-bottom: 3px;\n background-position: 0 100%;\n}\n.ML__error > .ML__error {\n background: transparent;\n padding: 0;\n}\n.ML__placeholder {\n color: var(--_placeholder-color);\n opacity: var(--_placeholder-opacity);\n padding-left: 0.4ex;\n padding-right: 0.4ex;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n}\n.ML__notation {\n position: absolute;\n box-sizing: border-box;\n line-height: 0;\n}\n/* This class is used to implement the `\\mathtip` and `\\texttip` commands\n For UI elements, see `[data-ML__tooltip]`\n*/\n.ML__tooltip-container {\n position: relative;\n transform: scale(0);\n}\n.ML__tooltip-container .ML__tooltip-content {\n position: fixed;\n display: inline-table;\n visibility: hidden;\n z-index: 2;\n width: max-content;\n max-width: 400px;\n padding: 12px 12px;\n border-radius: 8px;\n background: #616161;\n --_selection-color: #fff;\n color: #fff;\n box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);\n opacity: 0;\n transition: opacity 0.15s cubic-bezier(0.4, 0, 1, 1);\n}\n.ML__tooltip-container .ML__tooltip-content .ML__text {\n white-space: normal;\n}\n.ML__tooltip-container .ML__tooltip-content .ML__base {\n display: contents;\n}\n.ML__tooltip-container:hover .ML__tooltip-content {\n visibility: visible;\n opacity: 1;\n font-size: 0.75em;\n transform: scale(1) translate(0, 3em);\n}\n"; // css/environment-popover.less var environment_popover_default = "#mathlive-environment-popover.is-visible {\n visibility: visible;\n}\n#mathlive-environment-popover {\n --_environment-panel-height: var(--environment-panel-height, 70px);\n --_accent-color: var(--accent-color, #aaa);\n --_background: var(--environment-panel-background, #fff);\n --_button-background: var(--environment-panel-button-background, white);\n --_button-background-hover: var(--environment-panel-button-background-hover, #f5f5f7);\n --_button-background-active: var(--environment-panel-button-background-active, #f5f5f7);\n --_button-text: var(--environment-panel-button-text, #e3e4e8);\n position: absolute;\n width: calc(var(--_environment-panel-height) * 2);\n height: var(--_environment-panel-height);\n border-radius: 4px;\n border: 1.5px solid var(--_accent-color);\n background-color: var(--_background);\n box-shadow: 0 0 30px 0 var(--environment-shadow, rgba(0, 0, 0, 0.4));\n pointer-events: all;\n visibility: hidden;\n}\n#mathlive-environment-popover .MLEP__array-buttons {\n height: calc(var(--_environment-panel-height) * 5/4);\n width: calc(var(--_environment-panel-height) * 5/4);\n margin-left: calc(0px - var(--_environment-panel-height) * 0.16);\n margin-top: calc(0px - var(--_environment-panel-height) * 0.19);\n}\n#mathlive-environment-popover .MLEP__array-buttons .font {\n fill: white;\n}\n#mathlive-environment-popover .MLEP__array-buttons circle {\n fill: #7f7f7f;\n transition: fill 300ms;\n}\n#mathlive-environment-popover .MLEP__array-buttons .MLEP__array-insert-background {\n fill-opacity: 1;\n fill: var(--_background);\n stroke: var(--_accent-color);\n stroke-width: 3px;\n}\n#mathlive-environment-popover .MLEP__array-buttons line {\n stroke: var(--_accent-color);\n stroke-opacity: 0;\n stroke-width: 40;\n pointer-events: none;\n transition: stroke-opacity 300ms;\n stroke-linecap: round;\n}\n#mathlive-environment-popover .MLEP__array-buttons g[data-command]:hover circle {\n fill: var(--_accent-color);\n}\n#mathlive-environment-popover .MLEP__array-buttons g[data-command]:hover line {\n stroke-opacity: 1;\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls {\n height: 100%;\n width: 50%;\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options {\n width: var(--_environment-panel-height);\n height: var(--_environment-panel-height);\n display: flex;\n flex-wrap: wrap;\n flex-direction: row;\n justify-content: space-around;\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg {\n pointer-events: all;\n margin-top: 2px;\n width: calc(var(--_environment-panel-height) / 3 * 28 / 24);\n height: calc(var(--_environment-panel-height) / 3 - 2px);\n border-radius: calc(var(--_environment-panel-height) / 25);\n background-color: var(--_button-background);\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg:hover {\n background-color: var(--_button-background-hover);\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg path,\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg line {\n stroke: var(--_button-text);\n stroke-width: 2;\n stroke-linecap: round;\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg rect,\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg path {\n fill-opacity: 0;\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg.active {\n pointer-events: none;\n background-color: var(--_button-background-active);\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg.active path,\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg.active line {\n stroke: var(--_accent-color);\n}\n#mathlive-environment-popover .MLEP__environment-delimiter-controls .MLEP__array-delimiter-options svg.active circle {\n fill: var(--_accent-color);\n}\n"; // css/suggestion-popover.less var suggestion_popover_default = `/* The element that display info while in latex mode */ #mathlive-suggestion-popover { background-color: rgba(97, 97, 97); color: #fff; text-align: center; border-radius: 8px; position: fixed; z-index: 1; display: none; flex-direction: column; justify-content: center; box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); } #mathlive-suggestion-popover.top-tip::after { content: ''; position: absolute; top: -15px; left: calc(50% - 15px); width: 0; height: 0; border-left: 15px solid transparent; border-right: 15px solid transparent; border-bottom: 15px solid rgba(97, 97, 97); font-size: 1rem; } #mathlive-suggestion-popover.bottom-tip::after { content: ''; position: absolute; bottom: -15px; left: calc(50% - 15px); width: 0; height: 0; border-left: 15px solid transparent; border-right: 15px solid transparent; border-top: 15px solid rgba(97, 97, 97); font-size: 1rem; } #mathlive-suggestion-popover.is-animated { transition: all 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); animation: ML__fade-in cubic-bezier(0, 0, 0.2, 1) 0.15s; } #mathlive-suggestion-popover.is-visible { display: flex; } @keyframes ML__fade-in { from { opacity: 0; } to { opacity: 1; } } /* The wrapper class for the entire content of the popover panel */ #mathlive-suggestion-popover ul { display: flex; flex-flow: column; list-style: none; margin: 0; padding: 0; align-items: flex-start; max-height: 400px; overflow-y: auto; } #mathlive-suggestion-popover li { display: flex; flex-direction: row; justify-content: space-between; margin: 8px; padding: 8px; width: calc(100% - 16px - 16px); column-gap: 1em; border-radius: 8px; cursor: pointer; /* Since the content can be clicked on, provide feedback on hover */ } #mathlive-suggestion-popover li a { color: #5ea6fd; padding-top: 0.3em; margin-top: 0.4em; display: block; } #mathlive-suggestion-popover li a:hover { color: #5ea6fd; text-decoration: underline; } #mathlive-suggestion-popover li:hover, #mathlive-suggestion-popover li.is-pressed, #mathlive-suggestion-popover li.is-active { background: rgba(255, 255, 255, 0.1); } /* The command inside a popover (inside a #mathlive-suggestion-popover) */ .ML__popover__command { font-size: 1.6rem; font-family: KaTeX_Main; } .ML__popover__current { background: #5ea6fd; color: #fff; } .ML__popover__latex { font-family: 'IBM Plex Mono', 'Source Code Pro', Consolas, 'Roboto Mono', Menlo, 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Courier, monospace; align-self: center; } /* The keyboard shortcuts for a symbol as displayed in the popover */ .ML__popover__keybinding { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 0.8em; opacity: 0.7; } /* Style for the character that joins the modifiers of a keyboard shortcut (usually a "+" sign)*/ .ML__shortcut-join { opacity: 0.5; } `; // css/keystroke-caption.less var keystroke_caption_default = "/* The element that displays the keys as the user type them */\n#mathlive-keystroke-caption-panel {\n visibility: hidden;\n /*min-width: 160px;*/\n /*background-color: rgba(97, 97, 200, .95);*/\n background: var(--secondary, hsl(var(--_hue), 19%, 26%));\n border-color: var(--secondary-border, hsl(0, 0%, 91%));\n box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);\n text-align: center;\n border-radius: 6px;\n padding: 16px;\n position: absolute;\n z-index: 1;\n display: flex;\n flex-direction: row-reverse;\n justify-content: center;\n --keystroke: white;\n --on-keystroke: #555;\n --keystroke-border: #f7f7f7;\n}\n@media (prefers-color-scheme: dark) {\n body:not([theme='light']) #mathlive-keystroke-caption-panel {\n --keystroke: hsl(var(--_hue), 50%, 30%);\n --on-keystroke: hsl(0, 0%, 98%);\n --keystroke-border: hsl(var(--_hue), 50%, 25%);\n }\n}\nbody[theme='dark'] #mathlive-keystroke-caption-panel {\n --keystroke: hsl(var(--_hue), 50%, 30%);\n --on-keystroke: hsl(0, 0%, 98%);\n --keystroke-border: hsl(var(--_hue), 50%, 25%);\n}\n#mathlive-keystroke-caption-panel > span {\n min-width: 14px;\n /*height: 8px;*/\n margin: 0 8px 0 0;\n padding: 4px;\n background-color: var(--keystroke);\n color: var(--on-keystroke);\n fill: currentColor;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n font-size: 1em;\n border-radius: 6px;\n border: 2px solid var(--keystroke-border);\n /*box-shadow: 0 7px 14px rgba(0,0,0,0.25), 0 5px 5px rgba(0,0,0,0.22);*/\n}\n"; // css/virtual-keyboard.less var virtual_keyboard_default = `.ML__keyboard { --_keyboard-height: 0; --_keyboard-zindex: var(--keyboard-zindex, 105); --_accent-color: var(--keyboard-accent-color, #0c75d8); --_background: var(--keyboard-background, #cacfd7); --_border: var(--keyboard-border, #ddd); --_padding-horizontal: var(--keyboard-padding-horizontal, 0px); --_padding-top: var(--keyboard-padding-top, 5px); --_padding-bottom: var(--keyboard-padding-bottom, 0px); --_row-padding-left: var(--keyboard-row-padding-left, 0px); --_row-padding-right: var(--keyboard-row-padding-right, 0px); --_toolbar-text: var(--keyboard-toolbar-text, #2c2e2f); --_toolbar-text-active: var(--keyboard-toolbar-text-active, var(--_accent-color)); --_toolbar-background: var(--keyboard-toolbar-background, transparent); --_toolbar-background-hover: var(--keyboard-toolbar-background-hover, #eee); --_toolbar-background-selected: var(--keyboard-toolbar-background-selected, transparent); --_toolbar-font-size: var(--keyboard-toolbar-font-size, '135%'); --_horizontal-rule: var(--keyboard-horizontal-rule, 1px solid #fff); --_keycap-background: var(--keycap-background, white); --_keycap-background-hover: var(--keycap-background-hover, #f5f5f7); --_keycap-background-active: var(--keycap-background-active, var(--_accent-color)); --_keycap-background-pressed: var(--keycap-background-pressed, var(--_accent-color)); --_keycap-border: var(--keycap-border, #e5e6e9); --_keycap-border-bottom: var(--keycap-border-bottom, #8d8f92); --_keycap-text: var(--keycap-text, #000); --_keycap-text-active: var(--keycap-text-active, #fff); --_keycap-text-hover: var(--keycap-text-hover, var(--_keycap-text)); --_keycap-text-pressed: var(--keycap-text-pressed, #fff); --_keycap-shift-text: var(--keycap-shift-text, var(--_accent-color)); --_keycap-primary-background: var(--keycap-primary-background, var(--_accent-color)); --_keycap-primary-text: var(--keycap-primary-text, #ddd); --_keycap-primary-background-hover: var(--keycap-primary-background-hover, #0d80f2); --_keycap-secondary-background: var(--keycap-secondary-background, #a0a9b8); --_keycap-secondary-background-hover: var(--keycap-secondary-background-hover, #7d8795); --_keycap-secondary-text: var(--keycap-secondary-text, #060707); --_keycap-secondary-border: var(--keycap-secondary-border, #c5c9d0); --_keycap-secondary-border-bottom: var(--keycap-secondary-border-bottom, #989da6); --_keycap-height: var(--keycap-height, 60px); /* Keycap width (incl. margin) */ --_keycap-max-width: var(--keycap-max-width, 100px); --_keycap-gap: var(--keycap-gap, 8px); --_keycap-font-size: var(--keycap-font-size, clamp(16px, 4cqw, 24px)); --_keycap-small-font-size: var(--keycap-small-font-size, calc(var(--keycap-font-size) * 0.8)); --_keycap-extra-small-font-size: var(--keycap-extra-small-font-size, calc(var(--keycap-font-size) / 1.42)); --_variant-panel-background: var(--variant-panel-background, #fff); --_variant-keycap-text: var(--variant-keycap-text, var(--_keycap-text)); --_variant-keycap-text-active: var(--variant-keycap-text-active, var(--_keycap-text-active)); --_variant-keycap-background-active: var(--variant-keycap-background-active, var(--_accent-color)); --_variant-keycap-length: var(--variant-keycap-length, 70px); --_variant-keycap-font-size: var(--variant-keycap-font-size, 30px); --_variant-keycap-aside-font-size: var(--variant-keycap-aside-font-size, 12px); --_keycap-shift-font-size: var(--keycap-shift-font-size, 16px); --_keycap-shift-color: var(--keycap-shift-color, var(--_accent-color)); --_box-placeholder-color: var(--box-placeholder-color, var(--_accent-color)); --_box-placeholder-pressed-color: var(--box-placeholder-pressed-color, var(--keycap-text-pressed)); } .is-math-mode .MLK__rows .if-text-mode, .is-text-mode .MLK__rows .if-math-mode { display: none; } .if-can-undo, .if-can-redo, .if-can-copy, .if-can-cut, .if-can-paste { opacity: 0.4; pointer-events: none; } .can-undo .if-can-undo, .can-redo .if-can-redo, .can-copy .if-can-copy, .can-cut .if-can-cut, .can-paste .if-can-paste { opacity: 1; pointer-events: all; } body > .ML__keyboard { position: fixed; --_padding-bottom: calc(var(--keyboard-padding-bottom, 0px) + env(safe-area-inset-bottom, 0)); } body > .ML__keyboard.is-visible > .MLK__backdrop { box-shadow: 0 -5px 6px rgba(0, 0, 0, 0.08); border-top: 1px solid var(--_border); } body > .ML__keyboard.backdrop-is-transparent.is-visible > .MLK__backdrop { box-shadow: none; border: none; } body > .ML__keyboard.is-visible.animate > .MLK__backdrop { transition: 0.28s cubic-bezier(0, 0, 0.2, 1); transition-property: transform, opacity; transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } .ML__keyboard { position: relative; overflow: hidden; top: 0; left: 0; height: 100%; width: 100%; z-index: var(--_keyboard-zindex); box-sizing: border-box; outline: none; border: none; margin: 0; padding: 0; line-height: 1; overflow-wrap: unset; text-align: left; vertical-align: baseline; cursor: auto; white-space: pre; box-shadow: none; opacity: 1; transform: none; pointer-events: none; } .ML__keyboard :where(div) { box-sizing: border-box; outline: none; border: none; margin: 0; padding: 0; line-height: 1; overflow-wrap: unset; text-align: left; vertical-align: baseline; cursor: auto; white-space: pre; box-shadow: none; transform: none; } .MLK__backdrop { position: absolute; bottom: calc(-1 * var(--_keyboard-height)); width: 100%; height: var(--_keyboard-height); box-sizing: border-box; padding-top: var(--_padding-top); padding-bottom: var(--_padding-bottom); padding-left: var(--_padding-horizontal); padding-right: var(--_padding-horizontal); opacity: 0; visibility: hidden; transform: translate(0, 0); background: var(--_background); } .backdrop-is-transparent .MLK__backdrop { background: transparent; } /* If a custom layout has a custom container/backdrop (backdrop-is-transparent), make sure to let pointer event go through. */ .backdrop-is-transparent .MLK__plate { background: transparent; pointer-events: none; } /* If a custom layout has a custom container/backdrop, make sure to allow pointer events on it. */ .backdrop-is-transparent .MLK__layer > div > div { pointer-events: all; } .ML__keyboard.is-visible > .MLK__backdrop { transform: translate(0, calc(-1 * var(--_keyboard-height))); opacity: 1; visibility: visible; } .caps-lock-indicator { display: none; width: 8px; height: 8px; background: #0cbc0c; box-shadow: inset 0 0 4px 0 #13ca13, 0 0 4px 0 #a9ef48; border-radius: 8px; right: 8px; top: 8px; position: absolute; } .ML__keyboard.is-caps-lock .caps-lock-indicator { display: block; } .ML__keyboard.is-caps-lock .shift { background: var(--_keycap-background-active); color: var(--_keycap-text-active); } .MLK__plate { position: absolute; top: var(--_padding-top); left: var(--_padding-horizontal); width: calc(100% - 2 * var(--_padding-horizontal)); margin: 0; padding: 0; box-sizing: border-box; container-type: inline-size; touch-action: none; -webkit-user-select: none; user-select: none; pointer-events: all; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 16px; /* Size of toolbar labels */ font-weight: 400; text-shadow: none; } .ML__box-placeholder { color: var(--_box-placeholder-color); } .MLK__tex { font-family: KaTeX_Main, KaTeX_Math, 'Cambria Math', 'Asana Math', OpenSymbol, Symbola, STIX, Times, serif !important; } .MLK__tex-math { font-family: KaTeX_Math, KaTeX_Main, 'Cambria Math', 'Asana Math', OpenSymbol, Symbola, STIX, Times, serif !important; font-style: italic; } .MLK__layer { display: none; outline: none; } .MLK__layer.is-visible { display: flex; flex-flow: column; } /* Keyboard layouts are made or rows of keys... */ .MLK__rows { --_keycap-width: min(var(--_keycap-max-width), 10cqw); display: flex; flex-flow: column; align-items: center; border-collapse: separate; clear: both; border: 0; margin: 0; margin-bottom: var(--_keycap-gap); gap: var(--_keycap-gap); /* If the styling include, e.g., some shadows, they will be cut off by the overflow. In that case, set the padding to compensate. */ padding-left: var(--_row-padding-left); padding-right: var(--_row-padding-right); overflow: visible; touch-action: none; } .MLK__rows > .MLK__row { display: flex; flex-flow: row; justify-content: center; width: 100%; gap: var(--_keycap-gap); margin: 0; padding: 0; /* For the alignment of the text on some modifiers (e.g. shift) */ /* Extra spacing between two adjacent keys */ } .MLK__rows > .MLK__row .tex { font-family: KaTeX_Math, KaTeX_Main, 'Cambria Math', 'Asana Math', OpenSymbol, Symbola, STIX, Times, serif !important; } .MLK__rows > .MLK__row .tex-math { font-family: KaTeX_Math, 'Cambria Math', 'Asana Math', OpenSymbol, Symbola, STIX, Times, serif !important; } .MLK__rows > .MLK__row .big-op { font-size: calc(1.25 * var(--_keycap-font-size)); } .MLK__rows > .MLK__row .small { font-size: var(--_keycap-small-font-size); } .MLK__rows > .MLK__row .bottom { justify-content: flex-end; } .MLK__rows > .MLK__row .left { align-items: flex-start; padding-left: 12px; } .MLK__rows > .MLK__row .right { align-items: flex-end; padding-right: 12px; } .MLK__rows > .MLK__row .w0 { width: 0; } .MLK__rows > .MLK__row .w5 { width: calc(0.5 * var(--_keycap-width) - var(--_keycap-gap)); } .MLK__rows > .MLK__row .w15 { width: calc(1.5 * var(--_keycap-width) - var(--_keycap-gap)); } .MLK__rows > .MLK__row .w20 { width: calc(2 * var(--_keycap-width) - var(--_keycap-gap)); } .MLK__rows > .MLK__row .w40 { width: calc(4 * var(--_keycap-width) - var(--_keycap-gap)); } .MLK__rows > .MLK__row .w50 { width: calc(5 * var(--_keycap-width) - var(--_keycap-gap)); } .MLK__rows > .MLK__row .MLK__keycap.w50 { font-size: 80%; padding-top: 10px; font-weight: 100; } .MLK__rows > .MLK__row .separator { background: transparent; border: none; pointer-events: none; } .MLK__rows > .MLK__row .horizontal-rule { height: 6px; margin-top: 3px; margin-bottom: 0; width: 100%; border-radius: 0; border-top: var(--_horizontal-rule); } .MLK__rows > .MLK__row .ghost { background: var(--_toolbar-background); border: none; color: var(--_toolbar-text); } .MLK__rows > .MLK__row .ghost:hover { background: var(--_toolbar-background-hover); } .MLK__rows > .MLK__row .bigfnbutton { font-size: var(--_keycap-extra-small-font-size); } .MLK__rows > .MLK__row .shift, .MLK__rows > .MLK__row .action { color: var(--_keycap-secondary-text); background: var(--_keycap-secondary-background); border-color: var(--_keycap-secondary-border); border-bottom-color: var(--_keycap-secondary-border-bottom); line-height: 0.8; font-size: min(1rem, var(--_keycap-small-font-size)); font-weight: 600; padding: 8px 12px 8px 12px; } .MLK__rows > .MLK__row .shift:hover, .MLK__rows > .MLK__row .action:hover { background: var(--_keycap-secondary-background-hover); } .MLK__rows > .MLK__row .action.primary { background: var(--_keycap-primary-background); color: var(--_keycap-primary-text); } .MLK__rows > .MLK__row .action.primary:hover { background: var(--_keycap-primary-background-hover); color: var(--_keycap-primary-text); } .MLK__rows > .MLK__row .shift.selected, .MLK__rows > .MLK__row .action.selected { color: var(--_toolbar-text-active); } .MLK__rows > .MLK__row .shift.selected.is-pressed, .MLK__rows > .MLK__row .action.selected.is-pressed, .MLK__rows > .MLK__row .shift.selected.is-active, .MLK__rows > .MLK__row .action.selected.is-active { color: white; } .MLK__rows > .MLK__row .warning { background: #cd0030; color: white; } .MLK__rows > .MLK__row .warning svg.svg-glyph { width: 24px; height: 24px; min-height: 24px; } /** A regular keycap * Use the :where() pseudo-class to give it a very low specifity, * so that it can be overriden by custom style. */ :where(.MLK__rows > .MLK__row div) { display: flex; flex-flow: column; align-items: center; justify-content: space-evenly; width: calc(var(--_keycap-width) - var(--_keycap-gap)); height: var(--_keycap-height); box-sizing: border-box; padding: 0; vertical-align: top; text-align: center; float: left; color: var(--_keycap-text); fill: currentColor; font-size: var(--_keycap-font-size); background: var(--_keycap-background); border: 1px solid var(--_keycap-border); border-bottom-color: var(--_keycap-border-bottom); border-radius: 6px; cursor: pointer; touch-action: none; /* Keys with a variants panel */ position: relative; overflow: hidden; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; } :where(.MLK__rows > .MLK__row div):hover { overflow: visible; background: var(--_keycap-background-hover); } :where(.MLK__rows > .MLK__row div) .ML__latex { pointer-events: none; touch-action: none; } :where(.MLK__rows > .MLK__row div) svg.svg-glyph { margin: 8px 0; width: 20px; height: 20px; min-height: 20px; } :where(.MLK__rows > .MLK__row div) svg.svg-glyph-lg { margin: 8px 0; width: 24px; height: 24px; min-height: 24px; } :where(.MLK__rows > .MLK__row div).MLK__tex-math { font-size: 25px; } :where(.MLK__rows > .MLK__row div).is-pressed { background: var(--_keycap-background-pressed); color: var(--_keycap-text-pressed); --_box-placeholder-color: var(--_box-placeholder-pressed-color); } :where(.MLK__rows > .MLK__row div).MLK__keycap.is-active, :where(.MLK__rows > .MLK__row div).action.is-active, :where(.MLK__rows > .MLK__row div).MLK__keycap.is-pressed, :where(.MLK__rows > .MLK__row div).action.is-pressed { z-index: calc(var(--_keyboard-zindex) - 5); } :where(.MLK__rows > .MLK__row div).MLK__keycap.is-active aside, :where(.MLK__rows > .MLK__row div).action.is-active aside, :where(.MLK__rows > .MLK__row div).MLK__keycap.is-pressed aside, :where(.MLK__rows > .MLK__row div).action.is-pressed aside { display: none; } :where(.MLK__rows > .MLK__row div).MLK__keycap.is-active .MLK__shift, :where(.MLK__rows > .MLK__row div).action.is-active .MLK__shift, :where(.MLK__rows > .MLK__row div).MLK__keycap.is-pressed .MLK__shift, :where(.MLK__rows > .MLK__row div).action.is-pressed .MLK__shift { display: none; } :where(.MLK__rows > .MLK__row div).shift.is-pressed, :where(.MLK__rows > .MLK__row div).MLK__keycap.is-pressed, :where(.MLK__rows > .MLK__row div).action.is-pressed { background: var(--_keycap-background-pressed); color: var(--_keycap-text-pressed); } :where(.MLK__rows > .MLK__row div).shift.is-active, :where(.MLK__rows > .MLK__row div).MLK__keycap.is-active, :where(.MLK__rows > .MLK__row div).action.is-active { background: var(--_keycap-background-active); color: var(--_keycap-text-active); --_box-placeholder-color: var(--_box-placeholder-pressed-color); } :where(.MLK__rows > .MLK__row div) small { color: var(--_keycap-secondary-text); } :where(.MLK__rows > .MLK__row div) aside { font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 10px; line-height: 10px; color: var(--_keycap-secondary-text); } /* Add an attribute 'data-tooltip' to display a tooltip on hover. Note there are a different set of tooltip rules for the keyboard toggle (it's in a different CSS tree) */ .ML__keyboard [data-tooltip] { position: relative; } .ML__keyboard [data-tooltip]::after { position: absolute; display: inline-table; content: attr(data-tooltip); top: inherit; bottom: 100%; width: max-content; max-width: 200px; padding: 8px 8px; background: #616161; color: #fff; text-align: center; z-index: 2; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); border-radius: 2px; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-weight: 400; font-size: 12px; transition: all 0.15s cubic-bezier(0.4, 0, 1, 1) 1s; opacity: 0; transform: scale(0.5); } .ML__keyboard [data-tooltip]:hover { position: relative; } .ML__keyboard [data-tooltip]:hover::after { opacity: 1; transform: scale(1); } .MLK__toolbar { align-self: center; display: flex; flex-flow: row; justify-content: space-between; width: 100%; max-width: 996px; min-height: 32px; /* Icons for undo/redo, etc. */ } .MLK__toolbar svg { height: 20px; width: 20px; } .MLK__toolbar > .left { position: relative; display: flex; justify-content: flex-start; flex-flow: row; } .MLK__toolbar > .right { display: flex; justify-content: flex-end; flex-flow: row; } .MLK__toolbar > div > div { /* "button" in the toolbar */ display: flex; align-items: center; justify-content: center; color: var(--_toolbar-text); fill: currentColor; background: var(--_toolbar-background); font-size: var(--_toolbar-font-size); padding: 4px 15px; cursor: pointer; width: max-content; min-width: 42px; min-height: 34px; border: none; padding-left: 10px; padding-right: 10px; padding-bottom: 8px; padding-top: 8px; margin-top: 0; margin-bottom: 4px; margin-left: 4px; margin-right: 4px; border-radius: 8px; box-shadow: none; border-bottom: 2px solid transparent; } .MLK__toolbar > div > div:not(.disabled):not(.selected):hover { background: var(--_toolbar-background-hover); } .MLK__toolbar > div > div.disabled svg, .MLK__toolbar > div > div.disabled:hover svg, .MLK__toolbar > div > div.disabled.is-pressed svg { color: var(--_toolbar-text); opacity: 0.2; } .MLK__toolbar > div > div:hover, .MLK__toolbar > div > div:active, .MLK__toolbar > div > div.is-pressed, .MLK__toolbar > div > div.is-active { color: var(--_toolbar-text-active); } .MLK__toolbar > div > div.selected { color: var(--_toolbar-text-active); background: var(--_toolbar-background-selected); border-radius: 0; border-bottom-color: var(--_toolbar-text-active); padding-bottom: 4px; margin-bottom: 8px; } /* This is the element that displays variants on press+hold */ .MLK__variant-panel { visibility: hidden; position: fixed; display: flex; flex-flow: row wrap-reverse; justify-content: center; align-content: center; margin: 0; padding: 0; bottom: auto; top: 0; box-sizing: content-box; transform: none; z-index: calc(var(--_keyboard-zindex) + 1); touch-action: none; max-width: 350px; background: var(--_variant-panel-background); text-align: center; border-radius: 6px; padding: 6px; box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); transition: none; } .MLK__variant-panel.is-visible { visibility: visible; } .MLK__variant-panel.compact { --_variant-keycap-length: var(--variant-keycap-length, 50px); --_variant-keycap-font-size: var(--variant-keycap-font-size, 24px); --_variant-keycap-aside-font-size: var(--variant-keycap-aside-font-size, 10px); } .MLK__variant-panel .item { display: flex; flex-flow: column; align-items: center; justify-content: center; font-size: var(--_variant-keycap-font-size); height: var(--_variant-keycap-length); width: var(--_variant-keycap-length); margin: 0; box-sizing: border-box; border-radius: 5px; border: 1px solid transparent; background: transparent; pointer-events: all; cursor: pointer; color: var(--_variant-keycap-text); fill: currentColor; } @media (max-height: 412px) { .MLK__variant-panel .item { --_variant-keycap-font-size: var(--variant-keycap-font-size, 24px); --_variant-keycap-length: var(--variant-keycap-length, 50px); } } .MLK__variant-panel .item .ML__latex { pointer-events: none; } .MLK__variant-panel .item.is-active { background: var(--_variant-keycap-background-active); color: var(--_variant-keycap-text-active); } .MLK__variant-panel .item.is-pressed { background: var(--_variant-keycap-background-pressed); color: var(--_variant-keycap-text-pressed); } .MLK__variant-panel .item.small { font-size: var(--_keycap-small-font-size); } .MLK__variant-panel .item.swatch-button { box-sizing: border-box; background: #fbfbfb; } .MLK__variant-panel .item.swatch-button > span { display: inline-block; margin: 6px; width: calc(100% - 12px); height: calc(100% - 12px); border-radius: 50%; } .MLK__variant-panel .item.swatch-button:hover { background: #f0f0f0; } .MLK__variant-panel .item.swatch-button:hover > span { border-radius: 2px; } .MLK__variant-panel .item.box > div, .MLK__variant-panel .item.box > span { border: 1px dashed rgba(0, 0, 0, 0.24); } .MLK__variant-panel .item .warning { min-height: 60px; min-width: 60px; background: #cd0030; color: white; padding: 5px; display: flex; align-items: center; justify-content: center; border-radius: 5px; } .MLK__variant-panel .item .warning.is-pressed, .MLK__variant-panel .item .warning.is-active { background: red; } .MLK__variant-panel .item .warning svg.svg-glyph { width: 50px; height: 50px; } .MLK__variant-panel .item aside { font-size: var(--_variant-keycap-aside-font-size); line-height: 12px; opacity: 0.78; padding-top: 2px; } .MLK__keycap { position: relative; } .MLK__shift { display: block; position: absolute; right: 4px; top: 4px; font-size: var(--_keycap-shift-font-size); color: var(--_keycap-shift-color); } .hide-shift .MLK__shift { display: none; } @media (max-width: 414px) { .MLK__variant-panel { max-width: 350px; --_variant-keycap-font-size: var(--variant-keycap-font-size, 24px); --_variant-keycap-length: var(--variant-keycap-length, 50px); } } /* @xs breakpoint: iPhone 5 */ @container (max-width: 414px) { .MLK__rows { --_keycap-gap: max(var(--_keycap-gap, 2px), 2px); --_keycap-height: max(var(--_keycap-height), 42px); --_keycap-width: min(min(var(--_keycap-max-width), 10cqw), 62px); } .MLK__toolbar > div > div { font-size: 100%; margin-left: 2px; margin-right: 2px; } .MLK__rows .shift, .MLK__rows .action { font-size: 65%; } .MLK__rows .warning svg.svg-glyph { width: 14px; height: 14px; min-height: 14px; } } @container (max-width: 744px) { .MLK__rows { --_keycap-gap: max(var(--keycap-gap, 2px), 2px); --_keycap-height: max(var(--keycap-height, 52px), 52px); --_keycap-width: min(min(var(--_keycap-max-width), 10cqw), 62px); } .MLK__toolbar > div > div { padding-left: 0; padding-right: 0; } .MLK__tooltip::after { padding: 8px 16px; font-size: 16px; } .MLK__rows > .MLK__row > div.fnbutton { font-size: 16px; } .MLK__rows > .MLK__row > div.bigfnbutton { font-size: calc(var(--_keycap-extra-small-font-size) / 1.55); } .MLK__rows > .MLK__row > div.small { font-size: 13px; } .MLK__rows > .MLK__row > div > aside { display: none; } .MLK__shift { display: none; } } /* Medium breakpoint: larger phones */ @container (max-width: 768px) { .MLK__rows { --_keycap-height: max(var(--keycap-height, 42px), 42px); } .MLK__rows > .MLK__row > div > small { font-size: 14px; } } @media (max-height: 768px) { .MLK__rows { --_keycap-height: max(var(--keycap-height, 42px), 42px); } .MLK__rows > .MLK__row > div > small { font-size: 14px; } } @container (max-width: 1444px) { .MLK__rows .if-wide { display: none; } } @media (prefers-color-scheme: dark) { .ML__keyboard { --_accent-color: var(--keyboard-accent-color, #0b5c9c); --_background: var(--keyboard-background, #151515); --_border: var(--keyboard-border, transparent); --_toolbar-text: var(--keyboard-toolbar-text, #e3e4e8); --_toolbar-background-hover: var(--keyboard-toolbar-background-hover, #303030); --keyboard-toolbar-background-hover: #303030; --_horizontal-rule: var(--keyboard-horizontal-rule, 1px solid #303030); --_keycap-background: var(--keycap-background, #1f2022); --_keycap-background-hover: var(--keycap-background-hover, #2f3032); --_keycap-border: var(--_keycap-border, transparent); --_keycap-border-bottom: var(--_keycap-border-bottom, transparent); --_keycap-text: var(--keycap-text, #e3e4e8); --_keycap-secondary-background: var(--keycap-secondary-background, #3d4144); --_keycap-secondary-background-hover: var(--keycap-secondary-background-hover, #4d5154); --_keycap-secondary-text: var(--keycap-secondary-text, #e7ebee); --keycap-secondary-border: transparent; --keycap-secondary-border-bottom: transparent; --_keycap-secondary-border: var(--keycap-secondary-border, transparent); --_keycap-secondary-border-bottom: var(--keycap-secondary-border-bottom, transparent); --_variant-panel-background: var(--variant-panel-background, #303030); --_variant-keycap-text-active: var(--variant-keycap-text-active, #fff); } } /* Same as the media query, but with a class */ [theme='dark'] .ML__keyboard { --_accent-color: var(--keyboard-accent-color, #0b5c9c); --_background: var(--keyboard-background, #151515); --_border: var(--keyboard-border, transparent); --_toolbar-text: var(--keyboard-toolbar-text, #e3e4e8); --_toolbar-background-hover: var(--keyboard-toolbar-background-hover, #303030); --keyboard-toolbar-background-hover: #303030; --_horizontal-rule: var(--keyboard-horizontal-rule, 1px solid #303030); --_keycap-background: var(--keycap-background, #1f2022); --_keycap-background-hover: var(--keycap-background-hover, #2f3032); --_keycap-border: var(--_keycap-border, transparent); --_keycap-border-bottom: var(--_keycap-border-bottom, transparent); --_keycap-text: var(--keycap-text, #e3e4e8); --_keycap-secondary-background: var(--keycap-secondary-background, #3d4144); --_keycap-secondary-background-hover: var(--keycap-secondary-background-hover, #4d5154); --_keycap-secondary-text: var(--keycap-secondary-text, #e7ebee); --keycap-secondary-border: transparent; --keycap-secondary-border-bottom: transparent; --_keycap-secondary-border: var(--keycap-secondary-border, transparent); --_keycap-secondary-border-bottom: var(--keycap-secondary-border-bottom, transparent); --_variant-panel-background: var(--variant-panel-background, #303030); --_variant-keycap-text-active: var(--variant-keycap-text-active, #fff); } [theme='light'] .ML__keyboard { --_accent-color: var(--keyboard-accent-color, #0c75d8); --_background: var(--keyboard-background, #cacfd7); --_border: var(--keyboard-border, #ddd); --_toolbar-text: var(--keyboard-toolbar-text, #2c2e2f); --_toolbar-background: var(--keyboard-toolbar-background, transparent); --_toolbar-background-hover: var(--keyboard-toolbar-background-hover, #eee); --_toolbar-background-selected: var(--keyboard-toolbar-background-selected, transparent); --_horizontal-rule: var(--keyboard-horizontal-rule, 1px solid #fff); --_keycap-background: var(--keycap-background, white); --_keycap-background-hover: var(--keycap-background-hover, #f5f5f7); --_keycap-background-active: var(--keycap-background-active, var(--_accent-color)); --_keycap-background-pressed: var(--keycap-background-pressed, var(--_accent-color)); --_keycap-border: var(--_keycap-border, #e5e6e9); --_keycap-border-bottom: var(--_keycap-border-bottom, #8d8f92); --_keycap-text: var(--keycap-text, #000); --_keycap-text-active: var(--keycap-text-active, #fff); --_keycap-text-hover: var(--keycap-text-hover, var(--_keycap-text)); --_keycap-text-pressed: var(--keycap-text-pressed, #fff); --_keycap-shift-text: var(--keycap-shift-text, var(--_accent-color)); --_keycap-secondary-background: var(--keycap-secondary-background, #a0a9b8); --_keycap-secondary-background-hover: var(--keycap-secondary-background-hover, #7d8795); --_keycap-secondary-text: var(--keycap-secondary-text, #060707); --_keycap-secondary-border: var(--keycap-secondary-border, #c5c9d0); --_keycap-secondary-border-bottom: var(--keycap-secondary-border-bottom, #989da6); --_variant-panel-background: var(--variant-panel-background, #fff); --_variant-keycap-text: var(--variant-keycap-textvar, var(--_keycap-text)); --_variant-keycap-text-active: var(--variant-keycap-text-active, var(--_keycap-text-active)); --_variant-keycap-background-active: var(--variant-keycap-background-active, var(--_accent-color)); } `; // src/ui/style.less var style_default = ":host {\n --primary-color: #5898ff;\n --primary-color-dimmed: #c0c0f0;\n --primary-color-dark: var(--blue-500);\n --primary-color-light: var(--blue-100);\n --primary-color-reverse: #ffffff;\n --secondary-color: #ff8a65;\n --secondary-color-dimmed: #f0d5c5;\n --secondary-color-dark: var(--orange-500);\n --secondary-color-light: var(--orange-100);\n --secondary-color-reverse: #ffffff;\n --link-color: #5898ff;\n --link-color-dimmed: #c5c5c5;\n --link-color-dark: #121212;\n --link-color-light: #e2e2e2;\n --link-color-reverse: #ffffff;\n --semantic-blue: var(--blue-700);\n --semantic-red: var(--red-400);\n --semantic-orange: var(--orange-400);\n --semantic-green: var(--green-700);\n --neutral-100: #f5f5f5;\n --neutral-200: #eeeeee;\n --neutral-300: #e0e0e0;\n --neutral-400: #bdbdbd;\n --neutral-500: #9e9e9e;\n --neutral-600: #757575;\n --neutral-700: #616161;\n --neutral-800: #424242;\n --neutral-900: #212121;\n --red-25: #fff8f7;\n --red-50: #fff1ef;\n --red-100: #ffeae6;\n --red-200: #ffcac1;\n --red-300: #ffa495;\n --red-400: #ff7865;\n --red-500: #f21c0d;\n --red-600: #e50018;\n --red-700: #d30024;\n --red-800: #bd002c;\n --red-900: #a1002f;\n --orange-25: #fffbf8;\n --orange-50: #fff7f1;\n --orange-100: #fff3ea;\n --orange-200: #ffe1c9;\n --orange-300: #ffcca2;\n --orange-400: #ffb677;\n --orange-500: #fe9310;\n --orange-600: #f58700;\n --orange-700: #ea7c00;\n --orange-800: #dc6d00;\n --orange-900: #ca5b00;\n --brown-25: #fff8ef;\n --brown-50: #fff1df;\n --brown-100: #ffe9ce;\n --brown-200: #ebcca6;\n --brown-300: #cdaf8a;\n --brown-400: #af936f;\n --brown-500: #856a47;\n --brown-600: #7f5e34;\n --brown-700: #78511f;\n --brown-800: #6e4200;\n --brown-900: #593200;\n --yellow-25: #fffdf9;\n --yellow-50: #fffcf2;\n --yellow-100: #fffaec;\n --yellow-200: #fff2ce;\n --yellow-300: #ffe8ab;\n --yellow-400: #ffdf85;\n --yellow-500: #ffcf33;\n --yellow-600: #f1c000;\n --yellow-700: #dfb200;\n --yellow-800: #c9a000;\n --yellow-900: #ad8a00;\n --lime-25: #f4ffee;\n --lime-50: #e9ffdd;\n --lime-100: #ddffca;\n --lime-200: #a8fb6f;\n --lime-300: #94e659;\n --lime-400: #80d142;\n --lime-500: #63b215;\n --lime-600: #45a000;\n --lime-700: #268e00;\n --lime-800: #007417;\n --lime-900: #005321;\n --green-25: #f5fff5;\n --green-50: #ebffea;\n --green-100: #e0ffdf;\n --green-200: #a7ffa7;\n --green-300: #5afa65;\n --green-400: #45e953;\n --green-500: #17cf36;\n --green-600: #00b944;\n --green-700: #00a34a;\n --green-800: #008749;\n --green-900: #00653e;\n --teal-25: #f3ffff;\n --teal-50: #e6fffe;\n --teal-100: #d9fffe;\n --teal-200: #8dfffe;\n --teal-300: #57f4f4;\n --teal-400: #43e5e5;\n --teal-500: #17cfcf;\n --teal-600: #00c2c0;\n --teal-700: #00b5b1;\n --teal-800: #00a49e;\n --teal-900: #009087;\n --cyan-25: #f7fcff;\n --cyan-50: #eff8ff;\n --cyan-100: #e7f5ff;\n --cyan-200: #c2e6ff;\n --cyan-300: #95d5ff;\n --cyan-400: #61c4ff;\n --cyan-500: #13a7ec;\n --cyan-600: #069eda;\n --cyan-700: #0095c9;\n --cyan-800: #0088b2;\n --cyan-900: #0a7897;\n --blue-25: #f7faff;\n --blue-50: #eef5ff;\n --blue-100: #e5f1ff;\n --blue-200: #bfdbff;\n --blue-300: #92c2ff;\n --blue-400: #63a8ff;\n --blue-500: #0d80f2;\n --blue-600: #0077db;\n --blue-700: #006dc4;\n --blue-800: #0060a7;\n --blue-900: #005086;\n --indigo-25: #f8f7ff;\n --indigo-50: #f1efff;\n --indigo-100: #eae7ff;\n --indigo-200: #ccc3ff;\n --indigo-300: #ac99ff;\n --indigo-400: #916aff;\n --indigo-500: #63c;\n --indigo-600: #5a21b2;\n --indigo-700: #4e0b99;\n --indigo-800: #3b0071;\n --indigo-900: #220040;\n --purple-25: #fbf7ff;\n --purple-50: #f8f0ff;\n --purple-100: #f4e8ff;\n --purple-200: #e4c4ff;\n --purple-300: #d49aff;\n --purple-400: #c36aff;\n --purple-500: #a219e6;\n --purple-600: #9000c4;\n --purple-700: #7c009f;\n --purple-800: #600073;\n --purple-900: #3d0043;\n --magenta-25: #fff8fb;\n --magenta-50: #fff2f6;\n --magenta-100: #ffebf2;\n --magenta-200: #ffcddf;\n --magenta-300: #ffa8cb;\n --magenta-400: #ff7fb7;\n --magenta-500: #eb4799;\n --magenta-600: #da3689;\n --magenta-700: #c82179;\n --magenta-800: #b00065;\n --magenta-900: #8a004c;\n}\n@media (prefers-color-scheme: dark) {\n :host {\n --semantic-blue: var(--blue-700);\n --semantic-red: var(--red-400);\n --semantic-orange: var(--orange-400);\n --semantic-green: var(--green-700);\n --semantic-bg-blue: var(--blue-25);\n --semantic-bg-red: var(--red-25);\n --semantic-bg-orange: var(--orange-25);\n --semantic-bg-green: var(--green-25);\n --neutral-100: #121212;\n --neutral-200: #424242;\n --neutral-300: #616161;\n --neutral-400: #757575;\n --neutral-500: #9e9e9e;\n --neutral-600: #bdbdbd;\n --neutral-700: #e0e0e0;\n --neutral-800: #eeeeee;\n --neutral-900: #f5f5f5;\n }\n}\n:host([theme='dark']) {\n --semantic-blue: var(--blue-700);\n --semantic-red: var(--red-400);\n --semantic-orange: var(--orange-400);\n --semantic-green: var(--green-700);\n --semantic-bg-blue: var(--blue-25);\n --semantic-bg-red: var(--red-25);\n --semantic-bg-orange: var(--orange-25);\n --semantic-bg-green: var(--green-25);\n --neutral-100: #121212;\n --neutral-200: #424242;\n --neutral-300: #616161;\n --neutral-400: #757575;\n --neutral-500: #9e9e9e;\n --neutral-600: #bdbdbd;\n --neutral-700: #e0e0e0;\n --neutral-800: #eeeeee;\n --neutral-900: #f5f5f5;\n}\n/* @media (prefers-color-scheme: dark) {\n :host {\n --label-color: #fff;\n --active-label-color: #000;\n --menu-bg: #525252;\n --active-bg: #5898ff;\n --active-bg-dimmed: #5c5c5c;\n }\n} */\n:host {\n --ui-font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont,\n 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji',\n 'Segoe UI Emoji', 'Segoe UI Symbol';\n --ui-font-size: 14px;\n --ui-line-height: 1.5;\n --ui-letter-spacing: 0.007em;\n --mono-font-family: 'Berkeley Mono', 'JetBrains Mono', 'IBM Plex Mono',\n 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;\n --ui-layer-1: var(--neutral-100);\n --ui-layer-2: var(--neutral-200);\n --ui-layer-3: var(--neutral-300);\n --ui-layer-4: var(--neutral-400);\n --ui-layer-5: var(--neutral-500);\n --ui-layer-6: var(--neutral-600);\n --ui-border-color: var(--primary-color);\n --ui-border-radius: 4px;\n --ui-text: var(--neutral-900);\n --ui-text-secondary: var(--neutral-700);\n --ui-text-placeholder: var(--neutral-500);\n --ui-text-muted: var(--neutral-300);\n /** A field is a UI element in which a user can type data, for\n * example an input or textarea element.\n */\n --ui-field-bg: var(--neutral-100);\n --ui-field-bg-hover: var(--neutral-100);\n --ui-field-bg-disabled: var(--neutral-300);\n --ui-field-bg-invalid: var(--red-100);\n --ui-field-bg-focus: var(--neutral-100);\n --ui-field-border: 0.5px solid var(--border-color);\n --ui-field-border-hover: 0.5px solid var(--border-color);\n --ui-field-border-disabled: 0.5px solid var(--border-color);\n --ui-field-border-invalid: 0.5px solid var(--border-color);\n --ui-field-border-focus: 0.5px solid var(--border-color);\n --ui-menu-bg: var(--neutral-100);\n --ui-menu-text: var(--neutral-900);\n --ui-menu-bg-hover: var(--neutral-200);\n --ui-menu-text-hover: var(--neutral-900);\n /** The `active` state is used for the state of menu items\n * when they are selected.\n */\n --ui-menu-bg-active: var(--primary-color);\n --ui-menu-text-active: var(--primary-color-reverse);\n /** The `active-muted` set is used for the state of\n * submenus when they are open.\n */\n --ui-menu-bg-active-muted: var(--neutral-300);\n --ui-menu-text-active-muted: var(--neutral-900);\n /* --ui-menu-shadow: 0 1px 2px 0 rgba(60, 64, 67, 0.302),\n0 2px 6px 2px rgba(60, 64, 67, 0.149); */\n --ui-menu-shadow: 0 0 2px rgba(0, 0, 0, 0.5), 0 0 20px rgba(0, 0, 0, 0.2);\n --ui-menu-divider: 0.5px solid #c7c7c7;\n /* var(--neutral-300); */\n --ui-menu-z-index: 10000;\n --page-bg: var(--neutral-100);\n --content-bg: var(--neutral-200);\n}\n@media (prefers-color-scheme: dark) {\n :host {\n --ui-menu-bg: var(--neutral-200);\n }\n}\n:host([theme='dark']) {\n --ui-menu-bg: var(--neutral-200);\n}\n/* PingFang SC is a macOS font. Microsoft Yahei is a Windows font. \n Noto is a Linux/Android font.\n*/\n:lang(zh-cn),\n:lang(zh-sg),\n:lang(zh-my),\n:lang(zh) {\n --ui-font-family: -apple-system, system-ui, 'PingFang SC', 'Hiragino Sans GB',\n 'Noto Sans CJK SC', 'Noto Sans SC', 'Noto Sans', 'Microsoft Yahei UI',\n 'Microsoft YaHei New', 'Microsoft Yahei', '\u5FAE\u8F6F\u96C5\u9ED1', SimSun, '\u5B8B\u4F53',\n STXihei, '\u534E\u6587\u7EC6\u9ED1', sans-serif;\n}\n:lang(zh-tw),\n:lang(zh-hk),\n:lang(zh-mo) {\n --ui-font-family: -apple-system, system-ui, 'Noto Sans',\n 'Microsoft JhengHei UI', 'Microsoft JhengHei', '\u5FAE\u8EDF\u6B63\u9ED1\u9AD4', '\u65B0\u7D30\u660E\u9AD4',\n 'PMingLiU', '\u7D30\u660E\u9AD4', 'MingLiU', sans-serif;\n}\n:lang(ja),\n:lang(ja-jp),\n:lang(ja-jp-mac) {\n --ui-font-family: -apple-system, system-ui, 'Hiragino Sans',\n 'Hiragino Kaku Gothic ProN', 'Noto Sans CJK JP', 'Noto Sans JP', 'Noto Sans',\n '\u6E38\u30B4\u30B7\u30C3\u30AF', '\u6E38\u30B4\u30B7\u30C3\u30AF\u4F53', YuGothic, 'Yu Gothic', '\u30E1\u30A4\u30EA\u30AA', Meiryo,\n '\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF', 'MS PGothic', sans-serif;\n}\n:lang(ko),\n:lang(ko-kr),\n:lang(ko-kr-std) {\n --ui-font-family: -apple-system, system-ui, 'Noto Sans CJK KR', 'Noto Sans KR',\n 'Noto Sans', 'Malgun Gothic', '\uB9D1\uC740 \uACE0\uB515', 'Apple SD Gothic Neo',\n '\uC560\uD50C SD \uC0B0\uB3CC\uACE0\uB515 Neo', 'Apple SD \uC0B0\uB3CC\uACE0\uB515 Neo', '\uB3CB\uC6C0', Dotum, sans-serif;\n}\n:lang(ko-kr-apple) {\n --ui-font-family: -apple-system, system-ui, 'Noto Sans CJK KR', 'Noto Sans KR',\n 'Noto Sans', 'Apple SD Gothic Neo', '\uC560\uD50C SD \uC0B0\uB3CC\uACE0\uB515 Neo',\n 'Apple SD \uC0B0\uB3CC\uACE0\uB515 Neo', '\uB3CB\uC6C0', Dotum, sans-serif;\n}\n:lang(zh-cn),\n:lang(zh-sg),\n:lang(zh-my),\n:lang(zh),\n:lang(zh-tw),\n:lang(zh-hk),\n:lang(zh-mo),\n:lang(ja),\n:lang(ja-jp),\n:lang(ja-jp-mac),\n:lang(ko),\n:lang(ko-kr),\n:lang(ko-kr-std),\n:lang(ko-kr-apple) {\n --ui-font-size: 1rem;\n --ui-line-height: 1.7;\n --ui-letter-spacing: 0;\n}\n:dir(rtl) {\n --ui-line-height: auto;\n --ui-letter-spacing: 0;\n}\n"; // src/ui/menu/style.less var style_default2 = ".ui-menu *,\n.ui-menu ::before,\n.ui-menu ::after {\n box-sizing: border-box;\n}\n.ui-menu {\n display: none;\n color-scheme: light dark;\n -webkit-user-select: none;\n /* Important: Safari iOS doesn't respect user-select */\n user-select: none;\n cursor: default;\n -webkit-touch-callout: none;\n -webkit-tap-highlight-color: rgba(0 0 0 0);\n --active-label-color: #fff;\n /* ui-menu-text-active */\n --label-color: #121212;\n /* ui-menu-text */\n --menu-bg: #e2e2e2;\n /* ui-menu-background */\n --active-bg: #5898ff;\n /* ui-menu-background-active */\n --active-bg-dimmed: #c5c5c5;\n /* ui-menu-background-active-muted */\n}\n/** Use the :where pseudo selector to make the specificity of the\n * selector 0, so that it can be overridden by the user.\n */\n:where(.ui-menu-container) {\n position: absolute;\n overflow: visible;\n width: auto;\n height: auto;\n z-index: 10000;\n border-radius: 8px;\n background: var(--ui-menu-bg);\n box-shadow: var(--ui-menu-shadow);\n list-style: none;\n padding: 6px 0 6px 0;\n margin: 0;\n user-select: none;\n cursor: default;\n color: var(--ui-menu-text);\n font-weight: normal;\n font-style: normal;\n text-shadow: none;\n text-transform: none;\n letter-spacing: 0;\n outline: none;\n opacity: 1;\n /* The [popover] elements have a 1px solid black border. Ugh. */\n border: none;\n width: fit-content;\n height: fit-content;\n}\n:where(.ui-menu-container > li) {\n display: flex;\n flex-flow: row;\n align-items: center;\n padding: 1px 7px 1px 7px;\n margin-top: 0;\n margin-left: 6px;\n margin-right: 6px;\n border-radius: 4px;\n white-space: nowrap;\n position: relative;\n outline: none;\n fill: currentColor;\n user-select: none;\n cursor: default;\n text-align: left;\n color: inherit;\n font-family: var(--ui-font-family);\n font-size: var(--ui-font-size);\n line-height: var(--ui-line-height);\n letter-spacing: var(--ui-letter-spacing);\n}\n:where(.ui-menu-container > li > .label) {\n appearance: none;\n background: none;\n outline: none;\n width: 100%;\n margin: 0;\n padding: 1px 2px 1px 1px;\n overflow: visible;\n border: 1px solid transparent;\n white-space: nowrap;\n text-align: start;\n}\n:where(.ui-menu-container > li:has(.heading)) {\n margin-top: 0.5em;\n}\n:where(.ui-menu-container > li > .label.heading) {\n font-weight: bold;\n opacity: 0.4;\n}\n:where(.ui-menu-container > li.indent > .label) {\n margin-inline-start: 12px;\n}\n:where(.ui-menu-container > li > .label.indent) {\n margin-inline-start: 12px;\n}\n:where(.ui-menu-container > li[role='divider']) {\n border-bottom: 1px solid var(--ui-menu-divider);\n border-radius: 0;\n padding: 0;\n margin-left: 15px;\n margin-right: 15px;\n padding-top: 5px;\n margin-bottom: 5px;\n width: calc(100% - 30px);\n /** 100% - (margin-left + margin-right) */\n}\n:where(.ui-menu-container > li[aria-disabled='true']) {\n opacity: 0.5;\n}\n:where(.ui-menu-container > li.active) {\n background: var(--ui-menu-bg-active);\n background: -apple-system-control-accent;\n color: var(--ui-menu-text-active);\n}\n:where(.ui-menu-container > li.active.is-submenu-open) {\n background: var(--ui-menu-bg-active-muted);\n color: inherit;\n}\n:where(.ui-menu-container > li[aria-haspopup='true'] > .label) {\n padding-inline-end: 0;\n}\n:where(.ui-menu-container > li[aria-haspopup='true'].active::after) {\n color: var(--ui-menu-text-active);\n}\n/** Keyboard shortcut */\n:where(.ui-menu-container > li > kbd) {\n font-family: var(--ui-font-family);\n margin-inline-start: 12px;\n opacity: 0.4;\n}\n:where(.ui-menu-container > li.active > kbd) {\n opacity: 0.85;\n}\n.ui-trailing-chevron {\n display: flex;\n margin-inline-start: 24px;\n width: 10px;\n height: 10px;\n margin-bottom: 4px;\n}\n.ui-trailing-chevron:dir(rtl) {\n transform: scaleX(-1);\n}\n.ui-checkmark {\n display: flex;\n margin-inline-end: -11px;\n margin-inline-start: -4px;\n margin-top: 2px;\n width: 16px;\n height: 16px;\n}\n.ui-mixedmark {\n display: flex;\n margin-inline-end: -11px;\n margin-inline-start: -4px;\n margin-top: 2px;\n width: 16px;\n height: 16px;\n}\n"; // src/common/stylesheet.ts var gStylesheets; function getStylesheetContent(id) { let content = ""; switch (id) { case "mathfield-element": content = ` :host { display: inline-block; background-color: field; color: fieldtext; border-width: 1px; border-style: solid; border-color: #acacac; border-radius: 2px; padding:4px;} :host([hidden]) { display: none; } :host([disabled]), :host([disabled]:focus), :host([disabled]:focus-within) { outline: none; opacity: .5; } :host(:focus), :host(:focus-within) { outline: Highlight auto 1px; /* For Firefox */ outline: -webkit-focus-ring-color auto 1px; } :host([readonly]:focus), :host([readonly]:focus-within), :host([read-only]:focus), :host([read-only]:focus-within) { outline: none; } @media (hover: none) and (pointer: coarse) { :host(:not(:focus)) :first-child { pointer-events: none !important; } }`; break; case "core": content = core_default; break; case "mathfield": content = mathfield_default; break; case "environment-popover": content = environment_popover_default; break; case "suggestion-popover": content = suggestion_popover_default; break; case "keystroke-caption": content = keystroke_caption_default; break; case "virtual-keyboard": content = virtual_keyboard_default; break; case "ui": content = style_default; break; case "menu": content = style_default2; break; default: debugger; } return content; } function getStylesheet(id) { if (!gStylesheets) gStylesheets = {}; if (gStylesheets[id]) return gStylesheets[id]; gStylesheets[id] = new CSSStyleSheet(); gStylesheets[id].replaceSync(getStylesheetContent(id)); return gStylesheets[id]; } var gInjectedStylesheets; function injectStylesheet(id) { var _a3; if (!("adoptedStyleSheets" in document)) { if (window.document.getElementById(`mathlive-style-${id}`)) return; const styleNode = window.document.createElement("style"); styleNode.id = `mathlive-style-${id}`; styleNode.append(window.document.createTextNode(getStylesheetContent(id))); window.document.head.appendChild(styleNode); return; } if (!gInjectedStylesheets) gInjectedStylesheets = {}; if (((_a3 = gInjectedStylesheets[id]) != null ? _a3 : 0) !== 0) gInjectedStylesheets[id] += 1; else { const stylesheet = getStylesheet(id); document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet]; gInjectedStylesheets[id] = 1; } } function releaseStylesheet(id) { if (!("adoptedStyleSheets" in document)) return; if (!(gInjectedStylesheets == null ? void 0 : gInjectedStylesheets[id])) return; gInjectedStylesheets[id] -= 1; if (gInjectedStylesheets[id] <= 0) { const stylesheet = gStylesheets[id]; document.adoptedStyleSheets = document.adoptedStyleSheets.filter( (x) => x !== stylesheet ); } } // src/atoms/accent.ts var AccentAtom = class _AccentAtom extends Atom { constructor(options) { var _a3; super(__spreadProps(__spreadValues({}, options), { type: "accent", body: (_a3 = options.body) != null ? _a3 : void 0 })); if (options.accentChar) this.accent = options.accentChar; else this.svgAccent = options == null ? void 0 : options.svgAccent; this.skipBoundary = true; this.captureSelection = true; } static fromJson(json) { return new _AccentAtom(json); } toJson() { return __spreadProps(__spreadValues({}, super.toJson()), { accentChar: this.accent, svgAccent: this.svgAccent }); } render(parentContext) { var _a3; const context = new Context( { parent: parentContext, mathstyle: "cramp" }, this.style ); const base = (_a3 = Atom.createBox(context, this.body)) != null ? _a3 : new Box("\u25A2", { style: this.style }); let skew = 0; if (!this.hasEmptyBranch("body") && this.body.length === 2 && this.body[1].isCharacterBox()) skew = base.skew; let clearance = Math.min(base.height, X_HEIGHT); let accentBox; if (this.svgAccent) { accentBox = makeSVGBox(this.svgAccent); clearance = context.metrics.bigOpSpacing1 - clearance; } else if (this.accent) { const accent = new Box(this.accent, { fontFamily: "Main-Regular" }); accent.italic = 0; const vecClass = this.accent === 8407 ? " ML__accent-vec" : ""; accentBox = new Box(new Box(accent), { classes: "ML__accent-body" + vecClass }); } accentBox = new VBox({ shift: 0, children: [ { box: new Box(base) }, -clearance, { box: accentBox, marginLeft: base.left + 2 * skew, classes: ["ML__center"] } ] }); const result = new Box(accentBox, { type: "lift" }); if (this.caret) result.caret = this.caret; this.bind(context, result.wrap(context)); return this.attachSupsub(context, { base: result }); } }; // src/core/delimiters.ts var RIGHT_DELIM = { "(": ")", "{": "}", "[": "]", "|": "|", "\\lbrace": "\\rbrace", "\\lparen": "\\rparen", "\\{": "\\}", "\\langle": "\\rangle", "\\lfloor": "\\rfloor", "\\lceil": "\\rceil", "\\vert": "\\vert", "\\lvert": "\\rvert", "\\Vert": "\\Vert", "\\lVert": "\\rVert", "\\lbrack": "\\rbrack", "\\ulcorner": "\\urcorner", "\\llcorner": "\\lrcorner", "\\lgroup": "\\rgroup", "\\lmoustache": "\\rmoustache" }; var LEFT_DELIM = Object.fromEntries( Object.entries(RIGHT_DELIM).map(([leftDelim, rightDelim]) => [ rightDelim, leftDelim ]) ); function getSymbolValue(symbol) { var _a3; return (_a3 = { "[": 91, // '[', "]": 93, // ']', "(": 40, // '(', ")": 41, // ')', "\\mid": 8739, "|": 8739, "\u2223": 8739, // DIVIDES "\u2225": 8741, // PARALLEL TO "\\|": 8739, "\\{": 123, // '{', "\\}": 125, // '}', "\\lbrace": 123, // '{', "\\rbrace": 125, // '}', "\\lparen": 40, // '(' "\\rparen": 41, // ')' "\\lbrack": 91, // '[', "\\rbrack": 93, // ']', "\\vert": 8739, "\\lvert": 8739, "\\mvert": 8739, "\\rvert": 8739, "\\Vert": 8741, "\\lVert": 8741, "\\mVert": 8741, "\\rVert": 8741, "\\parallel": 8741, "\\shortparallel": 8741, "\\langle": 10216, "\\rangle": 10217, "\\lfloor": 8970, "\\rfloor": 8971, "\\lceil": 8968, "\\rceil": 8969, "\\ulcorner": 9484, "\\urcorner": 9488, "\\llcorner": 9492, "\\lrcorner": 9496, "\\lgroup": 10222, "\\rgroup": 10223, "\\lmoustache": 9136, "\\rmoustache": 9137, "\\surd": 8730 }[symbol]) != null ? _a3 : symbol.codePointAt(0); } function makeSmallDelim(delim, context, center, options) { var _a3; const text = new Box(getSymbolValue(delim), { fontFamily: "Main-Regular", isSelected: options.isSelected, classes: "ML__small-delim " + ((_a3 = options.classes) != null ? _a3 : "") }); const box = text.wrap(context); if (center) box.setTop((1 - context.scalingFactor) * AXIS_HEIGHT); return box; } function makeLargeDelim(delim, size, center, parentContext, options) { var _a3, _b3; const context = new Context( { parent: parentContext, mathstyle: "textstyle" }, options == null ? void 0 : options.style ); const result = new Box(getSymbolValue(delim), { fontFamily: `Size${size}-Regular`, isSelected: options.isSelected, classes: ((_a3 = options.classes) != null ? _a3 : "") + ` ML__delim-size${size}`, type: (_b3 = options.type) != null ? _b3 : "ignore" }).wrap(context); if (center) result.setTop((1 - context.scalingFactor) * AXIS_HEIGHT); return result; } function makeStackedDelim(delim, heightTotal, center, context, options) { var _a3; let top; let middle; let repeat; let bottom; top = repeat = bottom = getSymbolValue(delim); middle = null; let fontFamily = "Size1-Regular"; if (delim === "\\vert" || delim === "\\lvert" || delim === "\\rvert" || delim === "\\mvert" || delim === "\\mid") repeat = top = bottom = 8739; else if (delim === "\\Vert" || delim === "\\lVert" || delim === "\\rVert" || delim === "\\mVert" || delim === "\\|") repeat = top = bottom = 8741; else if (delim === "\\uparrow") repeat = bottom = 9168; else if (delim === "\\Uparrow") repeat = bottom = 8214; else if (delim === "\\downarrow") top = repeat = 9168; else if (delim === "\\Downarrow") top = repeat = 8214; else if (delim === "\\updownarrow") { top = 8593; repeat = 9168; bottom = 8595; } else if (delim === "\\Updownarrow") { top = 8657; repeat = 8214; bottom = 8659; } else if (delim === "[" || delim === "\\lbrack") { top = 9121; repeat = 9122; bottom = 9123; fontFamily = "Size4-Regular"; } else if (delim === "]" || delim === "\\rbrack") { top = 9124; repeat = 9125; bottom = 9126; fontFamily = "Size4-Regular"; } else if (delim === "\\lfloor" || delim === "\u230A") { repeat = top = 9122; bottom = 9123; fontFamily = "Size4-Regular"; } else if (delim === "\\lceil" || delim === "\u2308") { top = 9121; repeat = bottom = 9122; fontFamily = "Size4-Regular"; } else if (delim === "\\rfloor" || delim === "\u230B") { repeat = top = 9125; bottom = 9126; fontFamily = "Size4-Regular"; } else if (delim === "\\rceil" || delim === "\u2309") { top = 9124; repeat = bottom = 9125; fontFamily = "Size4-Regular"; } else if (delim === "(" || delim === "\\lparen") { top = 9115; repeat = 9116; bottom = 9117; fontFamily = "Size4-Regular"; } else if (delim === ")" || delim === "\\rparen") { top = 9118; repeat = 9119; bottom = 9120; fontFamily = "Size4-Regular"; } else if (delim === "\\{" || delim === "\\lbrace") { top = 9127; middle = 9128; bottom = 9129; repeat = 9130; fontFamily = "Size4-Regular"; } else if (delim === "\\}" || delim === "\\rbrace") { top = 9131; middle = 9132; bottom = 9133; repeat = 9130; fontFamily = "Size4-Regular"; } else if (delim === "\\lgroup" || delim === "\u27EE") { top = 9127; bottom = 9129; repeat = 9130; fontFamily = "Size4-Regular"; } else if (delim === "\\rgroup" || delim === "\u27EF") { top = 9131; bottom = 9133; repeat = 9130; fontFamily = "Size4-Regular"; } else if (delim === "\\lmoustache" || delim === "\u23B0") { top = 9127; bottom = 9133; repeat = 9130; fontFamily = "Size4-Regular"; } else if (delim === "\\rmoustache" || delim === "\u23B1") { top = 9131; bottom = 9129; repeat = 9130; fontFamily = "Size4-Regular"; } else if (delim === "\\surd") { top = 57345; bottom = 9143; repeat = 57344; fontFamily = "Size4-Regular"; } else if (delim === "\\ulcorner") { top = 9484; repeat = bottom = 32; } else if (delim === "\\urcorner") { top = 9488; repeat = bottom = 32; } else if (delim === "\\llcorner") { bottom = 9492; repeat = top = 32; } else if (delim === "\\lrcorner") { top = 9496; repeat = top = 32; } const topMetrics = getCharacterMetrics(top, fontFamily); const topHeightTotal = topMetrics.height + topMetrics.depth; const repeatMetrics = getCharacterMetrics(repeat, fontFamily); const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth; const bottomMetrics = getCharacterMetrics(bottom, fontFamily); const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth; let middleHeightTotal = 0; let middleFactor = 1; if (middle !== null) { const middleMetrics = getCharacterMetrics(middle, fontFamily); middleHeightTotal = middleMetrics.height + middleMetrics.depth; middleFactor = 2; } const minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; const repeatCount = Math.max( 0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal)) ); const realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; let axisHeight = AXIS_HEIGHT; if (center) axisHeight = axisHeight * context.scalingFactor; const depth = realHeightTotal / 2 - axisHeight; const OVERLAP = 8e-3; const stack = []; stack.push({ box: new Box(bottom, { fontFamily }) }); stack.push(-OVERLAP); const repeatBox = new Box(repeat, { fontFamily }); if (middle === null) { for (let i = 0; i < repeatCount; i++) stack.push({ box: repeatBox }); } else { for (let i = 0; i < repeatCount; i++) stack.push({ box: repeatBox }); stack.push(-OVERLAP); stack.push({ box: new Box(middle, { fontFamily }) }); stack.push(-OVERLAP); for (let i = 0; i < repeatCount; i++) stack.push({ box: repeatBox }); } stack.push(-OVERLAP); stack.push({ box: new Box(top, { fontFamily }) }); let sizeClass = ""; if (fontFamily === "Size1-Regular") sizeClass = " delim-size1"; else if (fontFamily === "Size4-Regular") sizeClass = " delim-size4"; const inner = new VBox( { bottom: depth, children: stack }, { classes: sizeClass } ); const result = new Box(inner, __spreadProps(__spreadValues({}, options != null ? options : {}), { classes: ((_a3 = options == null ? void 0 : options.classes) != null ? _a3 : "") + " ML__delim-mult" })); return result; } var stackLargeDelimiters = /* @__PURE__ */ new Set([ "(", ")", "\\lparen", "\\rparen", "[", "]", "\\lbrack", "\\rbrack", "\\{", "\\}", "\\lbrace", "\\rbrace", "\\lfloor", "\\rfloor", "\\lceil", "\\rceil", "\\surd", "\u230A", "\u230B", "\u2308", "\u2309" ]); var stackAlwaysDelimiters = /* @__PURE__ */ new Set([ "\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\mvert", "\\mid", "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache", "\u27EE", "\u27EF", "\u23B0", "\u23B1" ]); var stackNeverDelimiters = /* @__PURE__ */ new Set([ "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt" ]); var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3]; function makeSizedDelim(delim, size, context, options) { if (delim === void 0 || delim === ".") return makeNullDelimiter(context, options.classes); if (delim === "<" || delim === "\\lt" || delim === "\u27E8") delim = "\\langle"; else if (delim === ">" || delim === "\\gt" || delim === "\u27E9") delim = "\\rangle"; if (stackLargeDelimiters.has(delim) || stackNeverDelimiters.has(delim)) return makeLargeDelim(delim, size, false, context, options); if (stackAlwaysDelimiters.has(delim)) { return makeStackedDelim( delim, sizeToMaxHeight[size], false, context, options ); } console.assert(false, "Unknown delimiter '" + delim + "'"); return null; } var stackNeverDelimiterSequence = [ { type: "small", mathstyle: "scriptscriptstyle" }, { type: "small", mathstyle: "scriptstyle" }, { type: "small", mathstyle: "textstyle" }, { type: "large", size: 1 }, { type: "large", size: 2 }, { type: "large", size: 3 }, { type: "large", size: 4 } ]; var stackAlwaysDelimiterSequence = [ { type: "small", mathstyle: "scriptscriptstyle" }, { type: "small", mathstyle: "scriptscriptstyle" }, { type: "small", mathstyle: "textstyle" }, { type: "stack" } ]; var stackLargeDelimiterSequence = [ { type: "small", mathstyle: "scriptscriptstyle" }, { type: "small", mathstyle: "scriptstyle" }, { type: "small", mathstyle: "textstyle" }, { type: "large", size: 1 }, { type: "large", size: 2 }, { type: "large", size: 3 }, { type: "large", size: 4 }, { type: "stack" } ]; function delimTypeToFont(info) { if (info.type === "small") return "Main-Regular"; if (info.type === "large") return "Size" + info.size + "-Regular"; console.assert(info.type === "stack"); return "Size4-Regular"; } function traverseSequence(delim, height, sequence, context) { const start = { "-4": 0, "-3": 1, "0": 2 }[context.mathstyle.sizeDelta]; for (let i = start; i < sequence.length; i++) { if (sequence[i].type === "stack") { break; } const metrics = getCharacterMetrics(delim, delimTypeToFont(sequence[i])); if (metrics.defaultMetrics) { return { type: "small", mathstyle: "scriptstyle" }; } let heightDepth = metrics.height + metrics.depth; if (sequence[i].type === "small") { if (sequence[i].mathstyle === "scriptscriptstyle") { heightDepth *= Math.max( FONT_SCALE[Math.max(1, context.size - 2)], context.minFontScale ); } else if (sequence[i].mathstyle === "scriptstyle") { heightDepth *= Math.max( FONT_SCALE[Math.max(1, context.size - 1)], context.minFontScale ); } } if (heightDepth > height) return sequence[i]; } return sequence[sequence.length - 1]; } function makeCustomSizedDelim(type, delim, height, center, context, options) { if (!delim || delim.length === 0 || delim === ".") return makeNullDelimiter(context); if (delim === "<" || delim === "\\lt") delim = "\\langle"; else if (delim === ">" || delim === "\\gt") delim = "\\rangle"; let sequence; if (stackNeverDelimiters.has(delim)) sequence = stackNeverDelimiterSequence; else if (stackLargeDelimiters.has(delim)) sequence = stackLargeDelimiterSequence; else sequence = stackAlwaysDelimiterSequence; const delimType = traverseSequence( getSymbolValue(delim), height, sequence, context ); const ctx = new Context( { parent: context, mathstyle: delimType.mathstyle }, options == null ? void 0 : options.style ); if (delimType.type === "small") return makeSmallDelim(delim, ctx, center, __spreadProps(__spreadValues({}, options), { type })); if (delimType.type === "large") { return makeLargeDelim(delim, delimType.size, center, ctx, __spreadProps(__spreadValues({}, options), { type })); } console.assert(delimType.type === "stack"); return makeStackedDelim(delim, height, center, ctx, __spreadProps(__spreadValues({}, options), { type })); } function makeLeftRightDelim(type, delim, height, depth, context, options) { if (delim === ".") return makeNullDelimiter(context, options == null ? void 0 : options.classes); const axisHeight = AXIS_HEIGHT * context.scalingFactor; const delimiterFactor = 901; const delimiterExtend = 5 / PT_PER_EM; const maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight); const totalHeight = Math.max( maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend ); return makeCustomSizedDelim(type, delim, totalHeight, true, context, options); } function makeNullDelimiter(parent, classes) { const box = new Box(null, { classes: " nulldelimiter " + (classes != null ? classes : ""), type: "ignore" }); box.width = parent.getRegisterAsEm("nulldelimiterspace"); return box.wrap(new Context({ parent, mathstyle: "textstyle" })); } // src/atoms/placeholder.ts var PlaceholderAtom = class _PlaceholderAtom extends Atom { constructor(options) { var _a3; super({ type: "placeholder", command: "\\placeholder", mode: (_a3 = options == null ? void 0 : options.mode) != null ? _a3 : "math", style: options == null ? void 0 : options.style }); this.captureSelection = true; } static fromJson(json) { return new _PlaceholderAtom(json); } toJson() { return super.toJson(); } render(context) { let result; this.value = context.placeholderSymbol; if (typeof context.renderPlaceholder === "function") result = context.renderPlaceholder(context); else result = this.createBox(context); if (this.caret) result.classes += " ML__placeholder-selected"; return result; } _serialize(options) { if (options.skipPlaceholders) return ""; return "\\placeholder{}"; } }; // src/latex-commands/environment-types.ts var matrices = [ "matrix", "matrix*", "pmatrix", "pmatrix*", "bmatrix", "bmatrix*", "Bmatrix", "Bmatrix*", "vmatrix", "vmatrix*", "Vmatrix", "Vmatrix*" ]; var cases = ["cases", "dcases", "rcases"]; var align = ["align", "align*", "aligned", "gather", "gathered", "split"]; var otherTabular = ["array", "subequations", "eqnarray"]; function isTabularEnvironment(environment) { return otherTabular.concat(align).concat(cases).concat(matrices).includes(environment); } function isMatrixEnvironment(environment) { return matrices.includes(environment); } function isCasesEnvironment(environment) { return cases.includes(environment); } function isAlignEnvironment(environment) { return align.includes(environment); } // src/atoms/array.ts function normalizeArray(atom, array, colFormat) { let maxColCount = 0; for (const colSpec of colFormat) if ("align" in colSpec) maxColCount += 1; let colCount = 0; const rows = []; for (const row of array) { let colIndex2 = 0; colCount = Math.max(colCount, Math.min(row.length, maxColCount)); while (colIndex2 < row.length) { const newRow = []; const lastCol = Math.min(row.length, colIndex2 + maxColCount); while (colIndex2 < lastCol) { const cell = row[colIndex2]; if (cell.length === 0) newRow.push([new Atom({ type: "first", mode: atom.mode })]); else if (cell[0].type !== "first") newRow.push([new Atom({ type: "first", mode: atom.mode }), ...cell]); else { console.assert(!cell.slice(1).some((x) => x.type === "first")); newRow.push(cell); } colIndex2 += 1; } rows.push(newRow); } } if (rows.length > 0 && rows[rows.length - 1].length === 1 && rows[rows.length - 1][0].length === 1 && rows[rows.length - 1][0][0].type === "first") rows.pop(); const result = []; for (const row of rows) { if (row.length !== colCount) { for (let i = row.length; i < colCount; i++) { row.push([ new Atom({ type: "first", mode: atom.mode }), new PlaceholderAtom() ]); } } result.push(row); } let rowIndex = 0; let colIndex = 0; for (const row of result) { colIndex = 0; for (const cell of row) { for (const element of cell) { element.parent = atom; element.parentBranch = [rowIndex, colIndex]; } colIndex += 1; } rowIndex += 1; } atom.isDirty = true; return result; } var ArrayAtom = class _ArrayAtom extends Atom { constructor(envName, array, rowGaps, options = {}) { var _a3; super({ type: "array" }); this.environmentName = envName; this.rowGaps = rowGaps; if (options.mathstyleName) this.mathstyleName = options.mathstyleName; if (options.columns) { if (options.columns.length === 0) this.colFormat = [{ align: "l" }]; else this.colFormat = options.columns; } if (!this.colFormat) { this.colFormat = [ { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" }, { align: "l" } ]; } this.array = normalizeArray(this, array, this.colFormat); if (options.leftDelim) this.leftDelim = options.leftDelim; if (options.rightDelim) this.rightDelim = options.rightDelim; if (options.arraycolsep !== void 0) this.arraycolsep = options.arraycolsep; this.colSeparationType = options.colSeparationType; if (options.arraystretch !== void 0) this.arraystretch = options.arraystretch; this.minColumns = (_a3 = options.minColumns) != null ? _a3 : 1; } static fromJson(json) { return new _ArrayAtom( json.environmentName, json.array, json.rowGaps, json ); } toJson() { const result = __spreadProps(__spreadValues({}, super.toJson()), { environmentName: this.environmentName, array: this.array.map( (row) => row.map((col) => col.map((x) => x.toJson())) ), rowGaps: this.rowGaps, columns: this.colFormat, colSeparationType: this.colSeparationType }); if (this.arraystretch !== void 0) result.arraystretch = this.arraystretch; if (this.arraycolsep !== void 0) result.arraycolsep = this.arraycolsep; if (this.leftDelim) result.leftDelim = this.leftDelim; if (this.rightDelim) result.rightDelim = this.rightDelim; return result; } branch(cell) { var _a3; if (!isCellBranch(cell)) return void 0; return (_a3 = this.array[cell[0]][cell[1]]) != null ? _a3 : void 0; } createBranch(cell) { var _a3; if (!isCellBranch(cell)) return []; this.isDirty = true; return (_a3 = this.branch(cell)) != null ? _a3 : []; } get rowCount() { return this.array.length; } get colCount() { return this.array[0].length; } get maxColumns() { return this.colFormat.filter((col) => Boolean(col["align"])).length; } removeBranch(name) { if (isNamedBranch(name)) return super.removeBranch(name); const children = this.branch(name); this.array[name[0]][name[1]] = void 0; children.forEach((x) => { x.parent = void 0; x.parentBranch = void 0; }); console.assert(children[0].type === "first"); children.shift(); this.isDirty = true; return children; } get hasChildren() { return this.children.length > 0; } get children() { const result = []; for (const row of this.array) { for (const cell of row) { if (cell) { for (const atom of cell) { result.push(...atom.children); result.push(atom); } } } } return [...result, ...super.children]; } render(context) { var _a3, _b3, _c2, _d2, _e, _f; const innerContext = new Context( { parent: context, mathstyle: this.mathstyleName }, this.style ); const arrayRuleWidth = innerContext.getRegisterAsEm("arrayrulewidth"); const arrayColSep = innerContext.getRegisterAsEm("arraycolsep"); const doubleRuleSep = innerContext.getRegisterAsEm("doublerulesep"); const arraystretch = (_b3 = (_a3 = this.arraystretch) != null ? _a3 : innerContext.getRegisterAsNumber("arraystretch")) != null ? _b3 : 1; let arraycolsep = typeof this.arraycolsep === "number" ? this.arraycolsep : arrayColSep; if (this.colSeparationType === "small") { const localMultiplier = new Context({ parent: context, mathstyle: "scriptstyle" }).scalingFactor; arraycolsep = 0.2778 * (localMultiplier / context.scalingFactor); } const arrayskip = arraystretch * BASELINE_SKIP; const arstrutHeight = 0.7 * arrayskip; const arstrutDepth = 0.3 * arrayskip; let totalHeight = 0; const body = []; let nc = 0; const nr = this.array.length; for (let r = 0; r < nr; ++r) { const inrow = this.array[r]; nc = Math.max(nc, inrow.length); const cellContext = new Context( { parent: innerContext, mathstyle: this.mathstyleName }, this.style ); let height = arstrutHeight / cellContext.scalingFactor; let depth = arstrutDepth / cellContext.scalingFactor; const outrow = { cells: [], height: 0, depth: 0, pos: 0 }; for (const element of inrow) { const elt = (_c2 = Atom.createBox(cellContext, element, { type: "ignore" })) != null ? _c2 : new Box(null, { type: "ignore" }); depth = Math.max(depth, elt.depth); height = Math.max(height, elt.height); outrow.cells.push(elt); } let gap = (_d2 = convertDimensionToEm(this.rowGaps[r])) != null ? _d2 : 0; if (gap > 0) { gap += arstrutDepth; depth = Math.max(depth, gap); gap = 0; } if (r < nr - 1 && !isMatrixEnvironment(this.environmentName) && this.environmentName !== "cases" && this.environmentName !== "array") depth += innerContext.getRegisterAsEm("jot"); outrow.height = height; outrow.depth = depth; totalHeight += height; outrow.pos = totalHeight; totalHeight += depth + gap; body.push(outrow); } const offset = totalHeight / 2 + AXIS_HEIGHT; const contentCols = []; for (let colIndex = 0; colIndex < nc; colIndex++) { const stack = []; for (const row of body) { const element = row.cells[colIndex]; element.depth = row.depth; element.height = row.height; stack.push({ box: element, shift: row.pos - offset }); } if (stack.length > 0) contentCols.push(new VBox({ individualShift: stack })); } const cols = []; let previousColContent = false; let previousColRule = false; let currentContentCol = 0; let firstColumn = !this.leftDelim; const { colFormat } = this; for (const colDesc of colFormat) { if ("align" in colDesc && currentContentCol >= contentCols.length) { break; } if ("align" in colDesc) { if (previousColContent) { cols.push(makeColGap(2 * arraycolsep)); } else if (previousColRule || firstColumn) { cols.push(makeColGap(arraycolsep)); } cols.push( new Box(contentCols[currentContentCol], { classes: "col-align-" + colDesc.align }) ); currentContentCol++; previousColContent = true; previousColRule = false; firstColumn = false; } else if ("gap" in colDesc) { if (typeof colDesc.gap === "number") { cols.push(makeColGap(colDesc.gap)); } else { const col = makeColOfRepeatingElements( context, body, offset, colDesc.gap ); if (col) cols.push(col); } previousColContent = false; previousColRule = false; firstColumn = false; } else if ("separator" in colDesc) { const separator = new Box(null, { classes: "vertical-separator" }); separator.height = totalHeight; separator.setStyle("height", totalHeight, "em"); separator.setStyle( "border-right", `${arrayRuleWidth}em ${colDesc.separator} currentColor` ); separator.setStyle("vertical-align", -(totalHeight - offset), "em"); let gap = 0; if (previousColRule) gap = doubleRuleSep - arrayRuleWidth; else if (previousColContent) gap = arraycolsep - arrayRuleWidth; separator.left = gap; cols.push(separator); previousColContent = false; previousColRule = true; firstColumn = false; } } if (previousColContent && !this.rightDelim) { cols.push(makeColGap(arraycolsep)); } const inner = new Box(cols, { classes: "mtable" }); if ((!this.leftDelim || this.leftDelim === ".") && (!this.rightDelim || this.rightDelim === ".")) { if (this.caret) inner.caret = this.caret; return this.bind(context, inner); } const innerHeight = inner.height; const innerDepth = inner.depth; const base = this.bind( context, new Box( [ this.bind( context, makeLeftRightDelim( "open", (_e = this.leftDelim) != null ? _e : ".", innerHeight, innerDepth, innerContext, { isSelected: this.isSelected } ) ), inner, this.bind( context, makeLeftRightDelim( "close", (_f = this.rightDelim) != null ? _f : ".", innerHeight, innerDepth, innerContext, { isSelected: this.isSelected } ) ) ], { type: "ord" } ) ); if (!base) return null; base.setStyle("display", "inline-block"); if (this.caret) base.caret = this.caret; return this.bind(context, this.attachSupsub(context, { base })); } _serialize(options) { var _a3; const result = []; if (this.environmentName === "lines") result.push(`{\\displaylines`); else result.push(`\\begin{${this.environmentName}}`); if (this.environmentName === "array") { result.push("{"); if (this.colFormat !== void 0) { for (const format of this.colFormat) { if ("align" in format && typeof format.align === "string") result.push(format.align); else if ("separator" in format && format.separator === "solid") result.push("|"); else if ("separator" in format && format.separator === "dashed") result.push(":"); } } result.push("}"); } for (let row = 0; row < this.array.length; row++) { for (let col = 0; col < this.array[row].length; col++) { if (col > 0) result.push(" & "); result.push(Atom.serialize(this.array[row][col], options)); } if (row < this.array.length - 1) { const gap = this.rowGaps[row]; if (gap == null ? void 0 : gap.dimension) result.push(`\\\\[${gap.dimension} ${(_a3 = gap.unit) != null ? _a3 : "pt"}] `); else result.push("\\\\ "); } } if (this.environmentName === "lines") result.push(`}`); else result.push(`\\end{${this.environmentName}}`); return joinLatex(result); } getCell(row, col) { return this.array[row][col]; } setCell(row, column, value) { console.assert( this.type === "array" && Array.isArray(this.array) && this.array[row][column] !== void 0 ); for (const atom of this.array[row][column]) { atom.parent = void 0; atom.parentBranch = void 0; } let atoms = value; if (value.length === 0 || value[0].type !== "first") atoms = [new Atom({ type: "first", mode: this.mode }), ...value]; this.array[row][column] = atoms; for (const atom of atoms) { atom.parent = this; atom.parentBranch = [row, column]; } this.isDirty = true; } addRowBefore(row) { console.assert(this.type === "array" && Array.isArray(this.array)); const newRow = []; for (let i = 0; i < this.colCount; i++) newRow.push(makePlaceholderCell(this)); this.array.splice(row, 0, newRow); for (let i = row; i < this.rowCount; i++) { for (let j = 0; j < this.colCount; j++) { const atoms = this.array[i][j]; if (atoms) for (const atom of atoms) atom.parentBranch = [i, j]; } } this.isDirty = true; } addRowAfter(row) { console.assert(this.type === "array" && Array.isArray(this.array)); const newRow = []; for (let i = 0; i < this.colCount; i++) newRow.push(makePlaceholderCell(this)); this.array.splice(row + 1, 0, newRow); for (let i = row + 1; i < this.rowCount; i++) { for (let j = 0; j < this.colCount; j++) { const atoms = this.array[i][j]; if (atoms) for (const atom of atoms) atom.parentBranch = [i, j]; } } this.isDirty = true; } removeRow(row) { console.assert( this.type === "array" && Array.isArray(this.array) && this.rowCount > row ); const deleted = this.array.splice(row, 1); for (const column of deleted) { for (const cell of column) { if (cell) { for (const child of cell) { child.parent = void 0; child.parentBranch = void 0; } } } } for (let i = row; i < this.rowCount; i++) { for (let j = 0; j < this.colCount; j++) { const atoms = this.array[i][j]; if (atoms) for (const atom of atoms) atom.parentBranch = [i, j]; } } this.isDirty = true; } addColumnBefore(col) { console.assert(this.type === "array" && Array.isArray(this.array)); for (const row of this.array) row.splice(col, 0, makePlaceholderCell(this)); for (let i = 0; i < this.rowCount; i++) { for (let j = col; j < this.colCount; j++) { const atoms = this.array[i][j]; if (atoms) for (const atom of atoms) atom.parentBranch = [i, j]; } } this.isDirty = true; } addColumnAfter(col) { console.assert(this.type === "array" && Array.isArray(this.array)); for (const row of this.array) row.splice(col + 1, 0, makePlaceholderCell(this)); for (let i = 0; i < this.rowCount; i++) { for (let j = col + 1; j < this.colCount; j++) { const atoms = this.array[i][j]; if (atoms) for (const atom of atoms) atom.parentBranch = [i, j]; } } this.isDirty = true; } addColumn() { this.addColumnAfter(this.colCount - 1); } removeColumn(col) { console.assert( this.type === "array" && Array.isArray(this.array) && this.colCount > col ); for (const row of this.array) { const deleted = row.splice(col, 1); for (const cell of deleted) { if (cell) { for (const child of cell) { child.parent = void 0; child.parentBranch = void 0; } } } } for (let i = 0; i < this.rowCount; i++) { for (let j = col; j < this.colCount; j++) { const atoms = this.array[i][j]; if (atoms) for (const atom of atoms) atom.parentBranch = [i, j]; } } this.isDirty = true; } get cells() { const result = []; for (const row of this.array) { for (const cell of row) if (cell) result.push(cell.filter((x) => x.type !== "first")); } return result; } }; function makePlaceholderCell(parent) { const first = new Atom({ type: "first", mode: parent.mode }); first.parent = parent; const placeholder = new PlaceholderAtom(); placeholder.parent = parent; return [first, placeholder]; } function makeColGap(width) { const result = new Box(null, { classes: "arraycolsep" }); result.width = width; return result; } function makeColOfRepeatingElements(context, rows, offset, element) { if (!element) return null; const col = []; for (const row of rows) { const cell = Atom.createBox(context, element, { type: "ignore" }); if (cell) { cell.depth = row.depth; cell.height = row.height; col.push({ box: cell, shift: row.pos - offset }); } } return new VBox({ individualShift: col }).wrap(context); } // src/atoms/box.ts var BoxAtom = class _BoxAtom extends Atom { constructor(options) { super({ mode: options.mode, command: options.command, style: options.style, body: options.body, type: "box" }); this.framecolor = options.framecolor; this.backgroundcolor = options.backgroundcolor; this.padding = options.padding; this.offset = options.offset; this.border = options.border; } static fromJson(json) { return new _BoxAtom(json); } toJson() { return __spreadProps(__spreadValues({}, super.toJson()), { framecolor: this.framecolor, backgroundcolor: this.backgroundcolor, padding: this.padding, offset: this.offset, border: this.border }); } render(parentContext) { var _a3, _b3, _c2, _d2; const base = Atom.createBox(parentContext, this.body, { type: "lift" }); if (!base) return null; const offset = parentContext.toEm((_a3 = this.offset) != null ? _a3 : { dimension: 0 }); base.depth += offset; base.setStyle("display", "inline-block"); base.setStyle("position", "relative"); base.setStyle( "height", Math.floor(100 * base.height + base.depth) / 100, "em" ); base.setStyle("vertical-align", -Math.floor(100 * base.height) / 100, "em"); const context = new Context({ parent: parentContext }, this.style); const padding2 = context.toEm((_b3 = this.padding) != null ? _b3 : { register: "fboxsep" }); const box = new Box(null, { classes: "ML__box" }); box.height = base.height + padding2; box.depth = base.depth + padding2; box.setStyle("box-sizing", "border-box"); box.setStyle("position", "absolute"); box.setStyle("top", -padding2 + 0.3, "em"); box.setStyle("left", 0); box.setStyle("height", box.height + box.depth, "em"); box.setStyle("width", "100%"); if (this.backgroundcolor) { box.setStyle( "background-color", (_c2 = context.toColor(this.backgroundcolor)) != null ? _c2 : "transparent" ); } if (this.framecolor) { box.setStyle( "border", `${context.getRegisterAsEm("fboxrule", 2)}em solid ${(_d2 = context.toColor(this.framecolor)) != null ? _d2 : "black"}` ); } if (this.border) box.setStyle("border", this.border); const result = new Box([box, base], { type: "lift" }); result.setStyle("display", "inline-block"); result.setStyle("position", "relative"); result.setStyle("line-height", 0); result.height = base.height + padding2 + (offset > 0 ? offset : 0); result.depth = base.depth + padding2 + (offset < 0 ? -offset : 0); result.setStyle("padding-left", padding2, "em"); result.setStyle("padding-right", padding2, "em"); result.setStyle( "height", Math.floor( 100 * (base.height + base.depth + 2 * padding2 + Math.abs(offset)) ) / 100, "em" ); result.setStyle("margin-top", -padding2, "em"); result.setStyle( "top", Math.floor(100 * (base.depth - base.height + 2 * padding2 - offset)) / 100, "em" ); result.setStyle( "vertical-align", Math.floor(100 * (base.depth + 2 * padding2)) / 100, "em" ); if (this.caret) result.caret = this.caret; return this.attachSupsub(parentContext, { base: result }); } _serialize(options) { if (!options.skipStyles) return super._serialize(options); return joinLatex([this.bodyToLatex(options), this.supsubToLatex(options)]); } }; // src/atoms/composition.ts var CompositionAtom = class _CompositionAtom extends Atom { constructor(value, options) { var _a3; super({ type: "composition", mode: (_a3 = options == null ? void 0 : options.mode) != null ? _a3 : "math", value }); } static fromJson(json) { return new _CompositionAtom(json.value, json); } toJson() { return super.toJson(); } get computedStyle() { return {}; } render(context) { const result = new Box(this.value, { classes: "ML__composition", type: "composition" }); this.bind(context, result); if (this.caret) result.caret = this.caret; return result; } _serialize(_options) { return ""; } }; // src/atoms/error.ts var ErrorAtom = class _ErrorAtom extends Atom { constructor(value) { super({ type: "error", value, command: value, mode: "math" }); this.verbatimLatex = value; } static fromJson(json) { return new _ErrorAtom(json.command); } toJson() { return super.toJson(); } render(context) { const result = this.createBox(context, { classes: "ML__error" }); if (this.caret) result.caret = this.caret; return result; } }; // src/atoms/group.ts var GroupAtom = class _GroupAtom extends Atom { constructor(arg, mode, style) { super({ type: "group", mode, style }); this.body = arg; this.boxType = arg.length > 1 ? "ord" : "ignore"; this.skipBoundary = true; this.displayContainsHighlight = false; if (arg && arg.length === 1 && arg[0].command === ",") this.captureSelection = true; } static fromJson(json) { return new _GroupAtom(json.body, json.mode, json.style); } render(context) { const box = Atom.createBox(context, this.body, { type: this.boxType }); if (!box) return null; if (this.caret) box.caret = this.caret; return this.bind(context, box); } _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); return `{${this.bodyToLatex(options)}}`; } }; // src/atoms/leftright.ts var LeftRightAtom = class _LeftRightAtom extends Atom { constructor(variant, body, options) { super({ type: "leftright", style: options.style, displayContainsHighlight: true }); this.variant = variant; this.body = body; this.leftDelim = options.leftDelim; this.rightDelim = options.rightDelim; } static fromJson(json) { var _a3; return new _LeftRightAtom((_a3 = json.variant) != null ? _a3 : "", json.body, json); } toJson() { const result = super.toJson(); if (this.variant) result.variant = this.variant; if (this.leftDelim) result.leftDelim = this.leftDelim; if (this.rightDelim) result.rightDelim = this.rightDelim; return result; } _serialize(options) { var _a3, _b3; const rightDelim = this.matchingRightDelim(); if (this.variant === "left...right") { return joinLatex([ "\\left", (_a3 = this.leftDelim) != null ? _a3 : ".", this.bodyToLatex(options), "\\right", rightDelim ]); } if (this.variant === "mleft...mright") { return joinLatex([ "\\mleft", (_b3 = this.leftDelim) != null ? _b3 : ".", this.bodyToLatex(options), "\\mright", rightDelim ]); } return joinLatex([ !this.leftDelim || this.leftDelim === "." ? "" : this.leftDelim, this.bodyToLatex(options), rightDelim ]); } matchingRightDelim() { var _a3, _b3; if (this.rightDelim && this.rightDelim !== "?") return this.rightDelim; const leftDelim = (_a3 = this.leftDelim) != null ? _a3 : "."; return (_b3 = RIGHT_DELIM[leftDelim]) != null ? _b3 : leftDelim; } render(parentContext) { var _a3, _b3; const context = new Context({ parent: parentContext }, this.style); console.assert(this.body !== void 0); const delimContext = new Context( { parent: parentContext, mathstyle: "textstyle" }, this.style ); const inner = (_a3 = Atom.createBox(context, this.body, { type: "inner" })) != null ? _a3 : new Box(null, { type: "inner" }); const innerHeight = inner.height / delimContext.scalingFactor; const innerDepth = inner.depth / delimContext.scalingFactor; const boxes = []; if (this.leftDelim) { boxes.push( this.bind( delimContext, makeLeftRightDelim( "open", this.leftDelim, innerHeight, innerDepth, delimContext, { isSelected: this.isSelected, classes: "ML__open" + (this.containsCaret ? " ML__contains-caret" : ""), mode: this.mode, style: this.style } ) ) ); } if (inner) { upgradeMiddle(inner.children, this, context, innerHeight, innerDepth); boxes.push(inner); } if (this.rightDelim) { let classes = this.containsCaret ? " ML__contains-caret" : ""; let delim = this.rightDelim; if (delim === "?") { if (context.smartFence) { delim = this.matchingRightDelim(); classes += " ML__smart-fence__close"; } else delim = "."; } boxes.push( this.bind( delimContext, makeLeftRightDelim( "close", delim, innerHeight, innerDepth, delimContext, { isSelected: this.isSelected, classes: classes + " ML__close", mode: this.mode, style: this.style } ) ) ); } let tightSpacing = this.variant === "mleft...mright"; const sibling = this.leftSibling; if (sibling) { if (!tightSpacing && sibling.isFunction) tightSpacing = true; if (!tightSpacing && sibling.type === "subsup" && ((_b3 = sibling.leftSibling) == null ? void 0 : _b3.isFunction)) tightSpacing = true; } const result = new Box(boxes, { type: tightSpacing ? "close" : "inner", classes: "left-right" }); result.setStyle("margin-top", `${-inner.depth}em`); result.setStyle("height", `${inner.height + inner.depth}em`); if (this.caret) result.caret = this.caret; return this.bind(context, result.wrap(context)); } }; function upgradeMiddle(boxes, atom, context, height, depth) { if (!boxes) return; for (let i = 0; i < boxes.length; i++) { const child = boxes[i]; if (child.type === "middle") { boxes[i] = atom.bind( context, makeLeftRightDelim("inner", child.value, height, depth, context, { isSelected: atom.isSelected }) ); boxes[i].caret = child.caret; boxes[i].isSelected = child.isSelected; boxes[i].cssId = child.cssId; boxes[i].htmlData = child.htmlData; boxes[i].htmlStyle = child.htmlStyle; boxes[i].attributes = child.attributes; boxes[i].cssProperties = child.cssProperties; } else if (child.children) upgradeMiddle(child.children, atom, context, height, depth); } } // src/atoms/macro.ts var MacroAtom = class _MacroAtom extends Atom { constructor(macro, options) { var _a3; super({ type: "macro", command: macro, style: options.style }); this.body = options.body; if (options.captureSelection === void 0) { if (options.args) this.captureSelection = false; else this.captureSelection = true; } else this.captureSelection = options.captureSelection; this.macroArgs = options.args; this.expand = (_a3 = options.expand) != null ? _a3 : false; } static fromJson(json) { return new _MacroAtom(json.command, json); } toJson() { const options = super.toJson(); if (this.expand) options.expand = true; if (this.captureSelection !== void 0) options.captureSelection = this.captureSelection; if (this.macroArgs) options.args = this.macroArgs; return options; } _serialize(options) { var _a3; return options.expandMacro && this.expand ? this.bodyToLatex(options) : this.command + ((_a3 = this.macroArgs) != null ? _a3 : ""); } render(context) { const result = Atom.createBox(context, this.body); if (!result) return null; if (this.caret) result.caret = this.caret; return this.bind(context, result); } }; var MacroArgumentAtom = class _MacroArgumentAtom extends Atom { constructor() { super({ type: "macro-argument" }); } static fromJson(_json) { return new _MacroArgumentAtom(); } toJson() { const options = super.toJson(); return options; } _serialize(_options) { return ""; } render(_context) { return null; } }; // src/atoms/prompt.ts var PromptAtom = class _PromptAtom extends Atom { constructor(placeholderId, correctness, locked = false, body, options) { var _a3; super({ type: "prompt", mode: (_a3 = options == null ? void 0 : options.mode) != null ? _a3 : "math", style: options == null ? void 0 : options.style, command: "\\placeholder" }); this.body = body; this.correctness = correctness; this.placeholderId = placeholderId; this.locked = locked; this.captureSelection = this.locked; } static fromJson(json) { return new _PromptAtom( json.placeholderId, json.correctness, json.locked, json.body, json ); } toJson() { const result = super.toJson(); if (this.placeholderId) result.placeholderId = this.placeholderId; if (!this.body) delete result.body; if (this.body) { result.body = this.body.filter((x) => x.type !== "first").map((x) => x.toJson()); } if (this.correctness) result.correctness = this.correctness; result.locked = this.locked; return result; } render(parentContext) { const context = new Context({ parent: parentContext }); const fboxsep = context.getRegisterAsEm("fboxsep"); const hPadding = fboxsep; const vPadding = fboxsep; const content = Atom.createBox(parentContext, this.body); if (!content) return null; if (!content.height) content.height = context.metrics.xHeight; content.setStyle("vertical-align", -content.height, "em"); if (this.correctness === "correct") { content.setStyle( "color", "var(--correct-color, var(--ML__correct-color))" ); } else if (this.correctness === "incorrect") { content.setStyle( "color", "var(--incorrect-color, var(--ML__incorrect-color))" ); } const base = new Box(content, { type: "ord" }); base.setStyle("display", "inline-block"); base.setStyle("height", content.height + content.depth, "em"); base.setStyle("vertical-align", -vPadding, "em"); let boxClasses = "ML__prompt "; if (this.locked) { boxClasses += " ML__lockedPromptBox "; } else boxClasses += " ML__editablePromptBox "; if (this.correctness === "correct") boxClasses += " ML__correctPromptBox "; else if (this.correctness === "incorrect") boxClasses += " ML__incorrectPromptBox "; if (this.containsCaret) boxClasses += " ML__focusedPromptBox "; const box = new Box(null, { classes: boxClasses, attributes: { part: "prompt" } }); box.height = base.height + vPadding; box.depth = base.depth + vPadding; box.width = base.width + 2 * hPadding; box.setStyle("box-sizing", "border-box"); box.setStyle("position", "absolute"); box.setStyle("height", base.height + base.depth + 2 * vPadding, "em"); if (hPadding === 0) box.setStyle("width", "100%"); if (hPadding !== 0) { box.setStyle("width", `calc(100% + ${2 * hPadding}em)`); box.setStyle("top", fboxsep, "em"); box.setStyle("left", -hPadding, "em"); } if (!this.body || this.body.length === 1) { box.width = 3 * hPadding; box.setStyle("width", `calc(100% + ${3 * hPadding}em)`); box.setStyle("left", -1.5 * hPadding, "em"); } let svg = ""; if (this.correctness === "incorrect") { svg += ''; } if (svg) box.svgOverlay = svg; const result = new Box([box, base], { classes: "ML__prompt-atom" }); result.setStyle("position", "relative"); result.setStyle("display", "inline-block"); result.setStyle("line-height", 0); result.height = base.height + vPadding + 0.2; result.depth = base.depth + vPadding; result.left = hPadding; result.right = hPadding; result.setStyle("height", base.height + vPadding, "em"); result.setStyle("top", base.depth - base.height, "em"); result.setStyle("vertical-align", base.depth + vPadding, "em"); result.setStyle("margin-left", 0.5, "em"); result.setStyle("margin-right", 0.5, "em"); if (this.caret) result.caret = this.caret; return this.bind( context, this.attachSupsub(parentContext, { base: result }) ); } _serialize(options) { var _a3; const value = (_a3 = this.bodyToLatex(options)) != null ? _a3 : ""; if (options.skipPlaceholders) return value; let command = "\\placeholder"; if (this.placeholderId) command += `[${this.placeholderId}]`; if (this.correctness === "correct") command += "[correct]"; else if (this.correctness === "incorrect") command += "[incorrect]"; if (this.locked) command += "[locked]"; return latexCommand(command, value); } }; // src/atoms/subsup.ts var SubsupAtom = class _SubsupAtom extends Atom { constructor(options) { super({ type: "subsup", style: options == null ? void 0 : options.style }); this.subsupPlacement = "auto"; } static fromJson(json) { const result = new _SubsupAtom(json); for (const branch of NAMED_BRANCHES) if (json[branch]) result.setChildren(json[branch], branch); return result; } render(context) { var _a3; const phantomCtx = new Context({ parent: context, isPhantom: true }); const leftSibling = this.leftSibling; const base = (_a3 = leftSibling.render(phantomCtx)) != null ? _a3 : new Box(null); const phantom = new Box(null); phantom.height = base.height; phantom.depth = base.depth; return this.attachSupsub(context, { base: phantom, isCharacterBox: leftSibling.isCharacterBox(), // Set to 'ignore' so that it is ignored during inter-box spacing // adjustment. type: "ignore" }); } _serialize(options) { return this.supsubToLatex(options); } }; // src/core/parser.ts function isLiteral(token) { if (!token) return false; return !/^(<$$>|<$>||<{>|<}>|#[0-9\?]|\\.+)$/.test(token); } var Parser = class { /** * @param tokens - An array of tokens generated by the lexer. * * Note: smartFence and registers are usually defined by the GloablContext. * However, in some cases they need to be overridden. * */ constructor(tokens, context, options) { // Accumulated errors encountered while parsing this.errors = []; // The current token to be parsed: index in `this.tokens` this.index = 0; // Counter to prevent deadlock. If `end()` is called too many // times (1,000) in a row for the same token, bail. this.endCount = 0; var _a3, _b3, _c2, _d2; options != null ? options : options = {}; this.tokens = tokens; this.context = context instanceof Context && !(options == null ? void 0 : options.parseMode) && !options.mathstyle ? context : new Context( { from: context, mathstyle: options.mathstyle }, options.style ); this.args = (_a3 = options.args) != null ? _a3 : void 0; this.smartFence = this.context.smartFence; this.parsingContext = { parent: void 0, mathlist: [], style: (_b3 = options.style) != null ? _b3 : {}, parseMode: (_c2 = options.parseMode) != null ? _c2 : "math", mathstyle: (_d2 = options.mathstyle) != null ? _d2 : "displaystyle", tabular: false }; } beginContext(options) { var _a3, _b3, _c2; const current = this.parsingContext; const newContext = { parent: current, mathlist: [], style: __spreadValues({}, current.style), parseMode: (_a3 = options == null ? void 0 : options.mode) != null ? _a3 : current.parseMode, mathstyle: (_b3 = options == null ? void 0 : options.mathstyle) != null ? _b3 : current.mathstyle, tabular: (_c2 = options == null ? void 0 : options.tabular) != null ? _c2 : false }; this.parsingContext = newContext; } endContext() { this.parsingContext = this.parsingContext.parent; } onError(err) { this.errors.push(__spreadValues({ before: tokensToString(this.tokens.slice(this.index, this.index + 10)), after: tokensToString( this.tokens.slice(Math.max(0, this.index - 10), this.index) ) }, err)); } get mathlist() { return this.parsingContext.mathlist; } set mathlist(value) { this.parsingContext.mathlist = value; } get parseMode() { return this.parsingContext.parseMode; } set parseMode(value) { this.parsingContext.parseMode = value; } get tabularMode() { return this.parsingContext.tabular; } get style() { let context = this.parsingContext; while (context) { if (context.style) return __spreadValues({}, context.style); context = context.parent; } return {}; } set style(value) { this.parsingContext.style = value; } /** * True if we've reached the end of the token stream */ end() { this.endCount++; return this.index >= this.tokens.length || this.endCount > 1e3; } next() { this.index += 1; } get() { this.endCount = 0; return this.index < this.tokens.length ? this.tokens[this.index++] : ""; } peek() { return this.tokens[this.index]; } /** * @return True if the next token matches the input, and advance */ match(input) { if (this.tokens[this.index] === input) { this.index++; return true; } return false; } /** * Return the last atom in the mathlisst that can have a * subscript/superscript attached to it. * If there isn't one, insert a `SubsupAtom` and return it. */ lastSubsupAtom() { let atom; if (this.mathlist.length > 0) { atom = this.mathlist[this.mathlist.length - 1]; if (atom.type === "subsup") return atom; if (atom.subsupPlacement !== void 0) return atom; } atom = new SubsupAtom({ style: this.style }); this.mathlist.push(atom); return atom; } /** * @return True if the next token matches the specified regular expression pattern. */ hasPattern(pattern) { return pattern.test(this.tokens[this.index]); } hasInfixCommand() { var _a3; const { index } = this; if (index < this.tokens.length && this.tokens[index].startsWith("\\")) { const info = getDefinition(this.tokens[index], this.parseMode); if (!info || info.definitionType === "symbol") return false; if (info.ifMode && !info.ifMode.includes(this.parseMode)) return false; return (_a3 = info.infix) != null ? _a3 : false; } return false; } matchColumnSeparator() { if (!this.tabularMode) return false; const peek = this.peek(); if (peek !== "&") return false; this.index++; return true; } matchRowSeparator() { if (!this.tabularMode) return false; const peek = this.peek(); if (peek !== "\\\\" && peek !== "\\cr" && peek !== "\\tabularnewline") return false; this.index++; return true; } /** * Return the appropriate value for a placeholder, either a default * one, or if a value was provided for #? via args, that value. */ placeholder() { var _a3; const placeHolderArg = (_a3 = this.args) == null ? void 0 : _a3.call(this, "?"); if (!placeHolderArg) return [new PlaceholderAtom({ mode: this.parseMode, style: this.style })]; return parseLatex(placeHolderArg, { parseMode: this.parseMode, mathstyle: "textstyle" }); } skipWhitespace() { while (this.match("")) { } } skipUntilToken(input) { let token = this.tokens[this.index]; while (token && token !== input) token = this.tokens[++this.index]; if (token === input) this.index++; } skipFiller() { while (this.match("\\relax") || this.match("")) { } } /** * Keywords are used to specify dimensions, and for various other * syntactic constructs. * * Unlike commands, they are not case sensitive. * * There are 25 keywords: * * at by bp cc cm dd depth em ex fil fill filll height in minus * mm mu pc plus pt sp spread to true width * * TeX: 8212 * @return true if the expected keyword is present */ matchKeyword(keyword) { const savedIndex = this.index; let done = this.end(); let value = ""; while (!done) { const token = this.get(); if (isLiteral(token)) { value += token; done = this.end() || value.length >= keyword.length; } else done = true; } const hasKeyword = keyword.toUpperCase() === value.toUpperCase(); if (!hasKeyword) this.index = savedIndex; return hasKeyword; } /** * Return a sequence of characters as a string. * i.e. 'abcd' returns 'abcd'. * Terminates on the first non-literal token encountered * e.g. '<{>', '<}>' etc... * Will also terminate on character literal ']' */ scanString() { let result = ""; while (!this.end()) { const token = this.peek(); if (token === "]") return result; if (token === "") result += " "; else if (token.startsWith("\\")) { this.onError({ code: "unexpected-command-in-string" }); result += token.substring(1); } else if (isLiteral(token)) result += token; else { return result; } this.next(); } return result; } /** * Return a sequence of characters as a string. * Terminates on a balanced closing bracket * This is used by the `\ce` command */ scanBalancedString() { let result = ""; let done = this.end(); let level = 1; while (!done) { const token = this.get(); if (token === "") result += " "; else if (token === "<{>") { result += "{"; level += 1; } else if (token === "<}>") { level -= 1; if (level > 0) result += "}"; else this.index -= 1; } else if (token === "<$>") result += "$"; else if (token === "<$$>") result += "$$"; else result += token; done = level === 0 || this.end(); } return result; } /** * Return the literal tokens, as a string, until a matching closing "}" * Used when handling macros */ scanLiteralGroup() { var _a3; if (!this.match("<{>")) return ""; let result = ""; let level = 1; while (level > 0 && !this.end()) { const token = this.get(); if (token === "<}>") { level -= 1; if (level > 0) result += "}"; } else if (token === "<{>") { level += 1; result += "{"; } else { if (/\\[a-zA-Z]+$/.test(result) && /^[a-zA-Z]/.test(token)) result += " "; result += (_a3 = { "": " ", "<$$>": "$$", "<$>": "$" }[token]) != null ? _a3 : token; } } return result; } /** * Return as a number a group of characters representing a * numerical quantity. * * From TeX:8695 (scan_int): * > An integer number can be preceded by any number of spaces and `+' or * > `-' signs. Then comes either a decimal constant (i.e., radix 10), an * > octal constant (i.e., radix 8, preceded by '), a hexadecimal constant * > (radix 16, preceded by "), an alphabetic constant (preceded by `), or * > an internal variable. */ scanNumber(isInteger = true) { var _a3, _b3; let negative = false; let token = this.peek(); while (token === "" || token === "+" || token === "-") { this.get(); if (token === "-") negative = !negative; token = this.peek(); } isInteger = Boolean(isInteger); let radix = 10; let digits = /\d/; if (this.match("'")) { radix = 8; digits = /[0-7]/; isInteger = true; } else if (this.match('"')) { radix = 16; digits = /[\dA-F]/; isInteger = true; } else if (this.match("x")) { radix = 16; digits = /[\dA-Fa-f]/; isInteger = true; } else if (this.match("`")) { token = this.get(); if (token) { if (token.length === 2 && token.startsWith("\\")) { return { number: (negative ? -1 : 1) * ((_a3 = token.codePointAt(1)) != null ? _a3 : 0), base: "alpha" }; } return { number: (negative ? -1 : 1) * ((_b3 = token.codePointAt(0)) != null ? _b3 : 0), base: "alpha" }; } return null; } let value = ""; while (this.hasPattern(digits)) value += this.get(); if (!isInteger && (this.match(".") || this.match(","))) { value += "."; while (this.hasPattern(digits)) value += this.get(); } const result = isInteger ? Number.parseInt(value, radix) : Number.parseFloat(value); if (Number.isNaN(result)) return null; return { number: negative ? -result : result, base: radix === 16 ? "hexadecimal" : radix === 8 ? "octal" : "decimal" }; } scanRegister() { var _a3; const index = this.index; const number = this.scanNumber(false); this.skipWhitespace(); if (this.match("\\relax")) return number; let negative = false; if (number === null) { while (true) { const s = this.peek(); if (s === "-") negative = !negative; else if (s !== "+") break; this.next(); this.skipWhitespace(); } } if (this.match("\\global")) { this.skipWhitespace(); const register4 = this.get(); if (register4.startsWith("\\")) { if (number) { return { register: register4, global: true, factor: (negative ? -1 : 1) * number.number }; } if (negative) return { register: register4, global: true, factor: -1 }; return { register: register4, global: true }; } this.index = index; return null; } let register3 = this.get(); if (!(register3 == null ? void 0 : register3.startsWith("\\"))) { this.index = index; return null; } register3 = register3.substring(1); if (!this.context.registers[register3]) { this.index = index; return null; } if (!negative || number !== null) { return { register: register3, factor: (negative ? -1 : 1) * ((_a3 = number == null ? void 0 : number.number) != null ? _a3 : 1) }; } return { register: register3 }; } scanValue() { const register3 = this.scanRegister(); if (register3) return register3; const index = this.index; const glue = this.scanGlueOrDimen(); if (glue && ("unit" in glue || "glue" in glue && "unit" in glue.glue)) return glue; this.index = index; const number = this.scanNumber(); if (number) return number; if (this.end() || !isLiteral(this.peek())) return null; const s = this.scanString(); if (s.length > 0) return { string: s }; return null; } /** * Return a dimension * * See TeX:8831 */ scanDimen() { const value = this.scanNumber(false); if (value === null) return null; const dimension = value.number; this.skipWhitespace(); this.matchKeyword("true"); this.skipWhitespace(); let unit; if (this.matchKeyword("pt")) unit = "pt"; else if (this.matchKeyword("mm")) unit = "mm"; else if (this.matchKeyword("cm")) unit = "cm"; else if (this.matchKeyword("ex")) unit = "ex"; else if (this.matchKeyword("px")) unit = "px"; else if (this.matchKeyword("em")) unit = "em"; else if (this.matchKeyword("bp")) unit = "bp"; else if (this.matchKeyword("dd")) unit = "dd"; else if (this.matchKeyword("pc")) unit = "pc"; else if (this.matchKeyword("in")) unit = "in"; else if (this.matchKeyword("mu")) unit = "mu"; return unit ? { dimension, unit } : { dimension }; } scanGlueOrDimen() { const dimen = this.scanDimen(); if (dimen === null) return null; this.skipWhitespace(); if (this.match("\\relax")) return dimen; const result = { glue: dimen }; if (this.matchKeyword("plus")) { const grow = this.scanDimen(); if (grow) result.grow = grow; else return result; } this.skipWhitespace(); if (this.match("\\relax")) return result; this.skipWhitespace(); if (this.matchKeyword("minus")) { const shrink = this.scanDimen(); if (shrink) result.shrink = shrink; else return result; } if (!result.grow && !result.shrink) return dimen; return result; } scanColspec() { this.skipWhitespace(); const result = []; while (!this.end() && !(this.peek() === "<}>" || this.peek() === "]")) { const literal = this.get(); if (literal === "c" || literal === "r" || literal === "l") result.push({ align: literal }); else if (literal === "|") result.push({ separator: "solid" }); else if (literal === ":") result.push({ separator: "dashed" }); else if (literal === "@") { if (this.match("<{>")) { this.beginContext({ mode: "math" }); result.push({ gap: this.scan((token) => token === "<}>") }); this.endContext(); } if (!this.match("<}>")) this.onError({ code: "unbalanced-braces" }); } } return result; } /** * Scan a `\(...\)` or `\[...\]` sequence * @return group for the sequence or null */ scanModeSet() { let mathstyle = void 0; if (this.match("\\(")) mathstyle = "textstyle"; if (!mathstyle && this.match("\\[")) mathstyle = "displaystyle"; if (!mathstyle) return null; this.beginContext({ mode: "math", mathstyle }); const result = this.scan( (token) => token === (mathstyle === "displaystyle" ? "\\]" : "\\)") ); if (!this.match(mathstyle === "displaystyle" ? "\\]" : "\\)")) this.onError({ code: "unbalanced-mode-shift" }); this.endContext(); return result; } /** * Scan a `$...$` or `$$...$$` sequence */ scanModeShift() { let final = ""; if (this.match("<$>")) final = "<$>"; if (!final && this.match("<$$>")) final = "<$$>"; if (!final) return null; this.beginContext({ mode: "math", mathstyle: true ? "textstyle" : 0 }); const result = this.scan((token) => token === final); if (!this.match(final)) this.onError({ code: "unbalanced-mode-shift" }); this.endContext(); return result; } /** * Scan a \begin{env}...\end{end} sequence */ scanEnvironment() { if (!this.match("\\begin")) return null; const envName = this.scanArgument("string"); if (!envName) return null; const def = getEnvironmentDefinition(envName); if (!def) { this.onError({ code: "unknown-environment", arg: envName }); return null; } const args = []; if (def.params) { for (const parameter of def.params) { if (parameter.isOptional) { args.push(this.scanOptionalArgument(parameter.type)); } else { const arg = this.scanArgument(parameter.type); if (!arg) this.onError({ code: "missing-argument", arg: envName }); args.push(arg); } } } this.beginContext({ tabular: def.tabular }); const array = []; const rowGaps = []; let row = []; let done = false; do { if (this.end()) { this.onError({ code: "unbalanced-environment", arg: envName }); done = true; } if (!done && this.match("\\end")) { if (this.scanArgument("string") !== envName) { this.onError({ code: "unbalanced-environment", arg: envName }); } done = true; } if (!done) { if (this.matchColumnSeparator()) { row.push(this.mathlist); this.mathlist = []; } else if (this.matchRowSeparator()) { row.push(this.mathlist); this.mathlist = []; let gap = null; this.skipWhitespace(); if (this.match("[")) { gap = this.scanDimen(); this.skipWhitespace(); this.match("]"); } rowGaps.push(gap != null ? gap : { dimension: 0 }); array.push(row); row = []; } else { this.mathlist.push( ...this.scan( (token) => [ "<}>", "&", "\\end", "\\cr", "\\\\", "\\tabularnewline" ].includes(token) ) ); } } } while (!done); row.push(this.mathlist); if (row.length > 0) array.push(row); this.endContext(); return def.createAtom(envName, array, rowGaps, args); } /** * Parse an expression: a literal, or a command and its arguments */ scanExpression() { const savedList = this.mathlist; this.mathlist = []; if (this.parseExpression()) { const result = this.mathlist; this.mathlist = savedList; return result; } this.mathlist = savedList; return null; } /** * Parse a sequence until a group end marker, such as * `}`, `\end`, `&`, etc... * * Returns an array of atoms or an empty array if the sequence * terminates right away. * * @param done - A predicate indicating if a token signals the end of a * group */ scan(done) { this.beginContext(); if (!done) done = (token) => token === "<}>"; let infix = ""; let infixInfo = null; let infixArgs = []; let prefix = null; while (!this.end() && !done(this.peek())) { if (this.hasInfixCommand() && !infix) { infix = this.get(); infixInfo = getDefinition(infix, "math"); if (infixInfo) infixArgs = this.scanArguments(infixInfo)[1]; prefix = this.mathlist; this.mathlist = []; } else this.parseExpression(); } let result; if (infix) { console.assert(Boolean(infixInfo)); infixArgs.unshift(this.mathlist); if (prefix) infixArgs.unshift(prefix); result = [ infixInfo.createAtom({ command: infix, args: infixArgs, style: this.style, mode: this.parseMode }) ]; } else result = this.mathlist; this.endContext(); return result; } /** * Parse a group enclosed in a pair of braces: `{...}`. * * Return either a group Atom or null if not a group. * * Return a group Atom with an empty body if an empty * group (i.e. `{}`). */ scanGroup() { const initialIndex = this.index; if (!this.match("<{>")) return null; const body = this.scan((token) => token === "<}>"); if (!this.match("<}>")) this.onError({ code: "unbalanced-braces" }); const result = new GroupAtom(body, this.parseMode, this.style); result.verbatimLatex = tokensToString( this.tokens.slice(initialIndex, this.index) ); return result; } scanSmartFence() { this.skipWhitespace(); if (!this.match("(")) return null; this.beginContext(); let nestLevel = 1; while (!this.end() && nestLevel !== 0) { if (this.match("(")) nestLevel += 1; if (this.match(")")) nestLevel -= 1; if (nestLevel !== 0) this.parseExpression(); } const result = new LeftRightAtom("", this.mathlist, { leftDelim: "(", rightDelim: nestLevel === 0 ? ")" : "?" }); this.endContext(); return result; } /** * Scan a delimiter, e.g. '(', '|', '\vert', '\ulcorner' * * @return The delimiter (as a character or command) or null */ scanDelim() { this.skipWhitespace(); const token = this.peek(); if (!token) { this.onError({ code: "unexpected-end-of-string" }); return null; } if (!isLiteral(token) && !token.startsWith("\\")) return null; this.next(); const info = getDefinition(token, "math"); if (!info) { this.onError({ code: "unknown-command", arg: token }); return null; } if (info.definitionType === "function" && info.ifMode && !info.ifMode.includes(this.parseMode)) { this.onError({ code: "unexpected-delimiter", arg: token }); return null; } if (info.definitionType === "symbol" && (info.type === "mopen" || info.type === "mclose")) return token; if (/^(\.|\?|\||<|>|\\vert|\\Vert|\\\||\\surd|\\uparrow|\\downarrow|\\Uparrow|\\Downarrow|\\updownarrow|\\Updownarrow|\\mid|\\mvert|\\mVert)$/.test( token )) return token; this.onError({ code: "unexpected-delimiter", arg: token }); return null; } /** * Parse a `/left.../right` sequence. * * Note: the `/middle` command can occur multiple times inside a * `/left.../right` sequence, and is handled separately. * * Return either an atom of type `"leftright"` or null */ scanLeftRight() { var _a3; if (this.match("\\right")) { this.onError({ code: "unbalanced-braces" }); return new ErrorAtom("\\right"); } if (this.match("\\mright")) { this.onError({ code: "unbalanced-braces" }); return new ErrorAtom("\\mright"); } let close = "\\right"; if (!this.match("\\left")) { if (!this.match("\\mleft")) return null; close = "\\mright"; } const leftDelim = this.scanDelim(); if (!leftDelim) { this.onError({ code: "unexpected-delimiter" }); return new ErrorAtom(close === "\\right" ? "\\left" : "\\mleft"); } this.beginContext(); while (!this.end() && !this.match(close)) this.parseExpression(); const body = this.mathlist; this.endContext(); const rightDelim = (_a3 = this.scanDelim()) != null ? _a3 : "."; return new LeftRightAtom( close === "\\right" ? "left...right" : "mleft...mright", body, { leftDelim, rightDelim, style: this.style } ); } /** * Parse a subscript/superscript: `^` and `_`. * * Modify the last atom accordingly, or create a new 'subsup' carrier. * */ parseSupSub() { if (this.parseMode !== "math") return false; let token = this.peek(); if (token !== "^" && token !== "_" && token !== "'") return false; const target = this.lastSubsupAtom(); while (token === "^" || token === "_" || token === "'") { if (this.match("'")) { if (this.match("'")) { target.addChild( new Atom({ type: "mord", command: "\\doubleprime", mode: "math", value: "\u2032\u2032" // "\u2033" displays too high }), "superscript" ); } else { target.addChild( new Atom({ type: "mord", command: "\\prime", mode: "math", value: "\u2032" }), "superscript" ); } } else if (this.match("^") || this.match("_")) { target.addChildren( argAtoms(this.scanArgument("expression")), token === "_" ? "subscript" : "superscript" ); } token = this.peek(); } return true; } /** * Parse a `\limits` or `\nolimits` command. * * This will change the placement of limits to be either above or below * (if `\limits`) or in the superscript/subscript position (if `\nolimits`). * * This overrides the calculation made for the placement, which is usually * dependent on the displaystyle (`textstyle` prefers `\nolimits`, while * `displaystyle` prefers `\limits`). */ parseLimits() { if (this.parseMode !== "math") return false; const isLimits = this.match("\\limits"); const isNoLimits = !isLimits && this.match("\\nolimits"); const isDisplayLimits = !isNoLimits && !isLimits && this.match("\\displaylimits"); if (!isLimits && !isNoLimits && !isDisplayLimits) return false; const opAtom = this.mathlist.length > 0 ? this.mathlist[this.mathlist.length - 1] : null; if (opAtom === null) return false; opAtom.explicitSubsupPlacement = true; if (isLimits) opAtom.subsupPlacement = "over-under"; if (isNoLimits) opAtom.subsupPlacement = "adjacent"; if (isDisplayLimits) opAtom.subsupPlacement = "auto"; return true; } scanArguments(info) { if (!(info == null ? void 0 : info.params)) return [void 0, []]; let deferredArg = void 0; const args = []; let i = info.infix ? 2 : 0; while (i < info.params.length) { const parameter = info.params[i]; if (parameter.type === "rest") { args.push( this.scan( (token) => [ "<}>", "&", "\\end", "\\cr", "\\\\", "\\tabularnewline", "\\right" ].includes(token) ) ); } else if (parameter.isOptional) args.push(this.scanOptionalArgument(parameter.type)); else if (parameter.type.endsWith("*")) { deferredArg = parameter.type.slice(0, -1); } else args.push(this.scanArgument(parameter.type)); i += 1; } return [deferredArg, args]; } scanSymbolOrLiteral() { const token = this.peek(); if (!token) return null; this.next(); let result; if (isLiteral(token)) { const result2 = Mode.createAtom(this.parseMode, token, __spreadValues({}, this.style)); return result2 ? [result2] : null; } result = this.scanMacro(token); if (result) return [result]; if (token.startsWith("\\")) { const info = getDefinition(token, this.parseMode); if (!info) { this.onError({ code: "unknown-command", arg: token }); return [new ErrorAtom(token)]; } if (info.definitionType === "symbol") { const style = __spreadValues({}, this.style); if (info.variant) style.variant = info.variant; result = new Atom({ type: info.type, command: token, style, value: String.fromCodePoint(info.codepoint), mode: this.parseMode, verbatimLatex: token }); } else if (info.applyMode || info.applyStyle || info.infix) { this.onError({ code: "invalid-command", arg: token }); return [new ErrorAtom(token)]; } else if (info.createAtom) { result = info.createAtom({ command: token, args: [], style: this.style, mode: this.parseMode }); } } return result ? [result] : null; } scanArgument(type) { var _a3; this.skipFiller(); const mode = this.parseMode; if (type === "auto") type = mode; if (!this.match("<{>")) { if (type === "string") return this.scanString(); if (type === "value") return this.scanValue(); if (type === "delim") return (_a3 = this.scanDelim()) != null ? _a3 : "."; if (type === "expression") return this.scanExpression(); if (type === "math") { if (type !== mode) this.beginContext({ mode: "math" }); const result2 = this.scanSymbolOrLiteral(); if (type !== mode) this.endContext(); return result2; } if (type === "text") { if (type !== mode) this.beginContext({ mode: "text" }); const result2 = this.scanSymbolOrLiteral(); if (type !== mode) this.endContext(); return result2; } if (type === "balanced-string") return null; console.assert(false); return null; } if (type === "text") { this.beginContext({ mode: "text" }); do this.mathlist.push(...this.scan()); while (!this.match("<}>") && !this.end()); const atoms = this.mathlist; this.endContext(); return { group: atoms }; } if (type === "math") { this.beginContext({ mode: "math" }); do this.mathlist.push(...this.scan()); while (!this.match("<}>") && !this.end()); const atoms = this.mathlist; this.endContext(); return { group: atoms }; } let result = null; if (type === "expression") { this.beginContext({ mode: "math" }); do this.mathlist.push(...this.scan()); while (!this.match("<}>") && !this.end()); const atoms = this.mathlist; this.endContext(); return { group: atoms }; } if (type === "string") result = this.scanString(); else if (type === "balanced-string") result = this.scanBalancedString(); else if (type === "colspec") result = this.scanColspec(); else if (type === "value") result = this.scanValue(); this.skipUntilToken("<}>"); return result; } scanOptionalArgument(argType) { argType = argType === "auto" ? this.parseMode : argType; this.skipFiller(); if (!this.match("[")) return null; let result = null; while (!this.end() && !this.match("]")) { if (argType === "string") result = this.scanString(); else if (argType === "value") result = this.scanValue(); else if (argType === "colspec") result = this.scanColspec(); else if (argType === "bbox") { const bboxParameter = {}; const list = this.scanString().toLowerCase().trim().split(/,(?![^(]*\)(?:(?:[^(]*\)){2})*[^"]*$)/); for (const element of list) { const m = element.match(/^\s*([\d.]+)\s*([a-z]{2})/); if (m) { bboxParameter.padding = { dimension: parseInt(m[1]), unit: m[2] }; } else { const m2 = element.match(/^\s*border\s*:\s*(.*)/); if (m2) bboxParameter.border = m2[1]; else bboxParameter.backgroundcolor = { string: element }; } } result = bboxParameter; } else if (argType === "math") { this.beginContext({ mode: "math" }); result = this.mathlist.concat(this.scan((token) => token === "]")); this.endContext(); } } return result; } /** Parse a symbol or a command and its arguments */ scanSymbolOrCommand(command) { var _a3, _b3, _c2; if (command === "\\placeholder") { const id = this.scanOptionalArgument("string"); const defaultValue = this.scanOptionalArgument("math"); const defaultAsString = Atom.serialize(defaultValue, { defaultMode: "math" }); let defaultAtoms = []; let correctness; if (!correctness && defaultAsString === "correct") correctness = "correct"; else if (!correctness && defaultAsString === "incorrect") correctness = "incorrect"; else if (defaultAsString !== "") defaultAtoms = defaultValue; const locked = this.scanOptionalArgument("string") === "locked"; const value = this.scanArgument("auto"); let body; if (value && Array.isArray(value) && value.length > 0) body = value; else if (value && typeof value === "object" && "group" in value) body = value.group; else body = defaultAtoms; if (id) { return [ new PromptAtom(id, correctness, locked, body != null ? body : defaultAtoms, { mode: this.parseMode, style: this.style }) ]; } return [new PlaceholderAtom({ mode: this.parseMode, style: this.style })]; } if (command === "\\renewcommand" || command === "\\newcommand" || command === "\\providecommand" || command === "\\def") { const index = this.index; const cmd = this.scanLiteralGroup() || this.next(); if (!cmd) return null; if (this.context.registers[cmd.substring(1)]) { const value = this.scanArgument("string"); if (value !== null) this.context.registers[cmd.substring(1)] = value; const verbatimLatex = joinLatex([ command, tokensToString(this.tokens.slice(index, this.index)) ]); return [new Atom({ type: "text", value: "", verbatimLatex })]; } } let result = this.scanMacro(command); if (result) return [result]; const info = getDefinition(command, this.parseMode); if (!info) { if (this.parseMode === "text") { if (/[a-zA-Z]/.test((_a3 = this.peek()) != null ? _a3 : "")) { command += " "; } return [...command].map( (c) => new Atom({ type: "text", value: c, mode: "text", style: this.style }) ); } this.onError({ code: "unknown-command", arg: command }); return [new ErrorAtom(command)]; } const initialIndex = this.index; if (info.definitionType === "symbol") { const style = __spreadValues({}, this.style); if (info.variant) style.variant = info.variant; result = new Atom({ type: info.type, command, style, value: String.fromCodePoint(info.codepoint), mode: this.parseMode }); } else { if (info.ifMode && !info.ifMode.includes(this.parseMode)) { return []; } const savedMode = this.parseMode; if (info.applyMode) this.parseMode = info.applyMode; let deferredArg = void 0; let args = []; if (info.parse) args = info.parse(this); else [deferredArg, args] = this.scanArguments(info); this.parseMode = savedMode; if (info.applyMode && !info.applyStyle && !info.createAtom) return argAtoms(args[0]); if (info.infix) { this.onError({ code: "too-many-infix-commands", arg: command }); return null; } if (typeof info.createAtom === "function") { result = info.createAtom({ command, args, style: this.style, mode: this.parseMode }); if (deferredArg) result.body = argAtoms(this.scanArgument(deferredArg)); } else if (typeof info.applyStyle === "function") { const style = __spreadValues(__spreadValues({}, this.style), info.applyStyle(command, args, this.context)); const savedMode2 = this.parseMode; if (info.applyMode) this.parseMode = info.applyMode; if (deferredArg) { const saveStyle = this.style; this.style = style; const atoms = this.scanArgument(deferredArg); this.style = saveStyle; this.parseMode = savedMode2; return argAtoms(atoms); } this.style = style; } else { result = new Atom({ type: "mord", command: (_b3 = info.command) != null ? _b3 : command, style: __spreadValues({}, this.style), value: command, mode: (_c2 = info.applyMode) != null ? _c2 : this.parseMode }); } } if (!result) return null; if (result instanceof Atom && result.verbatimLatex === void 0 && !/^\\(llap|rlap|class|cssId|htmlData)$/.test(command)) { const verbatim = joinLatex([ command, tokensToString(this.tokens.slice(initialIndex, this.index)) ]); if (verbatim) result.verbatimLatex = verbatim; } if (result.verbatimLatex === null) result.verbatimLatex = void 0; if (result.isFunction && this.smartFence) { const smartFence = this.scanSmartFence(); if (smartFence) return [result, smartFence]; } return [result]; } scanSymbolCommandOrLiteral() { const token = this.get(); if (!token) return null; if (isLiteral(token)) { const result = Mode.createAtom(this.parseMode, token, __spreadValues({}, this.style)); if (!result) return null; if (result.isFunction && this.smartFence) { const smartFence = this.scanSmartFence(); if (smartFence) return [result, smartFence]; } return [result]; } if (token.startsWith("\\")) return this.scanSymbolOrCommand(token); if (token === "") { if (this.parseMode === "text") return [new TextAtom(" ", " ", this.style)]; return null; } if (token === "<}>") this.onError({ latex: "", code: "unbalanced-braces" }); else { this.onError({ latex: "", code: "unexpected-token", arg: token }); } return null; } /** * Scan the macro name and its arguments and return a macro atom */ scanMacro(macro) { var _a3; const def = this.context.getMacro(macro); if (!def) return null; const initialIndex = this.index; const argCount = def.args; const args = { "?": (_a3 = this.args) == null ? void 0 : _a3.call(this, "?") }; for (let i = 1; i <= argCount; i++) { let arg = this.scanLiteralGroup(); if (!arg) { const index = this.index; this.scanExpression(); arg = tokensToString(this.tokens.slice(index, this.index)); } args[i] = arg; } return new MacroAtom(macro, { expand: def.expand, captureSelection: def.captureSelection, args: initialIndex === this.index ? null : tokensToString(this.tokens.slice(initialIndex, this.index)), style: this.parsingContext.style, body: parseLatex(def.def, { context: this.context, parseMode: this.parseMode, args: (arg) => args[arg], mathstyle: this.parsingContext.mathstyle, style: this.parsingContext.style }) }); } /** * Make an atom for the current token or token group and * add it to the parser's mathlist. * If the token is a command with arguments, will also parse the * arguments. */ parseExpression() { var _a3, _b3, _c2, _d2; let result = (_d2 = (_c2 = (_b3 = (_a3 = this.scanEnvironment()) != null ? _a3 : this.scanModeShift()) != null ? _b3 : this.scanModeSet()) != null ? _c2 : this.scanGroup()) != null ? _d2 : this.scanLeftRight(); if (result === null) { if (this.parseSupSub()) return true; if (this.parseLimits()) return true; result = this.scanSymbolCommandOrLiteral(); } if (!result) return false; if (Array.isArray(result)) this.mathlist.push(...result); else this.mathlist.push(result); return true; } }; function parseLatex(s, options) { var _a3, _b3, _c2, _d2; const args = (_a3 = options == null ? void 0 : options.args) != null ? _a3 : void 0; const parser = new Parser(tokenize(s, args), options == null ? void 0 : options.context, { args, mathstyle: (_b3 = options == null ? void 0 : options.mathstyle) != null ? _b3 : "displaystyle", parseMode: (_c2 = options == null ? void 0 : options.parseMode) != null ? _c2 : "math", style: (_d2 = options == null ? void 0 : options.style) != null ? _d2 : {} }); const atoms = []; while (!parser.end()) atoms.push(...parser.scan(() => false)); return atoms; } function validateLatex(s, options) { var _a3; const parser = new Parser(tokenize(s, null), options == null ? void 0 : options.context, { mathstyle: "displaystyle", parseMode: (_a3 = options == null ? void 0 : options.parseMode) != null ? _a3 : "math" }); while (!parser.end()) parser.scan(); return parser.errors; } // src/latex-commands/mhchem.ts var ChemAtom = class _ChemAtom extends Atom { constructor(command, arg) { super({ type: "chem" }, { command, mode: "math" }); const tex = texify.go( mhchemParser.go(arg, command === "\\pu" ? "pu" : "ce"), false ); this.body = parseLatex(tex); this._verbatimLatex = command + "{" + arg + "}"; this.arg = arg; this.captureSelection = true; } static fromJson(json) { return new _ChemAtom(json.command, json.arg); } // We do not allow resetting the verbatimLatex for 'chem' atoms: // once it is set in the ctor, it is immutable. set verbatimLatex(_latex) { } get verbatimLatex() { return this._verbatimLatex; } toJson() { return __spreadProps(__spreadValues({}, super.toJson()), { arg: this.arg }); } render(context) { const box = Atom.createBox(context, this.body, { type: "inner" }); if (this.caret) box.caret = this.caret; return this.bind(context, box); } _serialize(_options) { console.assert(this.verbatimLatex !== void 0); return this.verbatimLatex; } }; defineFunction(["ce", "pu"], "{chemformula:balanced-string}", { createAtom: (options) => { var _a3; return new ChemAtom(options.command, (_a3 = options.args[0]) != null ? _a3 : ""); } }); var mhchemParser = { // // Parses mchem \ce syntax // // Call like // go("H2O"); // go: function(input, stateMachine) { if (!input) { return []; } if (stateMachine === void 0) { stateMachine = "ce"; } var state = "0"; var buffer = {}; buffer["parenthesisLevel"] = 0; input = input.replace(/\n/g, " "); input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); input = input.replace(/[\u2026]/g, "..."); var lastInput; var watchdog = 10; var output = []; while (true) { if (lastInput !== input) { watchdog = 10; lastInput = input; } else { watchdog--; } var machine = mhchemParser.stateMachines[stateMachine]; var t = machine.transitions[state] || machine.transitions["*"]; iterateTransitions: for (var i = 0; i < t.length; i++) { var matches = mhchemParser.patterns.match_(t[i].pattern, input); if (matches) { var task = t[i].task; for (var iA = 0; iA < task.action_.length; iA++) { var o; if (machine.actions[task.action_[iA].type_]) { o = machine.actions[task.action_[iA].type_]( buffer, matches.match_, task.action_[iA].option ); } else if (mhchemParser.actions[task.action_[iA].type_]) { o = mhchemParser.actions[task.action_[iA].type_]( buffer, matches.match_, task.action_[iA].option ); } else { throw [ "MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")" ]; } mhchemParser.concatArray(output, o); } state = task.nextState || state; if (input.length > 0) { if (!task.revisit) { input = matches.remainder; } if (!task.toContinue) { break iterateTransitions; } } else { return output; } } } if (watchdog <= 0) { throw ["MhchemBugU", "mhchem bug U. Please report."]; } } }, concatArray: function(a, b) { if (b) { if (Object.prototype.toString.call(b) === "[object Array]") { for (var iB = 0; iB < b.length; iB++) { a.push(b[iB]); } } else { a.push(b); } } }, patterns: { // // Matching patterns // either regexps or function that return null or {match_:"a", remainder:"bc"} // patterns: { // property names must not look like integers ("2") for correct property traversal order, later on "empty": /^$/, "else": /^./, "else2": /^./, "space": /^\s/, "space A": /^\s(?=[A-Z\\$])/, "space$": /^\s$/, "a-z": /^[a-z]/, "x": /^x/, "x$": /^x$/, "i$": /^i$/, "letters": /^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/, "\\greek": /^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/, "one lowercase latin letter $": /^(?:([a-z])(?:$|[^a-zA-Z]))$/, "$one lowercase latin letter$ $": /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/, "one lowercase greek letter $": /^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/, "digits": /^[0-9]+/, "-9.,9": /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/, "-9.,9 no missing 0": /^[+\-]?[0-9]+(?:[.,][0-9]+)?/, "(-)(9.,9)(e)(99)": function(input) { var m = input.match( /^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:(?:([eE])|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/ ); if (m && m[0]) { return { match_: m.slice(1), remainder: input.substr(m[0].length) }; } return null; }, "(-)(9)^(-9)": function(input) { var m = input.match( /^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/ ); if (m && m[0]) { return { match_: m.slice(1), remainder: input.substr(m[0].length) }; } return null; }, "state of aggregation $": function(input) { var a = mhchemParser.patterns.findObserveGroups( input, "", /^\([a-z]{1,3}(?=[\),])/, ")", "" ); if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) { return a; } var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); if (m) { return { match_: m[0], remainder: input.substr(m[0].length) }; } return null; }, "_{(state of aggregation)}$": /^_\{(\([a-z]{1,3}\))\}/, "{[(": /^(?:\\\{|\[|\()/, ")]}": /^(?:\)|\]|\\\})/, ", ": /^[,;]\s*/, ",": /^[,;]/, ".": /^[.]/, ". ": /^([.\u22C5\u00B7\u2022])\s*/, "...": /^\.\.\.(?=$|[^.])/, "* ": /^([*])\s*/, "^{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "^{", "", "", "}" ); }, "^($...$)": function(input) { return mhchemParser.patterns.findObserveGroups( input, "^", "$", "$", "" ); }, "^a": /^\^([0-9]+|[^\\_])/, "^\\x{}{}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true ); }, "^\\x{}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "^", /^\\[a-zA-Z]+\{/, "}", "" ); }, "^\\x": /^\^(\\[a-zA-Z]+)\s*/, "^(-1)": /^\^(-?\d+)/, "'": /^'/, "_{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "_{", "", "", "}" ); }, "_($...$)": function(input) { return mhchemParser.patterns.findObserveGroups( input, "_", "$", "$", "" ); }, "_9": /^_([+\-]?[0-9]+|[^\\])/, "_\\x{}{}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true ); }, "_\\x{}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "_", /^\\[a-zA-Z]+\{/, "}", "" ); }, "_\\x": /^_(\\[a-zA-Z]+)\s*/, "^_": /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/, "{}": /^\{\}/, "{...}": function(input) { return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", ""); }, "{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}"); }, "$...$": function(input) { return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); }, "${(...)}$": function(input) { return mhchemParser.patterns.findObserveGroups( input, "${", "", "", "}$" ); }, "$(...)$": function(input) { return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$"); }, "=<>": /^[=<>]/, "#": /^[#\u2261]/, "+": /^\+/, "-$": /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation "-9": /^-(?=[0-9])/, "- orbital overlap": /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, "-": /^-/, "pm-operator": /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, "operator": /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, "arrowUpDown": /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, "\\bond{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\bond{", "", "", "}" ); }, "->": /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, "CMT": /^[CMT](?=\[)/, "[(...)]": function(input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, "1st-level escape": /^(&|\\\\|\\hline)\s*/, "\\,": /^(?:\\[,\ ;:])/, // \\x - but output no space before "\\x{}{}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true ); }, "\\x{}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "", /^\\[a-zA-Z]+\{/, "}", "" ); }, "\\ca": /^\\ca(?:\s+|(?![a-zA-Z]))/, "\\x": /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, "orbital": /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway "others": /^[\/~|]/, "\\frac{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\frac{", "", "", "}", "{", "", "", "}" ); }, "\\overset{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\overset{", "", "", "}", "{", "", "", "}" ); }, "\\underset{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\underset{", "", "", "}", "{", "", "", "}" ); }, "\\underbrace{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\underbrace{", "", "", "}_", "{", "", "", "}" ); }, "\\color{(...)}0": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\color{", "", "", "}" ); }, "\\color{(...)}{(...)}1": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\color{", "", "", "}", "{", "", "", "}" ); }, "\\color(...){(...)}2": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}" ); }, "\\ce{(...)}": function(input) { return mhchemParser.patterns.findObserveGroups( input, "\\ce{", "", "", "}" ); }, "oxidation$": /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, "d-oxidation$": /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge "roman numeral": /^[IVX]+/, "1/2$": /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, "amount": function(input) { var match; match = input.match( /^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/ ); if (match) { return { match_: match[0], remainder: input.substr(match[0].length) }; } var a = mhchemParser.patterns.findObserveGroups( input, "", "$", "$", "" ); if (a) { match = a.match_.match( /^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/ ); if (match) { return { match_: match[0], remainder: input.substr(match[0].length) }; } } return null; }, "amount2": function(input) { return this["amount"](input); }, "(KV letters),": /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, "formula$": function(input) { if (input.match(/^\([a-z]+\)$/)) { return null; } var match = input.match( /^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/ ); if (match) { return { match_: match[0], remainder: input.substr(match[0].length) }; } return null; }, "uprightEntities": /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, "/": /^\s*(\/)\s*/, "//": /^\s*(\/\/)\s*/, "*": /^\s*[*.]\s*/ }, findObserveGroups: function(input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { var _match = function(input2, pattern) { if (typeof pattern === "string") { if (input2.indexOf(pattern) !== 0) { return null; } return pattern; } else { var match2 = input2.match(pattern); if (!match2) { return null; } return match2[0]; } }; var _findObserveGroups = function(input2, i, endChars) { var braces = 0; while (i < input2.length) { var a = input2.charAt(i); var match2 = _match(input2.substr(i), endChars); if (match2 !== null && braces === 0) { return { endMatchBegin: i, endMatchEnd: i + match2.length }; } else if (a === "{") { braces++; } else if (a === "}") { if (braces === 0) { throw [ "ExtraCloseMissingOpen", "Extra close brace or missing open brace" ]; } else { braces--; } } i++; } if (braces > 0) { return null; } return null; }; var match = _match(input, begExcl); if (match === null) { return null; } input = input.substr(match.length); match = _match(input, begIncl); if (match === null) { return null; } var e = _findObserveGroups(input, match.length, endIncl || endExcl); if (e === null) { return null; } var match1 = input.substring( 0, endIncl ? e.endMatchEnd : e.endMatchBegin ); if (!(beg2Excl || beg2Incl)) { return { match_: match1, remainder: input.substr(e.endMatchEnd) }; } else { var group2 = this.findObserveGroups( input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl ); if (group2 === null) { return null; } var matchRet = [match1, group2.match_]; return { match_: combine ? matchRet.join("") : matchRet, remainder: group2.remainder }; } }, // // Matching function // e.g. match("a", input) will look for the regexp called "a" and see if it matches // returns null or {match_:"a", remainder:"bc"} // match_: function(m, input) { var pattern = mhchemParser.patterns.patterns[m]; if (pattern === void 0) { throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; } else if (typeof pattern === "function") { return mhchemParser.patterns.patterns[m](input); } else { var match = input.match(pattern); if (match) { var mm; if (match[2]) { mm = [match[1], match[2]]; } else if (match[1]) { mm = match[1]; } else { mm = match[0]; } return { match_: mm, remainder: input.substr(match[0].length) }; } return null; } } }, // // Generic state machine actions // actions: { "a=": function(buffer, m) { buffer.a = (buffer.a || "") + m; }, "b=": function(buffer, m) { buffer.b = (buffer.b || "") + m; }, "p=": function(buffer, m) { buffer.p = (buffer.p || "") + m; }, "o=": function(buffer, m) { buffer.o = (buffer.o || "") + m; }, "q=": function(buffer, m) { buffer.q = (buffer.q || "") + m; }, "d=": function(buffer, m) { buffer.d = (buffer.d || "") + m; }, "rm=": function(buffer, m) { buffer.rm = (buffer.rm || "") + m; }, "text=": function(buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, "insert": function(buffer, m, a) { return { type_: a }; }, "insert+p1": function(buffer, m, a) { return { type_: a, p1: m }; }, "insert+p1+p2": function(buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, "copy": function(buffer, m) { return m; }, "rm": function(buffer, m) { return { type_: "rm", p1: m || "" }; }, "text": function(buffer, m) { return mhchemParser.go(m, "text"); }, "{text}": function(buffer, m) { var ret = ["{"]; mhchemParser.concatArray(ret, mhchemParser.go(m, "text")); ret.push("}"); return ret; }, "tex-math": function(buffer, m) { return mhchemParser.go(m, "tex-math"); }, "tex-math tight": function(buffer, m) { return mhchemParser.go(m, "tex-math tight"); }, "bond": function(buffer, m, k) { return { type_: "bond", kind_: k || m }; }, "color0-output": function(buffer, m) { return { type_: "color0", color: m[0] }; }, "ce": function(buffer, m) { return mhchemParser.go(m); }, "1/2": function(buffer, m) { var ret = []; if (m.match(/^[+\-]/)) { ret.push(m.substr(0, 1)); m = m.substr(1); } var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); n[1] = n[1].replace(/\$/g, ""); ret.push({ type_: "frac", p1: n[1], p2: n[2] }); if (n[3]) { n[3] = n[3].replace(/\$/g, ""); ret.push({ type_: "tex-math", p1: n[3] }); } return ret; }, "9,9": function(buffer, m) { return mhchemParser.go(m, "9,9"); } }, // // createTransitions // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } // with expansion of 'a|b' to 'a' and 'b' (at 2 places) // createTransitions: function(o) { var pattern, state; var stateArray; var i; var transitions = {}; for (pattern in o) { for (state in o[pattern]) { stateArray = state.split("|"); o[pattern][state].stateArray = stateArray; for (i = 0; i < stateArray.length; i++) { transitions[stateArray[i]] = []; } } } for (pattern in o) { for (state in o[pattern]) { stateArray = o[pattern][state].stateArray || []; for (i = 0; i < stateArray.length; i++) { var p = o[pattern][state]; if (p.action_) { p.action_ = [].concat(p.action_); for (var k = 0; k < p.action_.length; k++) { if (typeof p.action_[k] === "string") { p.action_[k] = { type_: p.action_[k] }; } } } else { p.action_ = []; } var patternArray = pattern.split("|"); for (var j = 0; j < patternArray.length; j++) { if (stateArray[i] === "*") { for (var t in transitions) { transitions[t].push({ pattern: patternArray[j], task: p }); } } else { transitions[stateArray[i]].push({ pattern: patternArray[j], task: p }); } } } } } return transitions; }, stateMachines: {} }; mhchemParser.stateMachines = { // // \ce state machines // //#region ce "ce": { // main parser transitions: mhchemParser.createTransitions({ "empty": { "*": { action_: "output" } }, "else": { "0|1|2": { action_: "beginsWithBond=false", revisit: true, toContinue: true } }, "oxidation$": { "0": { action_: "oxidation-output" } }, "CMT": { r: { action_: "rdt=", nextState: "rt" }, rd: { action_: "rqt=", nextState: "rdt" } }, "arrowUpDown": { "0|1|2|as": { action_: ["sb=false", "output", "operator"], nextState: "1" } }, "uprightEntities": { "0|1|2": { action_: ["o=", "output"], nextState: "1" } }, "orbital": { "0|1|2|3": { action_: "o=", nextState: "o" } }, "->": { "0|1|2|3": { action_: "r=", nextState: "r" }, "a|as": { action_: ["output", "r="], nextState: "r" }, "*": { action_: ["output", "r="], nextState: "r" } }, "+": { "o": { action_: "d= kv", nextState: "d" }, "d|D": { action_: "d=", nextState: "d" }, "q": { action_: "d=", nextState: "qd" }, "qd|qD": { action_: "d=", nextState: "qd" }, "dq": { action_: ["output", "d="], nextState: "d" }, "3": { action_: ["sb=false", "output", "operator"], nextState: "0" } }, "amount": { "0|2": { action_: "a=", nextState: "a" } }, "pm-operator": { "0|1|2|a|as": { action_: [ "sb=false", "output", { type_: "operator", option: "\\pm" } ], nextState: "0" } }, "operator": { "0|1|2|a|as": { action_: ["sb=false", "output", "operator"], nextState: "0" } }, "-$": { "o|q": { action_: ["charge or bond", "output"], nextState: "qd" }, "d": { action_: "d=", nextState: "d" }, "D": { action_: ["output", { type_: "bond", option: "-" }], nextState: "3" }, "q": { action_: "d=", nextState: "qd" }, "qd": { action_: "d=", nextState: "qd" }, "qD|dq": { action_: ["output", { type_: "bond", option: "-" }], nextState: "3" } }, "-9": { "3|o": { action_: ["output", { type_: "insert", option: "hyphen" }], nextState: "3" } }, "- orbital overlap": { o: { action_: ["output", { type_: "insert", option: "hyphen" }], nextState: "2" }, d: { action_: ["output", { type_: "insert", option: "hyphen" }], nextState: "2" } }, "-": { "0|1|2": { action_: [ { type_: "output", option: 1 }, "beginsWithBond=true", { type_: "bond", option: "-" } ], nextState: "3" }, "3": { action_: { type_: "bond", option: "-" } }, "a": { action_: ["output", { type_: "insert", option: "hyphen" }], nextState: "2" }, "as": { action_: [ { type_: "output", option: 2 }, { type_: "bond", option: "-" } ], nextState: "3" }, "b": { action_: "b=" }, "o": { action_: { type_: "- after o/d", option: false }, nextState: "2" }, "q": { action_: { type_: "- after o/d", option: false }, nextState: "2" }, "d|qd|dq": { action_: { type_: "- after o/d", option: true }, nextState: "2" }, "D|qD|p": { action_: ["output", { type_: "bond", option: "-" }], nextState: "3" } }, "amount2": { "1|3": { action_: "a=", nextState: "a" } }, "letters": { "0|1|2|3|a|as|b|p|bp|o": { action_: "o=", nextState: "o" }, "q|dq": { action_: ["output", "o="], nextState: "o" }, "d|D|qd|qD": { action_: "o after d", nextState: "o" } }, "digits": { "o": { action_: "q=", nextState: "q" }, "d|D": { action_: "q=", nextState: "dq" }, "q": { action_: ["output", "o="], nextState: "o" }, "a": { action_: "o=", nextState: "o" } }, "space A": { "b|p|bp": {} }, "space": { "a": { nextState: "as" }, "0": { action_: "sb=false" }, "1|2": { action_: "sb=true" }, "r|rt|rd|rdt|rdq": { action_: "output", nextState: "0" }, "*": { action_: ["output", "sb=true"], nextState: "1" } }, "1st-level escape": { "1|2": { action_: [ "output", { type_: "insert+p1", option: "1st-level escape" } ] }, "*": { action_: [ "output", { type_: "insert+p1", option: "1st-level escape" } ], nextState: "0" } }, "[(...)]": { "r|rt": { action_: "rd=", nextState: "rd" }, "rd|rdt": { action_: "rq=", nextState: "rdq" } }, "...": { "o|d|D|dq|qd|qD": { action_: ["output", { type_: "bond", option: "..." }], nextState: "3" }, "*": { action_: [ { type_: "output", option: 1 }, { type_: "insert", option: "ellipsis" } ], nextState: "1" } }, ". |* ": { "*": { action_: ["output", { type_: "insert", option: "addition compound" }], nextState: "1" } }, "state of aggregation $": { "*": { action_: ["output", "state of aggregation"], nextState: "1" } }, "{[(": { "a|as|o": { action_: ["o=", "output", "parenthesisLevel++"], nextState: "2" }, "0|1|2|3": { action_: ["o=", "output", "parenthesisLevel++"], nextState: "2" }, "*": { action_: ["output", "o=", "output", "parenthesisLevel++"], nextState: "2" } }, ")]}": { "0|1|2|3|b|p|bp|o": { action_: ["o=", "parenthesisLevel--"], nextState: "o" }, "a|as|d|D|q|qd|qD|dq": { action_: ["output", "o=", "parenthesisLevel--"], nextState: "o" } }, ", ": { "*": { action_: ["output", "comma"], nextState: "0" } }, "^_": { // ^ and _ without a sensible argument "*": {} }, "^{(...)}|^($...$)": { "0|1|2|as": { action_: "b=", nextState: "b" }, "p": { action_: "b=", nextState: "bp" }, "3|o": { action_: "d= kv", nextState: "D" }, "q": { action_: "d=", nextState: "qD" }, "d|D|qd|qD|dq": { action_: ["output", "d="], nextState: "D" } }, "^a|^\\x{}{}|^\\x{}|^\\x|'": { "0|1|2|as": { action_: "b=", nextState: "b" }, "p": { action_: "b=", nextState: "bp" }, "3|o": { action_: "d= kv", nextState: "d" }, "q": { action_: "d=", nextState: "qd" }, "d|qd|D|qD": { action_: "d=" }, "dq": { action_: ["output", "d="], nextState: "d" } }, "_{(state of aggregation)}$": { "d|D|q|qd|qD|dq": { action_: ["output", "q="], nextState: "q" } }, "_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x": { "0|1|2|as": { action_: "p=", nextState: "p" }, "b": { action_: "p=", nextState: "bp" }, "3|o": { action_: "q=", nextState: "q" }, "d|D": { action_: "q=", nextState: "dq" }, "q|qd|qD|dq": { action_: ["output", "q="], nextState: "q" } }, "=<>": { "0|1|2|3|a|as|o|q|d|D|qd|qD|dq": { action_: [{ type_: "output", option: 2 }, "bond"], nextState: "3" } }, "#": { "0|1|2|3|a|as|o": { action_: [ { type_: "output", option: 2 }, { type_: "bond", option: "#" } ], nextState: "3" } }, "{}": { "*": { action_: { type_: "output", option: 1 }, nextState: "1" } }, "{...}": { "0|1|2|3|a|as|b|p|bp": { action_: "o=", nextState: "o" }, "o|d|D|q|qd|qD|dq": { action_: ["output", "o="], nextState: "o" } }, "$...$": { "a": { action_: "a=" }, // 2$n$ "0|1|2|3|as|b|p|bp|o": { action_: "o=", nextState: "o" }, // not 'amount' "as|o": { action_: "o=" }, "q|d|D|qd|qD|dq": { action_: ["output", "o="], nextState: "o" } }, "\\bond{(...)}": { "*": { action_: [{ type_: "output", option: 2 }, "bond"], nextState: "3" } }, "\\frac{(...)}": { "*": { action_: [{ type_: "output", option: 1 }, "frac-output"], nextState: "3" } }, "\\overset{(...)}": { "*": { action_: [{ type_: "output", option: 2 }, "overset-output"], nextState: "3" } }, "\\underset{(...)}": { "*": { action_: [{ type_: "output", option: 2 }, "underset-output"], nextState: "3" } }, "\\underbrace{(...)}": { "*": { action_: [{ type_: "output", option: 2 }, "underbrace-output"], nextState: "3" } }, "\\color{(...)}{(...)}1|\\color(...){(...)}2": { "*": { action_: [{ type_: "output", option: 2 }, "color-output"], nextState: "3" } }, "\\color{(...)}0": { "*": { action_: [{ type_: "output", option: 2 }, "color0-output"] } }, "\\ce{(...)}": { "*": { action_: [{ type_: "output", option: 2 }, "ce"], nextState: "3" } }, "\\,": { "*": { action_: [{ type_: "output", option: 1 }, "copy"], nextState: "1" } }, "\\x{}{}|\\x{}|\\x": { "0|1|2|3|a|as|b|p|bp|o|c0": { action_: ["o=", "output"], nextState: "3" }, "*": { action_: ["output", "o=", "output"], nextState: "3" } }, "others": { "*": { action_: [{ type_: "output", option: 1 }, "copy"], nextState: "3" } }, "else2": { "a": { action_: "a to o", nextState: "o", revisit: true }, "as": { action_: ["output", "sb=true"], nextState: "1", revisit: true }, "r|rt|rd|rdt|rdq": { action_: ["output"], nextState: "0", revisit: true }, "*": { action_: ["output", "copy"], nextState: "3" } } }), actions: { "o after d": function(buffer, m) { var ret; if ((buffer.d || "").match(/^[0-9]+$/)) { var tmp = buffer.d; buffer.d = void 0; ret = this["output"](buffer); buffer.b = tmp; } else { ret = this["output"](buffer); } mhchemParser.actions["o="](buffer, m); return ret; }, "d= kv": function(buffer, m) { buffer.d = m; buffer.dType = "kv"; }, "charge or bond": function(buffer, m) { if (buffer["beginsWithBond"]) { var ret = []; mhchemParser.concatArray(ret, this["output"](buffer)); mhchemParser.concatArray( ret, mhchemParser.actions["bond"](buffer, m, "-") ); return ret; } else { buffer.d = m; } }, "- after o/d": function(buffer, m, isAfterD) { var c1 = mhchemParser.patterns.match_("orbital", buffer.o || ""); var c2 = mhchemParser.patterns.match_( "one lowercase greek letter $", buffer.o || "" ); var c3 = mhchemParser.patterns.match_( "one lowercase latin letter $", buffer.o || "" ); var c4 = mhchemParser.patterns.match_( "$one lowercase latin letter$ $", buffer.o || "" ); var hyphenFollows = m === "-" && (c1 && c1.remainder === "" || c2 || c3 || c4); if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { buffer.o = "$" + buffer.o + "$"; } var ret = []; if (hyphenFollows) { mhchemParser.concatArray(ret, this["output"](buffer)); ret.push({ type_: "hyphen" }); } else { c1 = mhchemParser.patterns.match_("digits", buffer.d || ""); if (isAfterD && c1 && c1.remainder === "") { mhchemParser.concatArray( ret, mhchemParser.actions["d="](buffer, m) ); mhchemParser.concatArray(ret, this["output"](buffer)); } else { mhchemParser.concatArray(ret, this["output"](buffer)); mhchemParser.concatArray( ret, mhchemParser.actions["bond"](buffer, m, "-") ); } } return ret; }, "a to o": function(buffer) { buffer.o = buffer.a; buffer.a = void 0; }, "sb=true": function(buffer) { buffer.sb = true; }, "sb=false": function(buffer) { buffer.sb = false; }, "beginsWithBond=true": function(buffer) { buffer["beginsWithBond"] = true; }, "beginsWithBond=false": function(buffer) { buffer["beginsWithBond"] = false; }, "parenthesisLevel++": function(buffer) { buffer["parenthesisLevel"]++; }, "parenthesisLevel--": function(buffer) { buffer["parenthesisLevel"]--; }, "state of aggregation": function(buffer, m) { return { type_: "state of aggregation", p1: mhchemParser.go(m, "o") }; }, "comma": function(buffer, m) { var a = m.replace(/\s*$/, ""); var withSpace = a !== m; if (withSpace && buffer["parenthesisLevel"] === 0) { return { type_: "comma enumeration L", p1: a }; } else { return { type_: "comma enumeration M", p1: a }; } }, "output": function(buffer, m, entityFollows) { var ret; if (!buffer.r) { ret = []; if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { } else { if (buffer.sb) { ret.push({ type_: "entitySkip" }); } if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows !== 2) { buffer.o = buffer.a; buffer.a = void 0; } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { buffer.o = buffer.a; buffer.d = buffer.b; buffer.q = buffer.p; buffer.a = buffer.b = buffer.p = void 0; } else { if (buffer.o && buffer.dType === "kv" && mhchemParser.patterns.match_("d-oxidation$", buffer.d || "")) { buffer.dType = "oxidation"; } else if (buffer.o && buffer.dType === "kv" && !buffer.q) { buffer.dType = void 0; } } ret.push({ type_: "chemfive", a: mhchemParser.go(buffer.a, "a"), b: mhchemParser.go(buffer.b, "bd"), p: mhchemParser.go(buffer.p, "pq"), o: mhchemParser.go(buffer.o, "o"), q: mhchemParser.go(buffer.q, "pq"), d: mhchemParser.go( buffer.d, buffer.dType === "oxidation" ? "oxidation" : "bd" ), dType: buffer.dType }); } } else { var rd; if (buffer.rdt === "M") { rd = mhchemParser.go(buffer.rd, "tex-math"); } else if (buffer.rdt === "T") { rd = [{ type_: "text", p1: buffer.rd || "" }]; } else { rd = mhchemParser.go(buffer.rd); } var rq; if (buffer.rqt === "M") { rq = mhchemParser.go(buffer.rq, "tex-math"); } else if (buffer.rqt === "T") { rq = [{ type_: "text", p1: buffer.rq || "" }]; } else { rq = mhchemParser.go(buffer.rq); } ret = { type_: "arrow", r: buffer.r, rd, rq }; } for (var p in buffer) { if (p !== "parenthesisLevel" && p !== "beginsWithBond") { delete buffer[p]; } } return ret; }, "oxidation-output": function(buffer, m) { var ret = ["{"]; mhchemParser.concatArray(ret, mhchemParser.go(m, "oxidation")); ret.push("}"); return ret; }, "frac-output": function(buffer, m) { return { type_: "frac-ce", p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; }, "overset-output": function(buffer, m) { return { type_: "overset", p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; }, "underset-output": function(buffer, m) { return { type_: "underset", p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; }, "underbrace-output": function(buffer, m) { return { type_: "underbrace", p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; }, "color-output": function(buffer, m) { return { type_: "color", color1: m[0], color2: mhchemParser.go(m[1]) }; }, "r=": function(buffer, m) { buffer.r = m; }, "rdt=": function(buffer, m) { buffer.rdt = m; }, "rd=": function(buffer, m) { buffer.rd = m; }, "rqt=": function(buffer, m) { buffer.rqt = m; }, "rq=": function(buffer, m) { buffer.rq = m; }, "operator": function(buffer, m, p1) { return { type_: "operator", kind_: p1 || m }; } } }, "a": { transitions: mhchemParser.createTransitions({ "empty": { "*": {} }, "1/2$": { "0": { action_: "1/2" } }, "else": { "0": { nextState: "1", revisit: true } }, "$(...)$": { "*": { action_: "tex-math tight", nextState: "1" } }, ",": { "*": { action_: { type_: "insert", option: "commaDecimal" } } }, "else2": { "*": { action_: "copy" } } }), actions: {} }, "o": { transitions: mhchemParser.createTransitions({ "empty": { "*": {} }, "1/2$": { "0": { action_: "1/2" } }, "else": { "0": { nextState: "1", revisit: true } }, "letters": { "*": { action_: "rm" } }, "\\ca": { "*": { action_: { type_: "insert", option: "circa" } } }, "\\x{}{}|\\x{}|\\x": { "*": { action_: "copy" } }, "${(...)}$|$(...)$": { "*": { action_: "tex-math" } }, "{(...)}": { "*": { action_: "{text}" } }, "else2": { "*": { action_: "copy" } } }), actions: {} }, "text": { transitions: mhchemParser.createTransitions({ "empty": { "*": { action_: "output" } }, "{...}": { "*": { action_: "text=" } }, "${(...)}$|$(...)$": { "*": { action_: "tex-math" } }, "\\greek": { "*": { action_: ["output", "rm"] } }, "\\,|\\x{}{}|\\x{}|\\x": { "*": { action_: ["output", "copy"] } }, "else": { "*": { action_: "text=" } } }), actions: { output: function(buffer) { if (buffer.text_) { var ret = { type_: "text", p1: buffer.text_ }; for (var p in buffer) { delete buffer[p]; } return ret; } } } }, "pq": { transitions: mhchemParser.createTransitions({ "empty": { "*": {} }, "state of aggregation $": { "*": { action_: "state of aggregation" } }, "i$": { "0": { nextState: "!f", revisit: true } }, "(KV letters),": { "0": { action_: "rm", nextState: "0" } }, "formula$": { "0": { nextState: "f", revisit: true } }, "1/2$": { "0": { action_: "1/2" } }, "else": { "0": { nextState: "!f", revisit: true } }, "${(...)}$|$(...)$": { "*": { action_: "tex-math" } }, "{(...)}": { "*": { action_: "text" } }, "a-z": { f: { action_: "tex-math" } }, "letters": { "*": { action_: "rm" } }, "-9.,9": { "*": { action_: "9,9" } }, ",": { "*": { action_: { type_: "insert+p1", option: "comma enumeration S" } } }, "\\color{(...)}{(...)}1|\\color(...){(...)}2": { "*": { action_: "color-output" } }, "\\color{(...)}0": { "*": { action_: "color0-output" } }, "\\ce{(...)}": { "*": { action_: "ce" } }, "\\,|\\x{}{}|\\x{}|\\x": { "*": { action_: "copy" } }, "else2": { "*": { action_: "copy" } } }), actions: { "state of aggregation": function(buffer, m) { return { type_: "state of aggregation subscript", p1: mhchemParser.go(m, "o") }; }, "color-output": function(buffer, m) { return { type_: "color", color1: m[0], color2: mhchemParser.go(m[1], "pq") }; } } }, "bd": { transitions: mhchemParser.createTransitions({ "empty": { "*": {} }, "x$": { "0": { nextState: "!f", revisit: true } }, "formula$": { "0": { nextState: "f", revisit: true } }, "else": { "0": { nextState: "!f", revisit: true } }, "-9.,9 no missing 0": { "*": { action_: "9,9" } }, ".": { "*": { action_: { type_: "insert", option: "electron dot" } } }, "a-z": { f: { action_: "tex-math" } }, "x": { "*": { action_: { type_: "insert", option: "KV x" } } }, "letters": { "*": { action_: "rm" } }, "'": { "*": { action_: { type_: "insert", option: "prime" } } }, "${(...)}$|$(...)$": { "*": { action_: "tex-math" } }, "{(...)}": { "*": { action_: "text" } }, "\\color{(...)}{(...)}1|\\color(...){(...)}2": { "*": { action_: "color-output" } }, "\\color{(...)}0": { "*": { action_: "color0-output" } }, "\\ce{(...)}": { "*": { action_: "ce" } }, "\\,|\\x{}{}|\\x{}|\\x": { "*": { action_: "copy" } }, "else2": { "*": { action_: "copy" } } }), actions: { "color-output": function(buffer, m) { return { type_: "color", color1: m[0], color2: mhchemParser.go(m[1], "bd") }; } } }, "oxidation": { transitions: mhchemParser.createTransitions({ "empty": { "*": {} }, "roman numeral": { "*": { action_: "roman-numeral" } }, "${(...)}$|$(...)$": { "*": { action_: "tex-math" } }, "else": { "*": { action_: "copy" } } }), actions: { "roman-numeral": function(buffer, m) { return { type_: "roman numeral", p1: m || "" }; } } }, "tex-math": { transitions: mhchemParser.createTransitions({ "empty": { "*": { action_: "output" } }, "\\ce{(...)}": { "*": { action_: ["output", "ce"] } }, "{...}|\\,|\\x{}{}|\\x{}|\\x": { "*": { action_: "o=" } }, "else": { "*": { action_: "o=" } } }), actions: { output: function(buffer) { if (buffer.o) { var ret = { type_: "tex-math", p1: buffer.o }; for (var p in buffer) { delete buffer[p]; } return ret; } } } }, "tex-math tight": { transitions: mhchemParser.createTransitions({ "empty": { "*": { action_: "output" } }, "\\ce{(...)}": { "*": { action_: ["output", "ce"] } }, "{...}|\\,|\\x{}{}|\\x{}|\\x": { "*": { action_: "o=" } }, "-|+": { "*": { action_: "tight operator" } }, "else": { "*": { action_: "o=" } } }), actions: { "tight operator": function(buffer, m) { buffer.o = (buffer.o || "") + "{" + m + "}"; }, "output": function(buffer) { if (buffer.o) { var ret = { type_: "tex-math", p1: buffer.o }; for (var p in buffer) { delete buffer[p]; } return ret; } } } }, "9,9": { transitions: mhchemParser.createTransitions({ "empty": { "*": {} }, ",": { "*": { action_: "comma" } }, "else": { "*": { action_: "copy" } } }), actions: { comma: function() { return { type_: "commaDecimal" }; } } }, //#endregion // // \pu state machines // //#region pu "pu": { transitions: mhchemParser.createTransitions({ "empty": { "*": { action_: "output" } }, "space$": { "*": { action_: ["output", "space"] } }, "{[(|)]}": { "0|a": { action_: "copy" } }, "(-)(9)^(-9)": { "0": { action_: "number^", nextState: "a" } }, "(-)(9.,9)(e)(99)": { "0": { action_: "enumber", nextState: "a" } }, "space": { "0|a": {} }, "pm-operator": { "0|a": { action_: { type_: "operator", option: "\\pm" }, nextState: "0" } }, "operator": { "0|a": { action_: "copy", nextState: "0" } }, "//": { d: { action_: "o=", nextState: "/" } }, "/": { d: { action_: "o=", nextState: "/" } }, "{...}|else": { "0|d": { action_: "d=", nextState: "d" }, "a": { action_: ["space", "d="], nextState: "d" }, "/|q": { action_: "q=", nextState: "q" } } }), actions: { "enumber": function(buffer, m) { var ret = []; if (m[0] === "+-" || m[0] === "+/-") { ret.push("\\pm "); } else if (m[0]) { ret.push(m[0]); } if (m[1]) { mhchemParser.concatArray(ret, mhchemParser.go(m[1], "pu-9,9")); if (m[2]) { if (m[2].match(/[,.]/)) { mhchemParser.concatArray(ret, mhchemParser.go(m[2], "pu-9,9")); } else { ret.push(m[2]); } } if (m[3] || m[4]) { if (m[3] === "e" || m[4] === "*") { ret.push({ type_: "cdot" }); } else { ret.push({ type_: "times" }); } } } if (m[5]) { ret.push("10^{" + m[5] + "}"); } return ret; }, "number^": function(buffer, m) { var ret = []; if (m[0] === "+-" || m[0] === "+/-") { ret.push("\\pm "); } else if (m[0]) { ret.push(m[0]); } mhchemParser.concatArray(ret, mhchemParser.go(m[1], "pu-9,9")); ret.push("^{" + m[2] + "}"); return ret; }, "operator": function(buffer, m, p1) { return { type_: "operator", kind_: p1 || m }; }, "space": function() { return { type_: "pu-space-1" }; }, "output": function(buffer) { var ret; var md = mhchemParser.patterns.match_("{(...)}", buffer.d || ""); if (md && md.remainder === "") { buffer.d = md.match_; } var mq = mhchemParser.patterns.match_("{(...)}", buffer.q || ""); if (mq && mq.remainder === "") { buffer.q = mq.match_; } if (buffer.d) { buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); } if (buffer.q) { buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); var b5 = { d: mhchemParser.go(buffer.d, "pu"), q: mhchemParser.go(buffer.q, "pu") }; if (buffer.o === "//") { ret = { type_: "pu-frac", p1: b5.d, p2: b5.q }; } else { ret = b5.d; if (b5.d.length > 1 || b5.q.length > 1) { ret.push({ type_: " / " }); } else { ret.push({ type_: "/" }); } mhchemParser.concatArray(ret, b5.q); } } else { ret = mhchemParser.go(buffer.d, "pu-2"); } for (var p in buffer) { delete buffer[p]; } return ret; } } }, "pu-2": { transitions: mhchemParser.createTransitions({ "empty": { "*": { action_: "output" } }, "*": { "*": { action_: ["output", "cdot"], nextState: "0" } }, "\\x": { "*": { action_: "rm=" } }, "space": { "*": { action_: ["output", "space"], nextState: "0" } }, "^{(...)}|^(-1)": { "1": { action_: "^(-1)" } }, "-9.,9": { "0": { action_: "rm=", nextState: "0" }, "1": { action_: "^(-1)", nextState: "0" } }, "{...}|else": { "*": { action_: "rm=", nextState: "1" } } }), actions: { "cdot": function() { return { type_: "tight cdot" }; }, "^(-1)": function(buffer, m) { buffer.rm += "^{" + m + "}"; }, "space": function() { return { type_: "pu-space-2" }; }, "output": function(buffer) { var ret = []; if (buffer.rm) { var mrm = mhchemParser.patterns.match_("{(...)}", buffer.rm || ""); if (mrm && mrm.remainder === "") { ret = mhchemParser.go(mrm.match_, "pu"); } else { ret = { type_: "rm", p1: buffer.rm }; } } for (var p in buffer) { delete buffer[p]; } return ret; } } }, "pu-9,9": { transitions: mhchemParser.createTransitions({ "empty": { "0": { action_: "output-0" }, "o": { action_: "output-o" } }, ",": { "0": { action_: ["output-0", "comma"], nextState: "o" } }, ".": { "0": { action_: ["output-0", "copy"], nextState: "o" } }, "else": { "*": { action_: "text=" } } }), actions: { "comma": function() { return { type_: "commaDecimal" }; }, "output-0": function(buffer) { var ret = []; buffer.text_ = buffer.text_ || ""; if (buffer.text_.length > 4) { var a = buffer.text_.length % 3; if (a === 0) { a = 3; } for (var i = buffer.text_.length - 3; i > 0; i -= 3) { ret.push(buffer.text_.substr(i, 3)); ret.push({ type_: "1000 separator" }); } ret.push(buffer.text_.substr(0, a)); ret.reverse(); } else { ret.push(buffer.text_); } for (var p in buffer) { delete buffer[p]; } return ret; }, "output-o": function(buffer) { var ret = []; buffer.text_ = buffer.text_ || ""; if (buffer.text_.length > 4) { var a = buffer.text_.length - 3; for (var i = 0; i < a; i += 3) { ret.push(buffer.text_.substr(i, 3)); ret.push({ type_: "1000 separator" }); } ret.push(buffer.text_.substr(i)); } else { ret.push(buffer.text_); } for (var p in buffer) { delete buffer[p]; } return ret; } } } //#endregion }; var texify = { go: function(input, isInner) { if (!input) { return ""; } var res = ""; var cee = false; for (var i = 0; i < input.length; i++) { var inputi = input[i]; if (typeof inputi === "string") { res += inputi; } else { res += texify._go2(inputi); if (inputi.type_ === "1st-level escape") { cee = true; } } } if (!isInner && !cee && res) { res = "{" + res + "}"; } return res; }, _goInner: function(input) { if (!input) { return input; } return texify.go(input, true); }, _go2: function(buf) { var res; switch (buf.type_) { case "chemfive": res = ""; var b5 = { a: texify._goInner(buf.a), b: texify._goInner(buf.b), p: texify._goInner(buf.p), o: texify._goInner(buf.o), q: texify._goInner(buf.q), d: texify._goInner(buf.d) }; if (b5.a) { if (b5.a.match(/^[+\-]/)) { b5.a = "{" + b5.a + "}"; } res += b5.a + "\\,"; } if (b5.b || b5.p) { res += "{\\vphantom{X}}"; res += "^{\\hphantom{" + (b5.b || "") + "}}_{\\hphantom{" + (b5.p || "") + "}}"; res += "{\\vphantom{X}}"; res += "^{\\smash[t]{\\vphantom{2}}\\llap{" + (b5.b || "") + "}}"; res += "_{\\vphantom{2}\\llap{\\smash[t]{" + (b5.p || "") + "}}}"; } if (b5.o) { if (b5.o.match(/^[+\-]/)) { b5.o = "{" + b5.o + "}"; } res += b5.o; } if (buf.dType === "kv") { if (b5.d || b5.q) { res += "{\\vphantom{X}}"; } if (b5.d) { res += "^{" + b5.d + "}"; } if (b5.q) { res += "_{\\smash[t]{" + b5.q + "}}"; } } else if (buf.dType === "oxidation") { if (b5.d) { res += "{\\vphantom{X}}"; res += "^{" + b5.d + "}"; } if (b5.q) { res += "{\\vphantom{X}}"; res += "_{\\smash[t]{" + b5.q + "}}"; } } else { if (b5.q) { res += "{\\vphantom{X}}"; res += "_{\\smash[t]{" + b5.q + "}}"; } if (b5.d) { res += "{\\vphantom{X}}"; res += "^{" + b5.d + "}"; } } break; case "rm": res = "\\mathrm{" + buf.p1 + "}"; break; case "text": if (buf.p1.match(/[\^_]/)) { buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); res = "\\mathrm{" + buf.p1 + "}"; } else { res = "\\text{" + buf.p1 + "}"; } break; case "roman numeral": res = "\\mathrm{" + buf.p1 + "}"; break; case "state of aggregation": res = "\\mskip2mu " + texify._goInner(buf.p1); break; case "state of aggregation subscript": res = "\\mskip1mu " + texify._goInner(buf.p1); break; case "bond": res = texify._getBond(buf.kind_); if (!res) { throw [ "MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")" ]; } break; case "frac": var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; res = "\\mathchoice{\\textstyle" + c + "}{" + c + "}{" + c + "}{" + c + "}"; break; case "pu-frac": var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; res = "\\mathchoice{\\textstyle" + d + "}{" + d + "}{" + d + "}{" + d + "}"; break; case "tex-math": res = buf.p1 + " "; break; case "frac-ce": res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; break; case "overset": res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; break; case "underset": res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; break; case "underbrace": res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; break; case "color": res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; break; case "color0": res = "\\color{" + buf.color + "}"; break; case "arrow": var b6 = { rd: texify._goInner(buf.rd), rq: texify._goInner(buf.rq) }; var arrow = texify._getArrow(buf.r); if (b6.rd || b6.rq) { if (buf.r === "<=>" || buf.r === "<=>>" || buf.r === "<<=>" || buf.r === "<-->") { arrow = "\\long" + arrow; if (b6.rd) { arrow = "\\overset{" + b6.rd + "}{" + arrow + "}"; } if (b6.rq) { if (buf.r === "<-->") { arrow = "\\underset{\\lower2mu{" + b6.rq + "}}{" + arrow + "}"; } else { arrow = "\\underset{\\lower6mu{" + b6.rq + "}}{" + arrow + "}"; } } arrow = " {}\\mathrel{" + arrow + "}{} "; } else { if (b6.rq) { arrow += "[{" + b6.rq + "}]"; } arrow += "{" + b6.rd + "}"; arrow = " {}\\mathrel{\\x" + arrow + "}{} "; } } else { arrow = " {}\\mathrel{\\long" + arrow + "}{} "; } res = arrow; break; case "operator": res = texify._getOperator(buf.kind_); break; case "1st-level escape": res = buf.p1 + " "; break; case "space": res = " "; break; case "entitySkip": res = "~"; break; case "pu-space-1": res = "~"; break; case "pu-space-2": res = "\\mkern3mu "; break; case "1000 separator": res = "\\mkern2mu "; break; case "commaDecimal": res = "{,}"; break; case "comma enumeration L": res = "{" + buf.p1 + "}\\mkern6mu "; break; case "comma enumeration M": res = "{" + buf.p1 + "}\\mkern3mu "; break; case "comma enumeration S": res = "{" + buf.p1 + "}\\mkern1mu "; break; case "hyphen": res = "\\text{-}"; break; case "addition compound": res = "\\,{\\cdot}\\,"; break; case "electron dot": res = "\\mkern1mu \\bullet\\mkern1mu "; break; case "KV x": res = "{\\times}"; break; case "prime": res = "\\prime "; break; case "cdot": res = "\\cdot "; break; case "tight cdot": res = "\\mkern1mu{\\cdot}\\mkern1mu "; break; case "times": res = "\\times "; break; case "circa": res = "{\\sim}"; break; case "^": res = "uparrow"; break; case "v": res = "downarrow"; break; case "ellipsis": res = "\\ldots "; break; case "/": res = "/"; break; case " / ": res = "\\,/\\,"; break; default: assertNever(buf); throw ["MhchemBugT", "mhchem bug T. Please report."]; } assertString(res); return res; }, _getArrow: function(a) { switch (a) { case "->": return "rightarrow"; case "\u2192": return "rightarrow"; case "\u27F6": return "rightarrow"; case "<-": return "leftarrow"; case "<->": return "leftrightarrow"; case "<-->": return "leftrightarrows"; case "<=>": return "rightleftharpoons"; case "\u21CC": return "rightleftharpoons"; case "<=>>": return "Rightleftharpoons"; case "<<=>": return "Leftrightharpoons"; default: assertNever(a); throw ["MhchemBugT", "mhchem bug T. Please report."]; } }, _getBond: function(a) { switch (a) { case "-": return "{-}"; case "1": return "{-}"; case "=": return "{=}"; case "2": return "{=}"; case "#": return "{\\equiv}"; case "3": return "{\\equiv}"; case "~": return "{\\tripledash}"; case "~-": return "{\\rlap{\\lower.1em{-}}\\raise.1em{\\tripledash}}"; case "~=": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}"; case "~--": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}"; case "-~-": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{-}}\\tripledash}"; case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; case "->": return "{\\rightarrow}"; case "<-": return "{\\leftarrow}"; case "<": return "{<}"; case ">": return "{>}"; default: assertNever(a); throw ["MhchemBugT", "mhchem bug T. Please report."]; } }, _getOperator: function(a) { switch (a) { case "+": return " {}+{} "; case "-": return " {}-{} "; case "=": return " {}={} "; case "<": return " {}<{} "; case ">": return " {}>{} "; case "<<": return " {}\\ll{} "; case ">>": return " {}\\gg{} "; case "\\pm": return " {}\\pm{} "; case "\\approx": return " {}\\approx{} "; case "$\\approx$": return " {}\\approx{} "; case "v": return " \\downarrow{} "; case "(v)": return " \\downarrow{} "; case "^": return " \\uparrow{} "; case "(^)": return " \\uparrow{} "; default: assertNever(a); throw ["MhchemBugT", "mhchem bug T. Please report."]; } } }; function assertNever(a) { } function assertString(a) { } // src/atoms/delim.ts var MiddleDelimAtom = class _MiddleDelimAtom extends Atom { constructor(options) { super(__spreadProps(__spreadValues({}, options), { type: "delim" })); this.value = options.delim; this.size = options.size; } static fromJson(json) { return new _MiddleDelimAtom(json); } toJson() { return __spreadProps(__spreadValues({}, super.toJson()), { delim: this.value, size: this.size }); } render(_context) { return new Box(this.value, { type: "middle" }); } _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); return latexCommand(this.command, this.value); } }; var SizedDelimAtom = class _SizedDelimAtom extends Atom { constructor(options) { super(__spreadProps(__spreadValues({}, options), { type: "sizeddelim", value: options.delim })); this.delimType = options.delimType; this.size = options.size; } static fromJson(json) { return new _SizedDelimAtom(json); } toJson() { return __spreadProps(__spreadValues({}, super.toJson()), { delim: this.value, size: this.size, delimType: this.delimType }); } render(context) { let result = makeSizedDelim(this.value, this.size, context, { classes: { open: "mopen", close: "mclose" }[this.delimType], type: this.delimType, isSelected: this.isSelected }); if (!result) return null; result = this.bind(context, result); if (this.caret) result.caret = this.caret; return result; } _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); return latexCommand(this.command, this.value); } }; // src/atoms/enclose.ts var EncloseAtom = class _EncloseAtom extends Atom { constructor(command, body, notation, options) { var _a3, _b3; super({ type: "enclose", command, style: options.style }); this.body = body; this.backgroundcolor = options.backgroundcolor; if (notation.updiagonalarrow) notation.updiagonalstrike = false; if (notation.box) { notation.left = false; notation.right = false; notation.bottom = false; notation.top = false; } this.notation = notation; this.shadow = (_a3 = options.shadow) != null ? _a3 : "none"; this.strokeWidth = (_b3 = options.strokeWidth) != null ? _b3 : "0.06em"; if (!this.strokeWidth) this.strokeWidth = "0.06em"; this.strokeStyle = options.strokeStyle; this.svgStrokeStyle = options.svgStrokeStyle; this.strokeColor = options.strokeColor; this.borderStyle = options.borderStyle; this.padding = options.padding; this.captureSelection = false; } static fromJson(json) { return new _EncloseAtom( json.command, json.body, json.notation, json ); } toJson() { return __spreadProps(__spreadValues({}, super.toJson()), { notation: this.notation, shadow: this.shadow, strokeWidth: this.strokeWidth, strokeStyle: this.strokeStyle, svgStrokeStyle: this.svgStrokeStyle, strokeColor: this.strokeColor, borderStyle: this.borderStyle, padding: this.padding }); } _serialize(options) { var _a3; if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); let command = (_a3 = this.command) != null ? _a3 : ""; if (this.command === "\\enclose") { command += "{" + Object.keys(this.notation).join(" ") + "}"; let style = ""; let sep = ""; if (this.backgroundcolor && this.backgroundcolor !== "transparent") { style += sep + 'mathbackground="' + this.backgroundcolor + '"'; sep = ","; } if (this.shadow && this.shadow !== "auto") { style += sep + 'shadow="' + this.shadow + '"'; sep = ","; } if (this.strokeWidth || this.strokeStyle !== "solid") { style += sep + this.borderStyle; sep = ","; } else if (this.strokeColor && this.strokeColor !== "currentColor") { style += sep + 'mathcolor="' + this.strokeColor + '"'; sep = ","; } if (style) command += `[${style}]`; } return latexCommand(command, this.bodyToLatex(options)); } render(parentContext) { const context = new Context({ parent: parentContext }, this.style); const base = Atom.createBox(context, this.body); if (!base) return null; const borderWidth = borderDim(this.borderStyle); const padding2 = context.toEm( !this.padding || this.padding === "auto" ? { register: "fboxsep" } : { string: this.padding } ); base.setStyle("position", "relative"); base.setStyle("display", "inline-block"); base.setStyle("top", padding2, "em"); base.setStyle("height", base.height + base.depth, "em"); base.setStyle("width", base.width, "em"); const notation = new Box(null, { classes: "ML__notation" }); let h = base.height + base.depth + 2 * padding2; const w = base.width + 2 * padding2; let svg = ""; if (this.notation.horizontalstrike) svg += this.line(3, 50, 97, 50); if (this.notation.verticalstrike) svg += this.line(50, 3, 50, 97); if (this.notation.updiagonalstrike) svg += this.line(3, 97, 97, 3); if (this.notation.downdiagonalstrike) svg += this.line(3, 3, 97, 97); if (this.notation.updiagonalarrow) { svg += this.line( padding2.toString(), (padding2 + base.depth + base.height).toString(), (padding2 + base.width).toString(), padding2.toString() ); const t = 1; const length = Math.sqrt(w * w + h * h); const f = 0.03 * length * t; const wf = base.width * f; const hf = (base.depth + base.height) * f; const x = padding2 + base.width; let y = padding2; if (y + hf - 0.4 * wf < 0) y = 0.4 * wf - hf; svg += '`; } }; function coord(c) { if (typeof c === "number") return `${Math.floor(100 * c) / 100}%`; return c; } function borderDim(s) { if (!s) return "1px"; const m = s.match(/([0-9][a-zA-Z\%]+)/); if (m === null) return "1px"; return m[1]; } function getRuleThickness(ctx) { return (Math.floor(100 * ctx.metrics.sqrtRuleThickness / ctx.scalingFactor) / 100 / 10).toString() + "em"; } function getClearance(ctx) { const phi = ctx.isDisplayStyle ? X_HEIGHT : ctx.metrics.defaultRuleThickness; return ctx.metrics.defaultRuleThickness + ctx.scalingFactor * phi / 4; } // src/atoms/genfrac.ts var GenfracAtom = class _GenfracAtom extends Atom { constructor(above, below, options) { var _a3, _b3; super(__spreadProps(__spreadValues({}, options), { type: "genfrac", displayContainsHighlight: true })); this.above = above; this.below = below; this.hasBarLine = (_a3 = options == null ? void 0 : options.hasBarLine) != null ? _a3 : true; this.continuousFraction = (_b3 = options == null ? void 0 : options.continuousFraction) != null ? _b3 : false; this.numerPrefix = options == null ? void 0 : options.numerPrefix; this.denomPrefix = options == null ? void 0 : options.denomPrefix; this.mathstyleName = options == null ? void 0 : options.mathstyleName; this.leftDelim = options == null ? void 0 : options.leftDelim; this.rightDelim = options == null ? void 0 : options.rightDelim; this.fractionNavigationOrder = options == null ? void 0 : options.fractionNavigationOrder; } static fromJson(json) { return new _GenfracAtom( json.above, json.below, json ); } toJson() { const options = {}; if (this.continuousFraction) options.continuousFraction = true; if (this.numerPrefix) options.numerPrefix = this.numerPrefix; if (this.denomPrefix) options.denomPrefix = this.denomPrefix; if (this.leftDelim) options.leftDelim = this.leftDelim; if (this.rightDelim) options.rightDelim = this.rightDelim; if (!this.hasBarLine) options.hasBarLine = false; if (this.mathstyleName) options.mathstyleName = this.mathstyleName; if (this.fractionNavigationOrder) options.fractionNavigationOrder = this.fractionNavigationOrder; return __spreadValues(__spreadValues({}, super.toJson()), options); } // The order of the children, which is used for keyboard navigation order, // may be customized for fractions... get children() { if (this._children) return this._children; const result = []; if (this.fractionNavigationOrder === "denominator-numerator") { for (const x of this.below) { result.push(...x.children); result.push(x); } for (const x of this.above) { result.push(...x.children); result.push(x); } } else { for (const x of this.above) { result.push(...x.children); result.push(x); } for (const x of this.below) { result.push(...x.children); result.push(x); } } this._children = result; return result; } render(context) { var _a3, _b3; const fracContext = new Context( { parent: context, mathstyle: this.mathstyleName }, this.style ); const metrics = fracContext.metrics; const numContext = new Context( { parent: fracContext, mathstyle: this.continuousFraction ? "" : "numerator" }, this.style ); const numerBox = this.numerPrefix ? new Box( [new Box(this.numerPrefix), Atom.createBox(numContext, this.above)], { isTight: numContext.isTight, type: "ignore" } ) : (_a3 = Atom.createBox(numContext, this.above, { type: "ignore" })) != null ? _a3 : new Box(null, { type: "ignore" }); const denomContext = new Context( { parent: fracContext, mathstyle: this.continuousFraction ? "" : "denominator" }, this.style ); const denomBox = this.denomPrefix ? new Box([ new Box(this.denomPrefix), Atom.createBox(denomContext, this.below, { type: "ignore" }) ]) : (_b3 = Atom.createBox(denomContext, this.below, { type: "ignore" })) != null ? _b3 : new Box(null, { type: "ignore" }); const ruleThickness = this.hasBarLine ? metrics.defaultRuleThickness : 0; let numerShift; let clearance = 0; let denomShift; if (fracContext.isDisplayStyle) { numerShift = numContext.metrics.num1; clearance = ruleThickness > 0 ? 3 * ruleThickness : 7 * ruleThickness; denomShift = denomContext.metrics.denom1; } else { if (ruleThickness > 0) { numerShift = numContext.metrics.num2; clearance = ruleThickness; } else { numerShift = numContext.metrics.num3; clearance = 3 * metrics.defaultRuleThickness; } denomShift = denomContext.metrics.denom2; } const classes = []; if (this.isSelected) classes.push("ML__selected"); const numerDepth = numerBox.depth; const denomHeight = denomBox.height; let frac; if (ruleThickness <= 0) { const candidateClearance = numerShift - numerDepth - (denomHeight - denomShift); if (candidateClearance < clearance) { numerShift += (clearance - candidateClearance) / 2; denomShift += (clearance - candidateClearance) / 2; } frac = new VBox({ individualShift: [ { box: numerBox, shift: -numerShift, classes: [...classes, "ML__center"] }, { box: denomBox, shift: denomShift, classes: [...classes, "ML__center"] } ] }).wrap(fracContext); } else { const fracLine = new Box(null, { classes: "ML__frac-line", mode: this.mode, style: this.style }); fracLine.softWidth = Math.max(numerBox.width, denomBox.width); fracLine.height = ruleThickness / 2; fracLine.depth = ruleThickness / 2; const numerLine = AXIS_HEIGHT + ruleThickness / 2; if (numerShift < clearance + numerDepth + numerLine) numerShift = clearance + numerDepth + numerLine; const denomLine = AXIS_HEIGHT - ruleThickness / 2; if (denomShift < clearance + denomHeight - denomLine) denomShift = clearance + denomHeight - denomLine; frac = new VBox({ individualShift: [ { box: denomBox, shift: denomShift, classes: [...classes, "ML__center"] }, { box: fracLine, shift: -denomLine, classes }, { box: numerBox, shift: -numerShift, classes: [...classes, "ML__center"] } ] }).wrap(fracContext); } const delimSize = fracContext.isDisplayStyle ? metrics.delim1 : metrics.delim2; const leftDelim = this.leftDelim ? this.bind( context, makeCustomSizedDelim( "open", this.leftDelim, delimSize, true, context, { style: this.style, mode: this.mode, isSelected: this.isSelected } ) ) : makeNullDelimiter(fracContext, "open"); let rightDelim = null; if (this.continuousFraction) { rightDelim = new Box(null, { type: "close" }); } else if (!this.rightDelim) rightDelim = makeNullDelimiter(fracContext, "close"); else { rightDelim = this.bind( context, makeCustomSizedDelim( "close", this.rightDelim, delimSize, true, context, { style: this.style, mode: this.mode, isSelected: this.isSelected } ) ); } const mfrac = new Box([leftDelim, frac, rightDelim], { isTight: fracContext.isTight, type: "inner", classes: "mfrac" }); const result = this.bind(context, mfrac); if (this.caret) result.caret = this.caret; return this.attachSupsub(context, { base: result }); } }; // src/atoms/latex.ts var LatexAtom = class _LatexAtom extends Atom { // Display errors with wavy red line constructor(value, options) { var _a3; super({ type: "latex", value, mode: "latex" }); this.isSuggestion = (_a3 = options == null ? void 0 : options.isSuggestion) != null ? _a3 : false; this.isError = false; } static fromJson(json) { const result = new _LatexAtom(json.value); if (json.isSuggestion) result.isSuggestion = true; if (json.isError) result.isError = true; return result; } toJson() { const options = {}; if (this.isSuggestion) options.isSuggestion = true; if (this.isError) options.isError = true; return __spreadValues({ type: "latex", value: this.value }, options); } get computedStyle() { return {}; } render(context) { const result = new Box(this.value, { classes: this.isSuggestion ? "ML__suggestion" : this.isError ? "ML__error" : "", type: "latex", maxFontSize: 1 }); if (!result) return null; if (this.caret) result.caret = this.caret; return this.bind(context, result); } }; var LatexGroupAtom = class _LatexGroupAtom extends Atom { constructor(latex) { super({ type: "latexgroup", mode: "latex" }); this.body = [...latex].map((x) => new LatexAtom(x)); this.skipBoundary = false; } static fromJson(_json) { return new _LatexGroupAtom(""); } toJson() { return super.toJson(); } render(context) { const box = Atom.createBox(context, this.body); if (!box) return null; if (this.caret) box.caret = this.caret; return this.bind(context, box); } _serialize(_options) { var _a3, _b3; return (_b3 = (_a3 = this.body) == null ? void 0 : _a3.map((x) => x.value).join("")) != null ? _b3 : ""; } }; // src/atoms/extensible-symbol.ts var ExtensibleSymbolAtom = class _ExtensibleSymbolAtom extends Atom { constructor(symbol, options) { super(__spreadProps(__spreadValues({}, options), { type: "extensible-symbol", isFunction: options == null ? void 0 : options.isFunction })); this.value = symbol; this.variant = options == null ? void 0 : options.variant; this.subsupPlacement = options == null ? void 0 : options.limits; } static fromJson(json) { return new _ExtensibleSymbolAtom(json.symbol, json); } toJson() { const result = super.toJson(); if (this.variant) result.variant = this.variant; if (this.subsupPlacement) result.limits = this.subsupPlacement; if (this.isExtensibleSymbol) result.isExtensibleSymbol = true; if (this.value) result.symbol = this.value; return result; } render(context) { var _a3; const large = context.isDisplayStyle && this.value !== "\\smallint"; const base = new Box(this.value, { fontFamily: large ? "Size2-Regular" : "Size1-Regular", classes: "op-symbol " + (large ? "large-op" : "small-op"), type: "op", maxFontSize: context.scalingFactor, isSelected: this.isSelected }); if (!base) return null; base.right = base.italic; const baseShift = (base.height - base.depth) / 2 - AXIS_HEIGHT * context.scalingFactor; const slant = base.italic; base.setTop(baseShift); let result = base; if (this.superscript || this.subscript) { const limits = (_a3 = this.subsupPlacement) != null ? _a3 : "auto"; result = limits === "over-under" || limits === "auto" && context.isDisplayStyle ? this.attachLimits(context, { base, baseShift, slant }) : this.attachSupsub(context, { base }); } return new Box(this.bind(context, result), { type: "op", caret: this.caret, isSelected: this.isSelected, classes: "op-group" }).wrap(context); } _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); const result = []; result.push(this.command); if (this.explicitSubsupPlacement) { if (this.subsupPlacement === "over-under") result.push("\\limits"); if (this.subsupPlacement === "adjacent") result.push("\\nolimits"); if (this.subsupPlacement === "auto") result.push("\\displaylimits"); } result.push(this.supsubToLatex(options)); return joinLatex(result); } }; // src/atoms/overlap.ts var OverlapAtom = class _OverlapAtom extends Atom { constructor(options) { const body = options.body; super(__spreadProps(__spreadValues({}, options), { type: "overlap", body: typeof body === "string" ? [new Atom({ value: body })] : body, style: options == null ? void 0 : options.style })); this.skipBoundary = true; this.align = options == null ? void 0 : options.align; this.boxType = options == null ? void 0 : options.boxType; } static fromJson(json) { return new _OverlapAtom(json); } toJson() { const options = {}; if (this.align) options.align = this.align; if (this.boxType) options.boxType = this.boxType; return __spreadValues(__spreadValues({}, super.toJson()), options); } render(context) { const inner = Atom.createBox(context, this.body, { classes: "inner" }); if (!inner) return null; if (this.caret) inner.caret = this.caret; return this.bind( context, new Box([inner, new Box(null, { classes: "fix" })], { classes: this.align === "right" ? "rlap" : "llap", type: this.boxType }) ); } }; // src/atoms/overunder.ts var OverunderAtom = class _OverunderAtom extends Atom { constructor(options) { var _a3, _b3, _c2, _d2; super({ type: "overunder", command: options.command, style: options.style, mode: options.mode, body: options.body, skipBoundary: (_a3 = options.skipBoundary) != null ? _a3 : true }); this.subsupPlacement = options.supsubPlacement; this.svgAbove = options.svgAbove; this.svgBelow = options.svgBelow; this.svgBody = options.svgBody; this.above = options.above; this.below = options.below; this.boxType = (_b3 = options.boxType) != null ? _b3 : "ord"; this.paddedBody = (_c2 = options.paddedBody) != null ? _c2 : false; this.paddedLabels = (_d2 = options.paddedLabels) != null ? _d2 : false; } static fromJson(json) { return new _OverunderAtom(json); } toJson() { const json = super.toJson(); if (!this.skipBoundary) json.skipBoundary = false; if (this.subsupPlacement) json.subsupPlacement = this.subsupPlacement; if (this.svgAbove) json.svgAbove = this.svgAbove; if (this.svgBelow) json.svgBelow = this.svgBelow; if (this.svgBody) json.svgBody = this.svgBody; if (this.boxType !== "ord") json.boxType = this.boxType; if (this.paddedBody) json.paddedBody = true; if (this.paddedLabels) json.paddedLabels = true; return json; } /** * Combine a base with an atom above and an atom below. * * See http://tug.ctan.org/macros/latex/required/amsmath/amsmath.dtx * * > \newcommand{\overset}[2]{\binrel@{#2}% * > \binrel@@{\mathop{\kern\z@#2}\limits^{#1}}} * */ render(parentContext) { let body = this.svgBody ? makeSVGBox(this.svgBody) : Atom.createBox(parentContext, this.body, { type: "ignore" }); const annotationContext = new Context( { parent: parentContext, mathstyle: "scriptstyle" }, this.style ); let above = null; if (this.svgAbove) above = makeSVGBox(this.svgAbove); else if (this.above) above = Atom.createBox(annotationContext, this.above, { type: "ignore" }); let below = null; if (this.svgBelow) below = makeSVGBox(this.svgBelow); else if (this.below) below = Atom.createBox(annotationContext, this.below, { type: "ignore" }); if (this.paddedBody) { body = new Box( [ makeNullDelimiter(parentContext, "open"), body, makeNullDelimiter(parentContext, "close") ], { type: "ignore" } ); } let base = makeOverunderStack(parentContext, { base: body, above, below, type: this.boxType === "bin" || this.boxType === "rel" ? this.boxType : "ord", paddedAboveBelow: this.paddedLabels }); if (!base) return null; if (this.subsupPlacement === "over-under") base = this.attachLimits(parentContext, { base, type: base.type }); else base = this.attachSupsub(parentContext, { base }); if (this.caret) base.caret = this.caret; return this.bind(parentContext, base); } }; function makeOverunderStack(context, options) { if (!options.base) return null; if (!options.above && !options.below) { const box = new Box(options.base, { type: options.type }); box.setStyle("position", "relative"); return box; } let aboveShift = 0; if (options.above) aboveShift = context.metrics.bigOpSpacing5; let result = null; const base = options.base; const baseShift = 0; const classes = ["ML__center"]; if (options.paddedAboveBelow) classes.push("ML__label_padding"); if (options.below && options.above) { const bottom = context.metrics.bigOpSpacing5 + options.below.height + options.below.depth + base.depth + baseShift; result = new VBox({ bottom, children: [ context.metrics.bigOpSpacing5, { box: options.below, classes }, { box: base, classes: ["ML__center"] }, aboveShift, { box: options.above, classes }, context.metrics.bigOpSpacing5 ] }); } else if (options.below) { result = new VBox({ top: base.height - baseShift, children: [ context.metrics.bigOpSpacing5, { box: options.below, classes }, { box: base, classes: ["ML__center"] } ] }); } else if (options.above) { result = new VBox({ bottom: base.depth + baseShift, children: [ // base.depth, { box: base, classes: ["ML__center"] }, aboveShift, { box: options.above, classes }, context.metrics.bigOpSpacing5 ] }); } return new Box(result, { type: options.type }); } // src/atoms/phantom.ts var PhantomAtom = class _PhantomAtom extends Atom { constructor(options) { var _a3, _b3, _c2, _d2; super(__spreadProps(__spreadValues({}, options), { type: "phantom" })); this.captureSelection = true; this.isInvisible = (_a3 = options.isInvisible) != null ? _a3 : false; this.smashDepth = (_b3 = options.smashDepth) != null ? _b3 : false; this.smashHeight = (_c2 = options.smashHeight) != null ? _c2 : false; this.smashWidth = (_d2 = options.smashWidth) != null ? _d2 : false; } static fromJson(json) { return new _PhantomAtom(json); } toJson() { const options = {}; if (this.isInvisible) options.isInvisible = true; if (this.smashDepth) options.smashDepth = true; if (this.smashHeight) options.smashHeight = true; if (this.smashWidth) options.smashWidth = true; return __spreadValues(__spreadValues({}, super.toJson()), options); } render(context) { const phantom = new Context({ parent: context, isPhantom: true }); if (!this.smashDepth && !this.smashHeight && !this.smashWidth) { console.assert(this.isInvisible); return Atom.createBox(phantom, this.body, { classes: "inner" }); } const content = Atom.createBox( this.isInvisible ? phantom : context, this.body ); if (!content) return null; if (this.smashWidth) { const fix = new Box(null, { classes: "fix" }); return new Box([content, fix], { classes: "rlap" }).wrap(context); } if (!this.smashHeight && !this.smashDepth) return content; if (this.smashHeight) content.height = 0; if (this.smashDepth) content.depth = 0; if (content.children) { for (const box of content.children) { if (this.smashHeight) box.height = 0; if (this.smashDepth) box.depth = 0; } } return new VBox( { firstBaseline: [{ box: content }] }, { type: content.type } ).wrap(context); } }; // src/atoms/spacing.ts var SpacingAtom = class _SpacingAtom extends Atom { constructor(options) { var _a3; super(__spreadValues({ type: "spacing" }, options)); this.width = options == null ? void 0 : options.width; this._braced = (_a3 = options == null ? void 0 : options.braced) != null ? _a3 : false; } static fromJson(json) { return new _SpacingAtom(json); } toJson() { const json = super.toJson(); if (this.width !== void 0) json.width = this.width; if (this._braced) json.braced = true; return json; } render(context) { var _a3; if (this.command === "space") return new Box(this.mode === "math" ? null : " "); let result; if (this.width !== void 0) { result = new Box(null, { classes: "mspace" }); result.left = context.toEm(this.width); } else { const spacingCls = (_a3 = { "\\qquad": "qquad", "\\quad": "quad", "\\enspace": "enspace", "\\;": "thickspace", "\\:": "mediumspace", "\\>": "mediumspace", "\\,": "thinspace", "\\!": "negativethinspace" }[this.command]) != null ? _a3 : "mediumspace"; result = new Box(null, { classes: spacingCls }); } result = this.bind(context, result); if (this.caret) result.caret = this.caret; return result; } _serialize(options) { var _a3; if (!options.expandMacro && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); const command = (_a3 = this.command) != null ? _a3 : ""; if (this.width === void 0) return command; if (this._braced && !("register" in this.width)) return `${command}{${serializeLatexValue(this.width)}}`; return `${command}${serializeLatexValue(this.width)}`; } }; // src/atoms/surd.ts var SurdAtom = class _SurdAtom extends Atom { constructor(options) { var _a3; super(__spreadProps(__spreadValues({}, options), { type: "surd", mode: (_a3 = options.mode) != null ? _a3 : "math", style: options.style, displayContainsHighlight: true, body: options.body })); this.above = options.index; } static fromJson(json) { return new _SurdAtom(__spreadProps(__spreadValues({}, json), { index: json.above })); } _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); const command = this.command; const body = this.bodyToLatex(options); if (this.above && !this.hasEmptyBranch("above")) return latexCommand(`${command}[${this.aboveToLatex(options)}]`, body); if (/^[0-9]$/.test(body)) return `${command}${body}`; return latexCommand(command, body); } // Custom implementation so that the navigation of the index feels natural get children() { if (this._children) return this._children; const result = []; if (this.above) { for (const x of this.above) { result.push(...x.children); result.push(x); } } if (this.body) { for (const x of this.body) { result.push(...x.children); result.push(x); } } this._children = result; return result; } render(context) { var _a3; const innerContext = new Context( { parent: context, mathstyle: "cramp" }, this.style ); const innerBox = (_a3 = Atom.createBox(innerContext, this.body, { type: "inner" })) != null ? _a3 : new Box(null); const factor = innerContext.scalingFactor; const ruleWidth = innerContext.metrics.defaultRuleThickness / factor; const phi = context.isDisplayStyle ? X_HEIGHT : ruleWidth; const line = new Box(null, { classes: "ML__sqrt-line", style: this.style }); line.height = ruleWidth; line.softWidth = innerBox.width; let lineClearance = factor * (ruleWidth + phi / 4); const innerTotalHeight = Math.max( factor * 2 * phi, innerBox.height + innerBox.depth ); const minDelimiterHeight = innerTotalHeight + lineClearance + ruleWidth; const delimContext = new Context({ parent: context }, this.style); const delimBox = this.bind( delimContext, new Box( makeCustomSizedDelim( "inner", // @todo not sure if that's the right type "\\surd", minDelimiterHeight, false, delimContext, { isSelected: this.isSelected } ), { isSelected: this.isSelected, classes: "ML__sqrt-sign", style: this.style } ) ); if (!delimBox) return null; const delimDepth = delimBox.height + delimBox.depth - ruleWidth; if (delimDepth > innerBox.height + innerBox.depth + lineClearance) { lineClearance = (lineClearance + delimDepth - (innerBox.height + innerBox.depth)) / 2; } delimBox.setTop(delimBox.height - innerBox.height - lineClearance); const bodyBox = this.bind( context, new VBox({ firstBaseline: [ { box: new Box(innerBox) }, // Need to wrap the inner for proper selection bound calculation lineClearance - 2 * ruleWidth, { box: line }, ruleWidth ] }) ); const indexBox = Atom.createBox( new Context({ parent: context, mathstyle: "scriptscriptstyle" }), this.above, { type: "ignore" } ); if (!indexBox) { const result2 = new Box([delimBox, bodyBox], { classes: this.containsCaret ? "ML__contains-caret" : "", type: "inner" }); result2.setStyle("display", "inline-block"); result2.setStyle("height", result2.height + result2.depth, "em"); if (this.caret) result2.caret = this.caret; return this.bind(context, result2); } const indexStack = new VBox({ shift: -0.6 * (Math.max(delimBox.height, bodyBox.height) - Math.max(delimBox.depth, bodyBox.depth)), children: [{ box: indexBox }] }); const result = new Box( [ new Box(indexStack, { classes: "ML__sqrt-index", type: "ignore" }), delimBox, bodyBox ], { type: "inner", classes: this.containsCaret ? "ML__contains-caret" : "" } ); result.height = delimBox.height; result.depth = delimBox.depth; if (this.caret) result.caret = this.caret; return this.bind(context, result); } }; // src/core/skip-box.ts var SkipBox = class extends Box { constructor(width) { super(null, { type: "skip" }); this._width = width; } toMarkup() { return ``; } }; function addSkipBefore(box, width) { if (!box.parent) return; const siblings = box.parent.children; const i = siblings.indexOf(box); let j = i - 1; while (j >= 0) { if (siblings[j].type === "ignore") j -= 1; else break; } if (j < 0 && box.parent.parent && box.parent.type === "lift") { addSkipBefore(box.parent, width); return; } if (i > 0 && siblings[i - 1].type === "skip") siblings[i - 1].width += width; else siblings.splice(i, 0, new SkipBox(width)); } // src/core/inter-box-spacing.ts var INTER_BOX_SPACING = { ord: { op: 3, bin: 4, rel: 5, inner: 3 }, op: { ord: 3, op: 3, rel: 5, inner: 3 }, bin: { ord: 4, op: 4, open: 4, inner: 4 }, rel: { ord: 5, op: 5, open: 5, inner: 5 }, close: { op: 3, bin: 4, rel: 5, inner: 3 }, punct: { ord: 3, op: 3, rel: 3, open: 3, punct: 3, inner: 3 }, inner: { ord: 3, op: 3, bin: 4, rel: 5, open: 3, punct: 3, inner: 3 } }; var INTER_BOX_TIGHT_SPACING = { ord: { op: 3 }, op: { ord: 3, op: 3 }, close: { op: 3 }, inner: { op: 3 } }; function adjustType(boxes) { traverseBoxes(boxes, (prev, cur) => { if (cur.type === "bin" && (!prev || /^(middle|bin|op|rel|open|punct)$/.test(prev.type))) cur.type = "ord"; if ((prev == null ? void 0 : prev.type) === "bin" && /^(rel|close|punct)$/.test(cur.type)) prev.type = "ord"; if (cur.type !== "ignore") prev = cur; }); } function applyInterBoxSpacing(root, context) { if (!root.children) return root; const boxes = root.children; adjustType(boxes); const thin = context.getRegisterAsEm("thinmuskip"); const med = context.getRegisterAsEm("medmuskip"); const thick = context.getRegisterAsEm("thickmuskip"); traverseBoxes(boxes, (prev, cur) => { var _a3, _b3, _c2; if (!prev) return; const prevType = prev.type; const table = cur.isTight ? (_a3 = INTER_BOX_TIGHT_SPACING[prevType]) != null ? _a3 : null : (_b3 = INTER_BOX_SPACING[prevType]) != null ? _b3 : null; const hskip = (_c2 = table == null ? void 0 : table[cur.type]) != null ? _c2 : null; if (hskip === 3) addSkipBefore(cur, thin); if (hskip === 4) addSkipBefore(cur, med); if (hskip === 5) addSkipBefore(cur, thick); }); return root; } function traverseBoxes(boxes, f, prev = void 0) { if (!boxes) return prev; boxes = [...boxes]; for (const cur of boxes) { if (cur.type === "lift") prev = traverseBoxes(cur.children, f, prev); else if (cur.type === "ignore") traverseBoxes(cur.children, f); else { f(prev, cur); traverseBoxes(cur.children, f); prev = cur; } } return prev; } // src/atoms/tooltip.ts var TooltipAtom = class _TooltipAtom extends Atom { constructor(options) { super({ type: "tooltip", command: options.command, mode: options.mode, style: options.style, body: options.body, displayContainsHighlight: true }); this.tooltip = new Atom({ type: "root", mode: options.content, body: options.tooltip, style: {} }); this.skipBoundary = true; this.captureSelection = false; } static fromJson(json) { return new _TooltipAtom(__spreadProps(__spreadValues({}, json), { tooltip: fromJson(json.tooltip) })); } toJson() { var _a3; const tooltip = (_a3 = this.tooltip.body) == null ? void 0 : _a3.filter((x) => x.type !== "first").map((x) => x.toJson()); return __spreadProps(__spreadValues({}, super.toJson()), { tooltip }); } render(context) { const body = Atom.createBox(new Context(), this.body); if (!body) return null; const tooltipContext = new Context( { parent: context, mathstyle: "displaystyle" }, { fontSize: DEFAULT_FONT_SIZE } ); const tooltip = coalesce( applyInterBoxSpacing( new Box(this.tooltip.render(tooltipContext), { classes: "ML__tooltip-content" }), tooltipContext ) ); const box = new Box([tooltip, body], { classes: "ML__tooltip-container" }); if (this.caret) box.caret = this.caret; return this.bind(context, box); } }; // src/atoms/operator.ts var OperatorAtom = class _OperatorAtom extends Atom { constructor(symbol, options) { super(__spreadProps(__spreadValues({}, options), { type: "operator", isFunction: options == null ? void 0 : options.isFunction })); this.value = symbol; this.variant = options == null ? void 0 : options.variant; this.variantStyle = options == null ? void 0 : options.variantStyle; this.subsupPlacement = options == null ? void 0 : options.limits; } static fromJson(json) { return new _OperatorAtom(json.symbol, json); } toJson() { const result = super.toJson(); if (this.variant) result.variant = this.variant; if (this.variantStyle) result.variantStyle = this.variantStyle; if (this.subsupPlacement) result.limits = this.subsupPlacement; if (this.value) result.symbol = this.value; return result; } render(context) { var _a3; const base = new Box(this.value, { type: "op", mode: "math", maxFontSize: context.scalingFactor, style: { variant: this.variant, variantStyle: this.variantStyle }, isSelected: this.isSelected, letterShapeStyle: context.letterShapeStyle }); let result = base; if (this.superscript || this.subscript) { const limits = (_a3 = this.subsupPlacement) != null ? _a3 : "auto"; result = limits === "over-under" || limits === "auto" && context.isDisplayStyle ? this.attachLimits(context, { base }) : this.attachSupsub(context, { base }); } return new Box(this.bind(context, result), { type: "op", caret: this.caret, isSelected: this.isSelected, classes: "op-group" }).wrap(context); } _serialize(options) { if (!(options.expandMacro || options.skipStyles || options.skipPlaceholders) && typeof this.verbatimLatex === "string") return this.verbatimLatex; const def = getDefinition(this.command, this.mode); if (def == null ? void 0 : def.serialize) return def.serialize(this, options); const result = [this.command]; if (this.explicitSubsupPlacement) { if (this.subsupPlacement === "over-under") result.push("\\limits"); if (this.subsupPlacement === "adjacent") result.push("\\nolimits"); if (this.subsupPlacement === "auto") result.push("\\displaylimits"); } result.push(this.supsubToLatex(options)); return joinLatex(result); } }; // src/core/atom.ts function fromJson(json) { if (isArray(json)) return json.map((x) => fromJson(x)); if (typeof json === "string") return Atom.fromJson(json); json = __spreadValues({}, json); for (const branch of NAMED_BRANCHES) if (json[branch]) json[branch] = fromJson(json[branch]); if (json.args) json.args = argumentsFromJson(json.args); if (json.array) json.array = fromJson(json.array); const type = json.type; let result = void 0; if (type === "accent") result = AccentAtom.fromJson(json); if (type === "array") result = ArrayAtom.fromJson(json); if (type === "box") result = BoxAtom.fromJson(json); if (type === "chem") result = ChemAtom.fromJson(json); if (type === "composition") result = CompositionAtom.fromJson(json); if (type === "delim") result = MiddleDelimAtom.fromJson(json); if (type === "enclose") result = EncloseAtom.fromJson(json); if (type === "error") result = ErrorAtom.fromJson(json); if (type === "extensible-symbol") result = ExtensibleSymbolAtom.fromJson(json); if (type === "genfrac") result = GenfracAtom.fromJson(json); if (type === "group") result = GroupAtom.fromJson(json); if (type === "latex") result = LatexAtom.fromJson(json); if (type === "latexgroup") result = LatexGroupAtom.fromJson(json); if (type === "leftright") result = LeftRightAtom.fromJson(json); if (type === "macro") result = MacroAtom.fromJson(json); if (type === "macro-argument") result = MacroArgumentAtom.fromJson(json); if (type === "operator") result = OperatorAtom.fromJson(json); if (type === "overlap") result = OverlapAtom.fromJson(json); if (type === "overunder") result = OverunderAtom.fromJson(json); if (type === "placeholder") result = PlaceholderAtom.fromJson(json); if (type === "prompt") result = PromptAtom.fromJson(json); if (type === "phantom") result = PhantomAtom.fromJson(json); if (type === "sizeddelim") result = SizedDelimAtom.fromJson(json); if (type === "spacing") result = SpacingAtom.fromJson(json); if (type === "subsup") result = SubsupAtom.fromJson(json); if (type === "surd") result = SurdAtom.fromJson(json); if (type === "text") result = TextAtom.fromJson(json); if (type === "tooltip") result = TooltipAtom.fromJson(json); if (!result) { console.assert( !type || [ "first", "mbin", "mrel", "mclose", "minner", "mop", "mopen", "mord", "mpunct", "root", "space" ].includes(type), `MathLive 0.98.5: an unexpected atom type "${type}" was encountered. Add new atom constructors to \`fromJson()\` in "atom.ts"` ); result = Atom.fromJson(json); } for (const branch of NAMED_BRANCHES) if (json[branch]) result.setChildren(json[branch], branch); if (json.verbatimLatex !== void 0) result.verbatimLatex = json.verbatimLatex; if (json.subsupPlacement) result.subsupPlacement = json.subsupPlacement; if (json.explicitSubsupPlacement) result.explicitSubsupPlacement = true; if (json.isFunction) result.isFunction = true; if (json.isExtensibleSymbol) result.isExtensibleSymbol = true; if (json.skipBoundary) result.skipBoundary = true; if (json.captureSelection) result.captureSelection = true; return result; } function argumentsFromJson(json) { if (!json) return void 0; if (!Array.isArray(json)) return void 0; return json.map((arg) => { if (arg === "") return null; if (typeof arg === "object" && "group" in arg) return { group: arg.group.map((x) => fromJson(x)) }; if (typeof arg === "object" && "atoms" in arg) return arg.atoms.map((x) => fromJson(x)); return arg; }); } // src/core/modes-math.ts var VARIANTS = { // Handle some special characters which are only available in "main" font (not "math") "main": ["Main-Regular", "ML__cmr"], "main-italic": ["Main-Italic", "ML__cmr ML__it"], "main-bold": ["Main-Bold", "ML__cmr ML__bold"], "main-bolditalic": ["Main-BoldItalic", "ML__cmr ML__bold ML__it"], "normal": ["Main-Regular", "ML__cmr"], // 'main' font. There is no 'math' regular (upright) "normal-bold": ["Main-Bold", "ML__mathbf"], // 'main' font. There is no 'math' bold "normal-italic": ["Math-Italic", "ML__mathit"], // Special metrics for 'math' "normal-bolditalic": ["Math-BoldItalic", "ML__mathbfit"], // Special metrics for 'math' // Extended math symbols, arrows, etc.. at their standard Unicode codepoints "ams": ["AMS-Regular", "ML__ams"], "ams-bold": ["AMS-Regular", "ML__ams"], "ams-italic": ["AMS-Regular", "ML__ams"], "ams-bolditalic": ["AMS-Regular", "ML__ams"], "sans-serif": ["SansSerif-Regular", "ML__sans"], "sans-serif-bold": ["SansSerif-Regular", "ML__sans ML__bold"], "sans-serif-italic": ["SansSerif-Regular", "ML__sans"], "sans-serif-bolditalic": ["SansSerif-Regular", "ML__sans"], "calligraphic": ["Caligraphic-Regular", "ML__cal"], "calligraphic-bold": ["Caligraphic-Regular", "ML__cal ML__bold"], "calligraphic-italic": ["Caligraphic-Regular", "ML__cal ML__it"], "calligraphic-bolditalic": ["Caligraphic-Regular", "ML__cal ML__bold ML__it"], "script": ["Script-Regular", "ML__script"], "script-bold": ["Script-Regular", "ML__script ML__bold"], "script-italic": ["Script-Regular", "ML__script ML__it"], "script-bolditalic": ["Script-Regular", "ML__script ML__bold ML__it"], "fraktur": ["Fraktur-Regular", "ML__frak"], "fraktur-bold": ["Fraktur-Regular", "ML__frak"], "fraktur-italic": ["Fraktur-Regular", "ML__frak"], "fraktur-bolditalic": ["Fraktur-Regular", "ML__frak"], "monospace": ["Typewriter-Regular", "ML__tt"], "monospace-bold": ["Typewriter-Regular", "ML__tt ML__bold"], "monospace-italic": ["Typewriter-Regular", "ML__tt ML__it"], "monospace-bolditalic": ["Typewriter-Regular", "ML__tt ML__bold ML__it"], // Blackboard characters are 'A-Z' in the AMS font "double-struck": ["AMS-Regular", "ML__bb"], "double-struck-bold": ["AMS-Regular", "ML__bb"], "double-struck-italic": ["AMS-Regular", "ML__bb"], "double-struck-bolditalic": ["AMS-Regular", "ML__bb"] }; var VARIANT_REPERTOIRE = { "double-struck": /^[A-Z ]$/, "script": /^[A-Z ]$/, "calligraphic": /^[\dA-Z ]$/, "fraktur": /^[\dA-Za-z ]$|^[!"#$%&'()*+,\-./:;=?[]^’‘]$/, "monospace": /^[\dA-Za-z ]$|^[!"&'()*+,\-./:;=?@[\]^_~\u0131\u0237\u0393\u0394\u0398\u039B\u039E\u03A0\u03A3\u03A5\u03A8\u03A9]$/, "sans-serif": /^[\dA-Za-z ]$|^[!"&'()*+,\-./:;=?@[\]^_~\u0131\u0237\u0393\u0394\u0398\u039B\u039E\u03A0\u03A3\u03A5\u03A8\u03A9]$/ }; var GREEK_LOWERCASE = /^[\u03B1-\u03C9]|\u03D1|\u03D5|\u03D6|\u03F1|\u03F5]$/; var GREEK_UPPERCASE = /^[\u0393|\u0394\u0398\u039B\u039E\u03A0\u03A3\u03A5\u03A6\u03A8\u03A9]$/; var LETTER_SHAPE_RANGES = [ /^[a-z]$/, // Lowercase latin /^[A-Z]$/, // Uppercase latin GREEK_LOWERCASE, GREEK_UPPERCASE ]; var LETTER_SHAPE_MODIFIER = { iso: ["it", "it", "it", "it"], tex: ["it", "it", "it", "up"], french: ["it", "up", "up", "up"], upright: ["up", "up", "up", "up"] }; var MathMode = class extends Mode { constructor() { super("math"); } createAtom(command, info, style) { var _a3, _b3, _c2, _d2; if (info === null) { return new Atom({ type: "mord", mode: "math", command, value: command, style }); } const isFunction = window.MathfieldElement.isFunction( (_a3 = info.command) != null ? _a3 : command ); if (info.definitionType === "symbol") { const result2 = new Atom({ type: (_b3 = info.type) != null ? _b3 : "mord", mode: "math", command: (_c2 = info.command) != null ? _c2 : command, value: String.fromCodePoint(info.codepoint), style }); if (isFunction) result2.isFunction = true; if (command.startsWith("\\")) result2.verbatimLatex = command; return result2; } const result = new Atom({ type: "mord", mode: "math", command: (_d2 = info.command) != null ? _d2 : command, value: command, style }); if (isFunction) result.isFunction = true; if (command.startsWith("\\")) result.verbatimLatex = command; return result; } serialize(run, options) { const result = emitVariantRun(run, __spreadProps(__spreadValues({}, options), { defaultMode: "math" })); if (result.length === 0 || options.defaultMode !== "text") return result; return ["$ ", ...result, " $"]; } getFont(box, style) { console.assert(style.variant !== void 0); let { variant } = style; let { variantStyle } = style; if (variant === "normal" && !variantStyle && /[\u00A3\u0131\u0237]/.test(box.value)) { variant = "main"; variantStyle = "italic"; } if (variant === "normal" && !variantStyle && box.value.length === 1) { LETTER_SHAPE_RANGES.forEach((x, i) => { var _a3; if (x.test(box.value) && LETTER_SHAPE_MODIFIER[(_a3 = style.letterShapeStyle) != null ? _a3 : "tex"][i] === "it") variantStyle = "italic"; }); } if (variantStyle === "up") variantStyle = void 0; const styledVariant = variantStyle ? variant + "-" + variantStyle : variant; console.assert(VARIANTS[styledVariant] !== void 0); const [fontName, classes] = VARIANTS[styledVariant]; if (VARIANT_REPERTOIRE[variant] && !VARIANT_REPERTOIRE[variant].test(box.value)) { box.value = mathVariantToUnicode(box.value, variant, variantStyle); return null; } if (GREEK_LOWERCASE.test(box.value)) box.classes += " lcGreek"; if (classes) box.classes += " " + classes; return fontName; } }; function emitVariantRun(run, options) { const { parent } = run[0]; const contextVariant = variantString(parent); return getPropertyRuns(run, "variant").map((x) => { const variant = variantString(x[0]); let command = ""; if (variant && variant !== contextVariant) { command = { "calligraphic": "\\mathcal", "fraktur": "\\mathfrak", "double-struck": "\\mathbb", "script": "\\mathscr", "monospace": "\\mathtt", "sans-serif": "\\mathsf", "normal": "\\mathrm", "normal-italic": "\\mathnormal", "normal-bold": "\\mathbf", "normal-bolditalic": "\\mathbfit", "ams": "", "ams-italic": "\\mathit", "ams-bold": "\\mathbf", "ams-bolditalic": "\\mathbfit", "main": "", "main-italic": "\\mathit", "main-bold": "\\mathbf", "main-bolditalic": "\\mathbfit" // There are a few rare font families possible, which // are not supported: // mathbbm, mathbbmss, mathbbmtt, mathds, swab, goth // In addition, the 'main' and 'math' font technically // map to \mathnormal{} }[variant]; console.assert(command !== void 0); } const arg = joinLatex(x.map((x2) => x2._serialize(options))); return !command ? arg : latexCommand(command, arg); }); } function variantString(atom) { if (!atom) return ""; const { style } = atom; if (style.variant === void 0) return ""; let result = style.variant; if (![ "calligraphic", "fraktur", "double-struck", "script", "monospace", "sans-serif" ].includes(style.variant) && style.variantStyle && style.variantStyle !== "up") result += "-" + style.variantStyle; return result; } new MathMode(); // src/core/modes-text.ts function emitStringTextRun(run, options) { return run.map((x) => x._serialize(options)); } function emitFontShapeTextRun(run, options) { return getPropertyRuns(run, "fontShape").map((x) => { const s = emitStringTextRun(x, options); const { fontShape } = x[0].style; let command = ""; if (fontShape === "it") command = "\\textit"; if (fontShape === "sl") command = "\\textsl"; if (fontShape === "sc") command = "\\textsc"; if (fontShape === "n") command = "\\textup"; if (!command && fontShape) return `{${latexCommand("\\fontshape", fontShape)}${joinLatex(s)}}`; return command ? latexCommand(command, joinLatex(s)) : joinLatex(s); }); } function emitFontSeriesTextRun(run, options) { return getPropertyRuns(run, "fontSeries").map((x) => { const s = emitFontShapeTextRun(x, options); const { fontSeries } = x[0].style; let command = ""; if (fontSeries === "b") command = "\\textbf"; if (fontSeries === "l") command = "\\textlf"; if (fontSeries === "m") command = "\\textmd"; if (fontSeries && !command) return `{${latexCommand("\\fontseries", fontSeries)}${joinLatex(s)}}`; return command ? latexCommand(command, joinLatex(s)) : joinLatex(s); }); } function emitSizeTextRun(run, options) { return getPropertyRuns(run, "fontSize").map((x) => { var _a3, _b3; const s = emitFontSeriesTextRun(x, options); const command = (_b3 = [ "", "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge" ][(_a3 = x[0].style.fontSize) != null ? _a3 : ""]) != null ? _b3 : ""; return command ? `${command} ${joinLatex(s)}` : joinLatex(s); }); } function emitFontFamilyTextRun(run, options, needsWrap) { return getPropertyRuns(run, "fontFamily").map((x) => { var _a3, _b3; const s = emitSizeTextRun(x, options); const command = (_b3 = { "roman": "textrm", "monospace": "texttt", "sans-serif": "textsf" }[(_a3 = x[0].style.fontFamily) != null ? _a3 : ""]) != null ? _b3 : ""; if (command) return `\\${command}{${joinLatex(s)}}`; if (x[0].style.fontFamily) return `{\\fontfamily{${x[0].style.fontFamily}} ${joinLatex(s)}}`; if (needsWrap) return `\\text{${joinLatex(s)}}`; return joinLatex(s); }); } var TEXT_FONT_CLASS = { "roman": "", "sans-serif": "ML__sans", "monospace": "ML__tt" }; var TextMode = class extends Mode { constructor() { super("text"); } createAtom(command, info, style) { if (!info) return null; if (info.definitionType === "symbol") { return new TextAtom( command, String.fromCodePoint(info.codepoint), style != null ? style : {} ); } return null; } serialize(run, options) { return emitFontFamilyTextRun( run, __spreadProps(__spreadValues({}, options), { defaultMode: "text" }), options.defaultMode !== "text" ); } /** * Return the font-family name */ getFont(box, style) { var _a3, _b3, _c2, _d2, _e; const { fontFamily } = style; if (TEXT_FONT_CLASS[fontFamily]) box.classes += " " + TEXT_FONT_CLASS[fontFamily]; else if (fontFamily) { box.setStyle("font-family", fontFamily); } if (style.fontShape) { box.classes += " "; box.classes += (_a3 = { it: "ML__it", sl: "ML__shape_sl", // Slanted sc: "ML__shape_sc", // Small caps ol: "ML__shape_ol" // Outline }[style.fontShape]) != null ? _a3 : ""; } if (style.fontSeries) { const m = style.fontSeries.match(/(.?[lbm])?(.?[cx])?/); if (m) { box.classes += " "; box.classes += (_c2 = { ul: "ML__series_ul", el: "ML__series_el", l: "ML__series_l", sl: "ML__series_sl", m: "", // Medium (default) sb: "ML__series_sb", b: "ML__bold", eb: "ML__series_eb", ub: "ML__series_ub" }[(_b3 = m[1]) != null ? _b3 : ""]) != null ? _c2 : ""; box.classes += " "; box.classes += (_e = { uc: "ML__series_uc", ec: "ML__series_ec", c: "ML__series_c", sc: "ML__series_sc", n: "", // Normal (default) sx: "ML__series_sx", x: "ML__series_x", ex: "ML__series_ex", ux: "ML__series_ux" }[(_d2 = m[2]) != null ? _d2 : ""]) != null ? _e : ""; } } return "Main-Regular"; } }; new TextMode(); // src/core/modes-latex.ts var LatexMode = class extends Mode { constructor() { super("latex"); } createAtom(command) { return new LatexAtom(command); } serialize(run, _options) { return run.filter((x) => x instanceof LatexAtom && !x.isSuggestion).map((x) => x.value); } getFont() { return null; } }; new LatexMode(); // src/editor/keyboard-layouts/dvorak.ts var DVORAK = { id: "dvorak", locale: "en", displayName: "Dvorak", virtualLayout: "dvorak", platform: "", score: 0, mapping: { KeyA: ["a", "A", "\xE5", "\xC5"], KeyB: ["x", "X", "\u2248", "\u02DB"], KeyC: ["j", "J", "\u2206", "\xD4"], KeyD: ["e", "E", "\xB4", "\xB4"], KeyE: [".", ">", "\u2265", "\u02D8"], KeyF: ["u", "U", "\xA8", "\xA8"], KeyG: ["i", "I", "\u02C6", "\u02C6"], KeyH: ["d", "D", "\u2202", "\xCE"], KeyI: ["c", "C", "\xE7", "\xC7"], KeyJ: ["h", "H", "\u02D9", "\xD3"], KeyK: ["t", "T", "\u2020", "\u02C7"], KeyL: ["n", "N", "\u02DC", "\u02DC"], KeyM: ["m", "M", "\xB5", "\xC2"], KeyN: ["b", "B", "\u222B", "\u0131"], KeyO: ["r", "R", "\xAE", "\u2030"], KeyP: ["l", "L", "\xAC", "\xD2"], KeyQ: ["'", '"', "\xE6", "\xC6"], KeyR: ["p", "P", "\u03C0", "\u220F"], KeyS: ["o", "O", "\xF8", "\xD8"], KeyT: ["y", "Y", "\xA5", "\xC1"], KeyU: ["g", "G", "\xA9", "\u02DD"], KeyV: ["k", "K", "\u02DA", "\uF8FF"], KeyW: [",", "<", "\u2264", "\xAF"], KeyX: ["q", "Q", "\u0153", "\u0152"], KeyY: ["f", "F", "\u0192", "\xCF"], KeyZ: [";", ":", "\u2026", "\xDA"], Digit1: ["1", "!", "\xA1", "\u2044"], Digit2: ["2", "@", "\u2122", "\u20AC"], Digit3: ["3", "#", "\xA3", "\u2039"], Digit4: ["4", "$", "\xA2", "\u203A"], Digit5: ["5", "%", "\u221E", "\uFB01"], Digit6: ["6", "^", "\xA7", "\uFB02"], Digit7: ["7", "&", "\xB6", "\u2021"], Digit8: ["8", "*", "\u2022", "\xB0"], Digit9: ["9", "(", "\xAA", "\xB7"], Digit0: ["0", ")", "\xBA", "\u201A"], Space: [" ", " ", " ", " "], Minus: ["[", "{", "\u201C", "\u201D"], Equal: ["]", "}", "\u2018", "\u2019"], BracketLeft: ["/", "?", "\xF7", "\xBF"], BracketRight: ["=", "+", "\u2260", "\xB1"], Backslash: ["\\", "|", "\xAB", "\xBB"], Semicolon: ["s", "S", "\xDF", "\xCD"], Quote: ["-", "_", "\u2013", "\u2014"], Backquote: ["`", "~", "`", "`"], Comma: ["w", "W", "\u2211", "\u201E"], Period: ["v", "V", "\u221A", "\u25CA"], Slash: ["z", "Z", "\u03A9", "\xB8"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], Numpad1: ["1", "1", "1", "1"], Numpad2: ["2", "2", "2", "2"], Numpad3: ["3", "3", "3", "3"], Numpad4: ["4", "4", "4", "4"], Numpad5: ["5", "5", "5", "5"], Numpad6: ["6", "6", "6", "6"], Numpad7: ["7", "7", "7", "7"], Numpad8: ["8", "8", "8", "8"], Numpad9: ["9", "9", "9", "9"], Numpad0: ["0", "0", "0", "0"], NumpadDecimal: [".", ".", ".", "."], IntlBackslash: ["\xA7", "\xB1", "\xA7", "\xB1"], NumpadEqual: ["=", "=", "=", "="], AudioVolumeUp: ["", "=", "", "="] } }; // src/editor/keyboard-layouts/english.ts var APPLE_ENGLISH = { id: "apple.en-intl", displayName: "English (international)", virtualLayout: "qwerty", platform: "apple", locale: "en", score: 0, mapping: { KeyA: ["a", "A", "\xE5", "\xC5"], KeyB: ["b", "B", "\u222B", "\u0131"], KeyC: ["c", "C", "\xE7", "\xC7"], KeyD: ["d", "D", "\u2202", "\xCE"], KeyE: ["e", "E", "\xB4", "\xB4"], KeyF: ["f", "F", "\u0192", "\xCF"], KeyG: ["g", "G", "\xA9", "\u02DD"], KeyH: ["h", "H", "\u02D9", "\xD3"], KeyI: ["i", "I", "\u02C6", "\u02C6"], KeyJ: ["j", "J", "\u2206", "\xD4"], KeyK: ["k", "K", "\u02DA", "\uF8FF"], KeyL: ["l", "L", "\xAC", "\xD2"], KeyM: ["m", "M", "\xB5", "\xC2"], KeyN: ["n", "N", "\u02DC", "\u02DC"], KeyO: ["o", "O", "\xF8", "\xD8"], KeyP: ["p", "P", "\u03C0", "\u220F"], KeyQ: ["q", "Q", "\u0153", "\u0152"], KeyR: ["r", "R", "\xAE", "\u2030"], KeyS: ["s", "S", "\xDF", "\xCD"], KeyT: ["t", "T", "\u2020", "\u02C7"], KeyU: ["u", "U", "\xA8", "\xA8"], KeyV: ["v", "V", "\u221A", "\u25CA"], KeyW: ["w", "W", "\u2211", "\u201E"], KeyX: ["x", "X", "\u2248", "\u02DB"], KeyY: ["y", "Y", "\xA5", "\xC1"], KeyZ: ["z", "Z", "\u03A9", "\xB8"], Digit1: ["1", "!", "\xA1", "\u2044"], Digit2: ["2", "@", "\u2122", "\u20AC"], Digit3: ["3", "#", "\xA3", "\u2039"], Digit4: ["4", "$", "\xA2", "\u203A"], Digit5: ["5", "%", "\u221E", "\uFB01"], Digit6: ["6", "^", "\xA7", "\uFB02"], Digit7: ["7", "&", "\xB6", "\u2021"], Digit8: ["8", "*", "\u2022", "\xB0"], Digit9: ["9", "(", "\xAA", "\xB7"], Digit0: ["0", ")", "\xBA", "\u201A"], Space: [" ", " ", " ", " "], Minus: ["-", "_", "\u2013", "\u2014"], Equal: ["=", "+", "\u2260", "\xB1"], BracketLeft: ["[", "{", "\u201C", "\u201D"], BracketRight: ["]", "}", "\u2018", "\u2019"], Backslash: ["\\", "|", "\xAB", "\xBB"], Semicolon: [";", ":", "\u2026", "\xDA"], Quote: ["'", '"', "\xE6", "\xC6"], Backquote: ["`", "\u02DC", "`", "`"], Comma: [",", "<", "\u2264", "\xAF"], Period: [".", ">", "\u2265", "\u02D8"], Slash: ["/", "?", "\xF7", "\xBF"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], Numpad1: ["1", "1", "1", "1"], Numpad2: ["2", "2", "2", "2"], Numpad3: ["3", "3", "3", "3"], Numpad4: ["4", "4", "4", "4"], Numpad5: ["5", "5", "5", "5"], Numpad6: ["6", "6", "6", "6"], Numpad7: ["7", "7", "7", "7"], Numpad8: ["8", "8", "8", "8"], Numpad9: ["9", "9", "9", "9"], Numpad0: ["0", "0", "0", "0"], NumpadDecimal: [".", ".", ".", "."], IntlBackslash: ["\xA7", "\xB1", "\xA7", "\xB1"], NumpadEqual: ["=", "=", "=", "="], AudioVolumeUp: ["", "=", "", "="] } }; var WINDOWS_ENGLISH = { id: "windows.en-intl", displayName: "English (international)", platform: "windows", virtualLayout: "qwerty", locale: "en", score: 0, mapping: { KeyA: ["a", "A", "\xE1", "\xC1"], KeyB: ["b", "B", "", ""], KeyC: ["c", "C", "\xA9", "\xA2"], KeyD: ["d", "D", "\xF0", "\xD0"], KeyE: ["e", "E", "\xE9", "\xC9"], KeyF: ["f", "F", "", ""], KeyG: ["g", "G", "", ""], KeyH: ["h", "H", "", ""], KeyI: ["i", "I", "\xED", "\xCD"], KeyJ: ["j", "J", "", ""], KeyK: ["k", "K", "", ""], KeyL: ["l", "L", "\xF8", "\xD8"], KeyM: ["m", "M", "\xB5", ""], KeyN: ["n", "N", "\xF1", "\xD1"], KeyO: ["o", "O", "\xF3", "\xD3"], KeyP: ["p", "P", "\xF6", "\xD6"], KeyQ: ["q", "Q", "\xE4", "\xC4"], KeyR: ["r", "R", "\xAE", ""], KeyS: ["s", "S", "\xDF", "\xA7"], KeyT: ["t", "T", "\xFE", "\xDE"], KeyU: ["u", "U", "\xFA", "\xDA"], KeyV: ["v", "V", "", ""], KeyW: ["w", "W", "\xE5", "\xC5"], KeyX: ["x", "X", "", ""], KeyY: ["y", "Y", "\xFC", "\xDC"], KeyZ: ["z", "Z", "\xE6", "\xC6"], Digit1: ["1", "!", "\xA1", "\xB9"], Digit2: ["2", "@", "\xB2", ""], Digit3: ["3", "#", "\xB3", ""], Digit4: ["4", "$", "\xA4", "\xA3"], Digit5: ["5", "%", "\u20AC", ""], Digit6: ["6", "^", "\xBC", ""], Digit7: ["7", "&", "\xBD", ""], Digit8: ["8", "*", "\xBE", ""], Digit9: ["9", "(", "\u2018", ""], Digit0: ["0", ")", "\u2019", ""], Space: [" ", " ", "", ""], Minus: ["-", "_", "\xA5", ""], Equal: ["=", "+", "\xD7", "\xF7"], BracketLeft: ["[", "{", "\xAB", ""], BracketRight: ["]", "}", "\xBB", ""], Backslash: ["\\", "|", "\xAC", "\xA6"], Semicolon: [";", ":", "\xB6", "\xB0"], Quote: ["'", '"', "\xB4", "\xA8"], Backquote: ["`", "~", "", ""], Comma: [",", "<", "\xE7", "\xC7"], Period: [".", ">", "", ""], Slash: ["/", "?", "\xBF", ""], NumpadDivide: ["/", "/", "", ""], NumpadMultiply: ["*", "*", "", ""], NumpadSubtract: ["-", "-", "", ""], NumpadAdd: ["+", "+", "", ""], IntlBackslash: ["\\", "|", "", ""] } }; var LINUX_ENGLISH = { id: "linux.en", displayName: "English", platform: "linux", virtualLayout: "qwerty", locale: "en", score: 0, mapping: { KeyA: ["a", "A", "a", "A"], KeyB: ["b", "B", "b", "B"], KeyC: ["c", "C", "c", "C"], KeyD: ["d", "D", "d", "D"], KeyE: ["e", "E", "e", "E"], KeyF: ["f", "F", "f", "F"], KeyG: ["g", "G", "g", "G"], KeyH: ["h", "H", "h", "H"], KeyI: ["i", "I", "i", "I"], KeyJ: ["j", "J", "j", "J"], KeyK: ["k", "K", "k", "K"], KeyL: ["l", "L", "l", "L"], KeyM: ["m", "M", "m", "M"], KeyN: ["n", "N", "n", "N"], KeyO: ["o", "O", "o", "O"], KeyP: ["p", "P", "p", "P"], KeyQ: ["q", "Q", "q", "Q"], KeyR: ["r", "R", "r", "R"], KeyS: ["s", "S", "s", "S"], KeyT: ["t", "T", "t", "T"], KeyU: ["u", "U", "u", "U"], KeyV: ["v", "V", "v", "V"], KeyW: ["w", "W", "w", "W"], KeyX: ["x", "X", "x", "X"], KeyY: ["y", "Y", "y", "Y"], KeyZ: ["z", "Z", "z", "Z"], Digit1: ["1", "!", "1", "!"], Digit2: ["2", "@", "2", "@"], Digit3: ["3", "#", "3", "#"], Digit4: ["4", "$", "4", "$"], Digit5: ["5", "%", "5", "%"], Digit6: ["6", "^", "6", "^"], Digit7: ["7", "&", "7", "&"], Digit8: ["8", "*", "8", "*"], Digit9: ["9", "(", "9", "("], Digit0: ["0", ")", "0", ")"], Space: [" ", " ", " ", " "], Minus: ["-", "_", "-", "_"], Equal: ["=", "+", "=", "+"], BracketLeft: ["[", "{", "[", "{"], BracketRight: ["]", "}", "]", "}"], Backslash: ["\\", "|", "\\", "|"], Semicolon: [";", ":", ";", ":"], Quote: ["'", '"', "'", '"'], Backquote: ["`", "~", "`", "~"], Comma: [",", "<", ",", "<"], Period: [".", ">", ".", ">"], Slash: ["/", "?", "/", "?"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], Numpad1: ["1", "1", "1", "1"], Numpad2: ["2", "2", "2", "2"], Numpad3: ["3", "3", "3", "3"], Numpad4: ["4", "4", "4", "4"], Numpad5: ["5", "5", "5", "5"], Numpad6: ["6", "6", "6", "6"], Numpad7: ["7", "7", "7", "7"], Numpad8: ["8", "8", "8", "8"], Numpad9: ["9", "9", "9", "9"], Numpad0: ["0", "0", "0", "0"], NumpadDecimal: ["", ".", "", "."], IntlBackslash: ["<", ">", "|", "\xA6"], NumpadEqual: ["=", "=", "=", "="], NumpadComma: [".", ".", ".", "."], NumpadParenLeft: ["(", "(", "(", "("], NumpadParenRight: [")", ")", ")", ")"] } }; // src/editor/keyboard-layouts/french.ts var APPLE_FRENCH = { id: "apple.french", locale: "fr", displayName: "French", platform: "apple", virtualLayout: "azerty", score: 0, mapping: { KeyA: ["q", "Q", "\u2021", "\u03A9"], KeyB: ["b", "B", "\xDF", "\u222B"], KeyC: ["c", "C", "\xA9", "\xA2"], KeyD: ["d", "D", "\u2202", "\u2206"], KeyE: ["e", "E", "\xEA", "\xCA"], KeyF: ["f", "F", "\u0192", "\xB7"], KeyG: ["g", "G", "\uFB01", "\uFB02"], KeyH: ["h", "H", "\xCC", "\xCE"], KeyI: ["i", "I", "\xEE", "\xEF"], KeyJ: ["j", "J", "\xCF", "\xCD"], KeyK: ["k", "K", "\xC8", "\xCB"], KeyL: ["l", "L", "\xAC", "|"], KeyM: [",", "?", "\u221E", "\xBF"], KeyN: ["n", "N", "~", "\u0131"], KeyO: ["o", "O", "\u0153", "\u0152"], KeyP: ["p", "P", "\u03C0", "\u220F"], KeyQ: ["a", "A", "\xE6", "\xC6"], KeyR: ["r", "R", "\xAE", "\u201A"], KeyS: ["s", "S", "\xD2", "\u2211"], KeyT: ["t", "T", "\u2020", "\u2122"], KeyU: ["u", "U", "\xBA", "\xAA"], KeyV: ["v", "V", "\u25CA", "\u221A"], KeyW: ["z", "Z", "\xC2", "\xC5"], KeyX: ["x", "X", "\u2248", "\u2044"], KeyY: ["y", "Y", "\xDA", "\u0178"], KeyZ: ["w", "W", "\u2039", "\u203A"], Digit1: ["&", "1", "\uF8FF", "\xB4"], Digit2: ["\xE9", "2", "\xEB", "\u201E"], Digit3: ['"', "3", "\u201C", "\u201D"], Digit4: ["'", "4", "\u2018", "\u2019"], Digit5: ["(", "5", "{", "["], Digit6: ["\xA7", "6", "\xB6", "\xE5"], Digit7: ["\xE8", "7", "\xAB", "\xBB"], Digit8: ["!", "8", "\xA1", "\xDB"], Digit9: ["\xE7", "9", "\xC7", "\xC1"], Digit0: ["\xE0", "0", "\xF8", "\xD8"], Space: [" ", " ", " ", " "], Minus: [")", "\xB0", "}", "]"], Equal: ["-", "_", "\u2014", "\u2013"], BracketLeft: ["^", "\xA8", "\xF4", "\xD4"], BracketRight: ["$", "*", "\u20AC", "\xA5"], Backslash: ["`", "\xA3", "@", "#"], Semicolon: ["m", "M", "\xB5", "\xD3"], Quote: ["\xF9", "%", "\xD9", "\u2030"], Backquote: ["<", ">", "\u2264", "\u2265"], Comma: [";", ".", "\u2026", "\u2022"], Period: [":", "/", "\xF7", "\\"], Slash: ["=", "+", "\u2260", "\xB1"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], NumpadDecimal: [",", ".", ",", "."], IntlBackslash: ["@", "#", "\u2022", "\u0178"], NumpadEqual: ["=", "=", "=", "="] } }; var WINDOWS_FRENCH = { id: "windows.french", locale: "fr", displayName: "French", virtualLayout: "azerty", platform: "windows", score: 0, mapping: { KeyA: ["q", "Q", "", ""], KeyB: ["b", "B", "", ""], KeyC: ["c", "C", "", ""], KeyD: ["d", "D", "", ""], KeyE: ["e", "E", "\u20AC", ""], KeyF: ["f", "F", "", ""], KeyG: ["g", "G", "", ""], KeyH: ["h", "H", "", ""], KeyI: ["i", "I", "", ""], KeyJ: ["j", "J", "", ""], KeyK: ["k", "K", "", ""], KeyL: ["l", "L", "", ""], KeyM: [",", "?", "", ""], KeyN: ["n", "N", "", ""], KeyO: ["o", "O", "", ""], KeyP: ["p", "P", "", ""], KeyQ: ["a", "A", "", ""], KeyR: ["r", "R", "", ""], KeyS: ["s", "S", "", ""], KeyT: ["t", "T", "", ""], KeyU: ["u", "U", "", ""], KeyV: ["v", "V", "", ""], KeyW: ["z", "Z", "", ""], KeyX: ["x", "X", "", ""], KeyY: ["y", "Y", "", ""], KeyZ: ["w", "W", "", ""], Digit1: ["&", "1", "", ""], Digit2: ["\xE9", "2", "~", ""], Digit3: ['"', "3", "#", ""], Digit4: ["'", "4", "{", ""], Digit5: ["(", "5", "[", ""], Digit6: ["-", "6", "|", ""], Digit7: ["\xE8", "7", "`", ""], Digit8: ["_", "8", "\\", ""], Digit9: ["\xE7", "9", "^", ""], Digit0: ["\xE0", "0", "@", ""], Space: [" ", " ", "", ""], Minus: [")", "\xB0", "]", ""], Equal: ["=", "+", "}", ""], BracketLeft: ["^", "\xA8", "", ""], BracketRight: ["$", "\xA3", "\xA4", ""], Backslash: ["*", "\xB5", "", ""], Semicolon: ["m", "M", "", ""], Quote: ["\xF9", "%", "", ""], Backquote: ["\xB2", "", "", ""], Comma: [";", ".", "", ""], Period: [":", "/", "", ""], Slash: ["!", "\xA7", "", ""], NumpadDivide: ["/", "/", "", ""], NumpadMultiply: ["*", "*", "", ""], NumpadSubtract: ["-", "-", "", ""], NumpadAdd: ["+", "+", "", ""], IntlBackslash: ["<", ">", "", ""] } }; var LINUX_FRENCH = { id: "linux.french", locale: "fr", displayName: "French", virtualLayout: "azerty", platform: "linux", score: 0, mapping: { KeyA: ["q", "Q", "@", "\u03A9"], KeyB: ["b", "B", "\u201D", "\u2019"], KeyC: ["c", "C", "\xA2", "\xA9"], KeyD: ["d", "D", "\xF0", "\xD0"], KeyE: ["e", "E", "\u20AC", "\xA2"], KeyF: ["f", "F", "\u0111", "\xAA"], KeyG: ["g", "G", "\u014B", "\u014A"], KeyH: ["h", "H", "\u0127", "\u0126"], KeyI: ["i", "I", "\u2192", "\u0131"], KeyJ: ["j", "J", "\u0309", "\u031B"], KeyK: ["k", "K", "\u0138", "&"], KeyL: ["l", "L", "\u0142", "\u0141"], KeyM: [",", "?", "\u0301", "\u030B"], KeyN: ["n", "N", "n", "N"], KeyO: ["o", "O", "\xF8", "\xD8"], KeyP: ["p", "P", "\xFE", "\xDE"], KeyQ: ["a", "A", "\xE6", "\xC6"], KeyR: ["r", "R", "\xB6", "\xAE"], KeyS: ["s", "S", "\xDF", "\xA7"], KeyT: ["t", "T", "\u0167", "\u0166"], KeyU: ["u", "U", "\u2193", "\u2191"], KeyV: ["v", "V", "\u201C", "\u2018"], KeyW: ["z", "Z", "\xAB", "<"], KeyX: ["x", "X", "\xBB", ">"], KeyY: ["y", "Y", "\u2190", "\xA5"], KeyZ: ["w", "W", "\u0142", "\u0141"], Digit1: ["&", "1", "\xB9", "\xA1"], Digit2: ["\xE9", "2", "~", "\u215B"], Digit3: ['"', "3", "#", "\xA3"], Digit4: ["'", "4", "{", "$"], Digit5: ["(", "5", "[", "\u215C"], Digit6: ["-", "6", "|", "\u215D"], Digit7: ["\xE8", "7", "`", "\u215E"], Digit8: ["_", "8", "\\", "\u2122"], Digit9: ["\xE7", "9", "^", "\xB1"], Digit0: ["\xE0", "0", "@", "\xB0"], Enter: ["\r", "\r", "\r", "\r"], Escape: ["\x1B", "\x1B", "\x1B", "\x1B"], Backspace: ["\b", "\b", "\b", "\b"], Tab: [" ", "", " ", ""], Space: [" ", " ", " ", " "], Minus: [")", "\xB0", "]", "\xBF"], Equal: ["=", "+", "}", "\u0328"], BracketLeft: ["\u0302", "\u0308", "\u0308", "\u030A"], BracketRight: ["$", "\xA3", "\xA4", "\u0304"], Backslash: ["*", "\xB5", "\u0300", "\u0306"], Semicolon: ["m", "M", "\xB5", "\xBA"], Quote: ["\xF9", "%", "\u0302", "\u030C"], Backquote: ["\xB2", "~", "\xAC", "\xAC"], Comma: [";", ".", "\u2500", "\xD7"], Period: [":", "/", "\xB7", "\xF7"], Slash: ["!", "\xA7", "\u0323", "\u0307"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], NumpadDecimal: ["", ".", "", "."], IntlBackslash: ["<", ">", "|", "\xA6"] } }; // src/editor/keyboard-layouts/german.ts var APPLE_GERMAN = { id: "apple.german", locale: "de", displayName: "German", virtualLayout: "qwertz", platform: "apple", score: 0, mapping: { KeyA: ["a", "A", "\xE5", "\xC5"], KeyB: ["b", "B", "\u222B", "\u2039"], KeyC: ["c", "C", "\xE7", "\xC7"], KeyD: ["d", "D", "\u2202", "\u2122"], KeyE: ["e", "E", "\u20AC", "\u2030"], KeyF: ["f", "F", "\u0192", "\xCF"], KeyG: ["g", "G", "\xA9", "\xCC"], KeyH: ["h", "H", "\xAA", "\xD3"], KeyI: ["i", "I", "\u2044", "\xDB"], KeyJ: ["j", "J", "\xBA", "\u0131"], KeyK: ["k", "K", "\u2206", "\u02C6"], KeyL: ["l", "L", "@", "\uFB02"], KeyM: ["m", "M", "\xB5", "\u02D8"], KeyN: ["n", "N", "~", "\u203A"], KeyO: ["o", "O", "\xF8", "\xD8"], KeyP: ["p", "P", "\u03C0", "\u220F"], KeyQ: ["q", "Q", "\xAB", "\xBB"], KeyR: ["r", "R", "\xAE", "\xB8"], KeyS: ["s", "S", "\u201A", "\xCD"], KeyT: ["t", "T", "\u2020", "\u02DD"], KeyU: ["u", "U", "\xA8", "\xC1"], KeyV: ["v", "V", "\u221A", "\u25CA"], KeyW: ["w", "W", "\u2211", "\u201E"], KeyX: ["x", "X", "\u2248", "\xD9"], KeyY: ["z", "Z", "\u03A9", "\u02C7"], KeyZ: ["y", "Y", "\xA5", "\u2021"], Digit1: ["1", "!", "\xA1", "\xAC"], Digit2: ["2", '"', "\u201C", "\u201D"], Digit3: ["3", "\xA7", "\xB6", "#"], Digit4: ["4", "$", "\xA2", "\xA3"], Digit5: ["5", "%", "[", "\uFB01"], Digit6: ["6", "&", "]", "^"], Digit7: ["7", "/", "|", "\\"], Digit8: ["8", "(", "{", "\u02DC"], Digit9: ["9", ")", "}", "\xB7"], Digit0: ["0", "=", "\u2260", "\xAF"], Space: [" ", " ", " ", " "], Minus: ["\xDF", "?", "\xBF", "\u02D9"], Equal: ["\xB4", "`", "'", "\u02DA"], BracketLeft: ["\xFC", "\xDC", "\u2022", "\xB0"], BracketRight: ["+", "*", "\xB1", "\uF8FF"], Backslash: ["#", "'", "\u2018", "\u2019"], Semicolon: ["\xF6", "\xD6", "\u0153", "\u0152"], Quote: ["\xE4", "\xC4", "\xE6", "\xC6"], Backquote: ["<", ">", "\u2264", "\u2265"], Comma: [",", ";", "\u221E", "\u02DB"], Period: [".", ":", "\u2026", "\xF7"], Slash: ["-", "_", "\u2013", "\u2014"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], NumpadDecimal: [",", ",", ".", "."], IntlBackslash: ["^", "\xB0", "\u201E", "\u201C"], NumpadEqual: ["=", "=", "=", "="] } }; var WINDOWS_GERMAN = { id: "windows.german", locale: "de", displayName: "German", platform: "windows", virtualLayout: "qwertz", score: 0, mapping: { KeyA: ["a", "A", "", ""], KeyB: ["b", "B", "", ""], KeyC: ["c", "C", "", ""], KeyD: ["d", "D", "", ""], KeyE: ["e", "E", "\u20AC", ""], KeyF: ["f", "F", "", ""], KeyG: ["g", "G", "", ""], KeyH: ["h", "H", "", ""], KeyI: ["i", "I", "", ""], KeyJ: ["j", "J", "", ""], KeyK: ["k", "K", "", ""], KeyL: ["l", "L", "", ""], KeyM: ["m", "M", "\xB5", ""], KeyN: ["n", "N", "", ""], KeyO: ["o", "O", "", ""], KeyP: ["p", "P", "", ""], KeyQ: ["q", "Q", "@", ""], KeyR: ["r", "R", "", ""], KeyS: ["s", "S", "", ""], KeyT: ["t", "T", "", ""], KeyU: ["u", "U", "", ""], KeyV: ["v", "V", "", ""], KeyW: ["w", "W", "", ""], KeyX: ["x", "X", "", ""], KeyY: ["z", "Z", "", ""], KeyZ: ["y", "Y", "", ""], Digit1: ["1", "!", "", ""], Digit2: ["2", '"', "\xB2", ""], Digit3: ["3", "\xA7", "\xB3", ""], Digit4: ["4", "$", "", ""], Digit5: ["5", "%", "", ""], Digit6: ["6", "&", "", ""], Digit7: ["7", "/", "{", ""], Digit8: ["8", "(", "[", ""], Digit9: ["9", ")", "]", ""], Digit0: ["0", "=", "}", ""], Space: [" ", " ", "", ""], Minus: ["\xDF", "?", "\\", "\u1E9E"], Equal: ["\xB4", "`", "", ""], BracketLeft: ["\xFC", "\xDC", "", ""], BracketRight: ["+", "*", "~", ""], Backslash: ["#", "'", "", ""], Semicolon: ["\xF6", "\xD6", "", ""], Quote: ["\xE4", "\xC4", "", ""], Backquote: ["^", "\xB0", "", ""], Comma: [",", ";", "", ""], Period: [".", ":", "", ""], Slash: ["-", "_", "", ""], NumpadDivide: ["/", "/", "", ""], NumpadMultiply: ["*", "*", "", ""], NumpadSubtract: ["-", "-", "", ""], NumpadAdd: ["+", "+", "", ""], IntlBackslash: ["<", ">", "|", ""] } }; var LINUX_GERMAN = { id: "linux.german", locale: "de", displayName: "German", platform: "windows", virtualLayout: "qwertz", score: 0, mapping: { KeyA: ["a", "A", "\xE6", "\xC6"], KeyB: ["b", "B", "\u201C", "\u2018"], KeyC: ["c", "C", "\xA2", "\xA9"], KeyD: ["d", "D", "\xF0", "\xD0"], KeyE: ["e", "E", "\u20AC", "\u20AC"], KeyF: ["f", "F", "\u0111", "\xAA"], KeyG: ["g", "G", "\u014B", "\u014A"], KeyH: ["h", "H", "\u0127", "\u0126"], KeyI: ["i", "I", "\u2192", "\u0131"], KeyJ: ["j", "J", "\u0323", "\u0307"], KeyK: ["k", "K", "\u0138", "&"], KeyL: ["l", "L", "\u0142", "\u0141"], KeyM: ["m", "M", "\xB5", "\xBA"], KeyN: ["n", "N", "\u201D", "\u2019"], KeyO: ["o", "O", "\xF8", "\xD8"], KeyP: ["p", "P", "\xFE", "\xDE"], KeyQ: ["q", "Q", "@", "\u03A9"], KeyR: ["r", "R", "\xB6", "\xAE"], KeyS: ["s", "S", "\u017F", "\u1E9E"], KeyT: ["t", "T", "\u0167", "\u0166"], KeyU: ["u", "U", "\u2193", "\u2191"], KeyV: ["v", "V", "\u201E", "\u201A"], KeyW: ["w", "W", "\u0142", "\u0141"], KeyX: ["x", "X", "\xAB", "\u2039"], KeyY: ["z", "Z", "\u2190", "\xA5"], KeyZ: ["y", "Y", "\xBB", "\u203A"], Digit1: ["1", "!", "\xB9", "\xA1"], Digit2: ["2", '"', "\xB2", "\u215B"], Digit3: ["3", "\xA7", "\xB3", "\xA3"], Digit4: ["4", "$", "\xBC", "\xA4"], Digit5: ["5", "%", "\xBD", "\u215C"], Digit6: ["6", "&", "\xAC", "\u215D"], Digit7: ["7", "/", "{", "\u215E"], Digit8: ["8", "(", "[", "\u2122"], Digit9: ["9", ")", "]", "\xB1"], Digit0: ["0", "=", "}", "\xB0"], Enter: ["\r", "\r", "\r", "\r"], Escape: ["\x1B", "\x1B", "\x1B", "\x1B"], Backspace: ["\b", "\b", "\b", "\b"], Tab: [" ", "", " ", ""], Space: [" ", " ", " ", " "], Minus: ["\xDF", "?", "\\", "\xBF"], Equal: ["\u0301", "\u0300", "\u0327", "\u0328"], BracketLeft: ["\xFC", "\xDC", "\u0308", "\u030A"], BracketRight: ["+", "*", "~", "\xAF"], Backslash: ["#", "'", "\u2019", "\u0306"], Semicolon: ["\xF6", "\xD6", "\u030B", "\u0323"], Quote: ["\xE4", "\xC4", "\u0302", "\u030C"], Backquote: ["\u0302", "\xB0", "\u2032", "\u2033"], Comma: [",", ";", "\xB7", "\xD7"], Period: [".", ":", "\u2026", "\xF7"], Slash: ["-", "_", "\u2013", "\u2014"], PrintScreen: ["", "", "", ""], PageUp: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], Numpad1: ["", "1", "", "1"], Numpad2: ["", "2", "", "2"], Numpad3: ["", "3", "", "3"], Numpad4: ["", "4", "", "4"], Numpad5: ["", "5", "", "5"], Numpad6: ["", "6", "", "6"], Numpad7: ["", "7", "", "7"], Numpad8: ["", "8", "", "8"], Numpad9: ["", "9", "", "9"], Numpad0: ["", "0", "", "0"], NumpadDecimal: ["", ",", "", ","], IntlBackslash: ["<", ">", "|", "\u0331"], AltRight: ["\r", "\r", "\r", "\r"], MetaRight: [".", ".", ".", "."] } }; // src/editor/keyboard-layouts/spanish.ts var APPLE_SPANISH = { id: "apple.spanish", locale: "es", displayName: "Spanish ISO", platform: "apple", virtualLayout: "qwerty", score: 0, mapping: { KeyA: ["a", "A", "\xE5", "\xC5"], KeyB: ["b", "B", "\xDF", ""], KeyC: ["c", "C", "\xA9", " "], KeyD: ["d", "D", "\u2202", "\u2206"], KeyE: ["e", "E", "\u20AC", "\u20AC"], KeyF: ["f", "F", "\u0192", "\uFB01"], KeyG: ["g", "G", "\uF8FF", "\uFB02"], KeyH: ["h", "H", "\u2122", " "], KeyI: ["i", "I", " ", " "], KeyJ: ["j", "J", "\xB6", "\xAF"], KeyK: ["k", "K", "\xA7", "\u02C7"], KeyL: ["l", "L", " ", "\u02D8"], KeyM: ["m", "M", "\xB5", "\u02DA"], KeyN: ["n", "N", " ", "\u02D9"], KeyO: ["o", "O", "\xF8", "\xD8"], KeyP: ["p", "P", "\u03C0", "\u220F"], KeyQ: ["q", "Q", "\u0153", "\u0152"], KeyR: ["r", "R", "\xAE", " "], KeyS: ["s", "S", "\u222B", " "], KeyT: ["t", "T", "\u2020", "\u2021"], KeyU: ["u", "U", " ", " "], KeyV: ["v", "V", "\u221A", "\u25CA"], KeyW: ["w", "W", "\xE6", "\xC6"], KeyX: ["x", "X", "\u2211", "\u203A"], KeyY: ["y", "Y", "\xA5", " "], KeyZ: ["z", "Z", "\u03A9", "\u2039"], Digit1: ["1", "!", "|", "\u0131"], Digit2: ["2", '"', "@", "\u02DD"], Digit3: ["3", "\xB7", "#", "\u2022"], Digit4: ["4", "$", "\xA2", "\xA3"], Digit5: ["5", "%", "\u221E", "\u2030"], Digit6: ["6", "&", "\xAC", " "], Digit7: ["7", "/", "\xF7", "\u2044"], Digit8: ["8", "(", "\u201C", "\u2018"], Digit9: ["9", ")", "\u201D", "\u2019"], Digit0: ["0", "=", "\u2260", "\u2248"], Space: [" ", " ", " ", " "], Minus: ["'", "?", "\xB4", "\xB8"], Equal: ["\xA1", "\xBF", "\u201A", "\u02DB"], BracketLeft: ["`", "^", "[", "\u02C6"], BracketRight: ["+", "*", "]", "\xB1"], Backslash: ["\xE7", "\xC7", "}", "\xBB"], Semicolon: ["\xF1", "\xD1", "~", "\u02DC"], Quote: ["\xB4", "\xA8", "{", "\xAB"], Backquote: ["<", ">", "\u2264", "\u2265"], Comma: [",", ";", "\u201E", ""], Period: [".", ":", "\u2026", "\u2026"], Slash: ["-", "_", "\u2013", "\u2014"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], Numpad1: ["1", "1", "1", "1"], Numpad2: ["2", "2", "2", "2"], Numpad3: ["3", "3", "3", "3"], Numpad4: ["4", "4", "4", "4"], Numpad5: ["5", "5", "5", "5"], Numpad6: ["6", "6", "6", "6"], Numpad7: ["7", "7", "7", "7"], Numpad8: ["8", "8", "8", "8"], Numpad9: ["9", "9", "9", "9"], Numpad0: ["0", "0", "0", "0"], NumpadDecimal: [",", ",", ",", ","], IntlBackslash: ["\xBA", "\xAA", "\\", "\xB0"] } }; var WINDOWS_SPANISH = { id: "windows.spanish", locale: "es", displayName: "Spanish", platform: "windows", virtualLayout: "qwerty", score: 0, mapping: { KeyA: ["a", "A", "", ""], KeyB: ["b", "B", "", ""], KeyC: ["c", "C", "", ""], KeyD: ["d", "D", "", ""], KeyE: ["e", "E", "\u20AC", ""], KeyF: ["f", "F", "", ""], KeyG: ["g", "G", "", ""], KeyH: ["h", "H", "", ""], KeyI: ["i", "I", "", ""], KeyJ: ["j", "J", "", ""], KeyK: ["k", "K", "", ""], KeyL: ["l", "L", "", ""], KeyM: ["m", "M", "", ""], KeyN: ["n", "N", "", ""], KeyO: ["o", "O", "", ""], KeyP: ["p", "P", "", ""], KeyQ: ["q", "Q", "", ""], KeyR: ["r", "R", "", ""], KeyS: ["s", "S", "", ""], KeyT: ["t", "T", "", ""], KeyU: ["u", "U", "", ""], KeyV: ["v", "V", "", ""], KeyW: ["w", "W", "", ""], KeyX: ["x", "X", "", ""], KeyY: ["y", "Y", "", ""], KeyZ: ["z", "Z", "", ""], Digit1: ["1", "!", "|", ""], Digit2: ["2", '"', "@", ""], Digit3: ["3", "\xB7", "#", ""], Digit4: ["4", "$", "~", ""], Digit5: ["5", "%", "\u20AC", ""], Digit6: ["6", "&", "\xAC", ""], Digit7: ["7", "/", "", ""], Digit8: ["8", "(", "", ""], Digit9: ["9", ")", "", ""], Digit0: ["0", "=", "", ""], Space: [" ", " ", "", ""], Minus: ["'", "?", "", ""], Equal: ["\xA1", "\xBF", "", ""], BracketLeft: ["`", "^", "[", ""], BracketRight: ["+", "*", "]", ""], Backslash: ["\xE7", "\xC7", "}", ""], Semicolon: ["\xF1", "\xD1", "", ""], Quote: ["\xB4", "\xA8", "{", ""], Backquote: ["\xBA", "\xAA", "\\", ""], Comma: [",", ";", "", ""], Period: [".", ":", "", ""], Slash: ["-", "_", "", ""], NumpadDivide: ["/", "/", "", ""], NumpadMultiply: ["*", "*", "", ""], NumpadSubtract: ["-", "-", "", ""], NumpadAdd: ["+", "+", "", ""], IntlBackslash: ["<", ">", "", ""] } }; var LINUX_SPANISH = { id: "linux.spanish", locale: "es", displayName: "Spanish", platform: "linux", virtualLayout: "qwerty", score: 0, mapping: { KeyA: ["a", "A", "\xE6", "\xC6"], KeyB: ["b", "B", "\u201D", "\u2019"], KeyC: ["c", "C", "\xA2", "\xA9"], KeyD: ["d", "D", "\xF0", "\xD0"], KeyE: ["e", "E", "\u20AC", "\xA2"], KeyF: ["f", "F", "\u0111", "\xAA"], KeyG: ["g", "G", "\u014B", "\u014A"], KeyH: ["h", "H", "\u0127", "\u0126"], KeyI: ["i", "I", "\u2192", "\u0131"], KeyJ: ["j", "J", "\u0309", "\u031B"], KeyK: ["k", "K", "\u0138", "&"], KeyL: ["l", "L", "\u0142", "\u0141"], KeyM: ["m", "M", "\xB5", "\xBA"], KeyN: ["n", "N", "n", "N"], KeyO: ["o", "O", "\xF8", "\xD8"], KeyP: ["p", "P", "\xFE", "\xDE"], KeyQ: ["q", "Q", "@", "\u03A9"], KeyR: ["r", "R", "\xB6", "\xAE"], KeyS: ["s", "S", "\xDF", "\xA7"], KeyT: ["t", "T", "\u0167", "\u0166"], KeyU: ["u", "U", "\u2193", "\u2191"], KeyV: ["v", "V", "\u201C", "\u2018"], KeyW: ["w", "W", "\u0142", "\u0141"], KeyX: ["x", "X", "\xBB", ">"], KeyY: ["y", "Y", "\u2190", "\xA5"], KeyZ: ["z", "Z", "\xAB", "<"], Digit1: ["1", "!", "|", "\xA1"], Digit2: ["2", '"', "@", "\u215B"], Digit3: ["3", "\xB7", "#", "\xA3"], Digit4: ["4", "$", "~", "$"], Digit5: ["5", "%", "\xBD", "\u215C"], Digit6: ["6", "&", "\xAC", "\u215D"], Digit7: ["7", "/", "{", "\u215E"], Digit8: ["8", "(", "[", "\u2122"], Digit9: ["9", ")", "]", "\xB1"], Digit0: ["0", "=", "}", "\xB0"], Enter: ["\r", "\r", "\r", "\r"], Escape: ["\x1B", "\x1B", "\x1B", "\x1B"], Backspace: ["\b", "\b", "\b", "\b"], Tab: [" ", "", " ", ""], Space: [" ", " ", " ", " "], Minus: ["'", "?", "\\", "\xBF"], Equal: ["\xA1", "\xBF", "\u0303", "~"], BracketLeft: ["\u0300", "\u0302", "[", "\u030A"], BracketRight: ["+", "*", "]", "\u0304"], Backslash: ["\xE7", "\xC7", "}", "\u0306"], Semicolon: ["\xF1", "\xD1", "~", "\u030B"], Quote: ["\u0301", "\u0308", "{", "{"], Backquote: ["\xBA", "\xAA", "\\", "\\"], Comma: [",", ";", "\u2500", "\xD7"], Period: [".", ":", "\xB7", "\xF7"], Slash: ["-", "_", "\u0323", "\u0307"], NumpadDivide: ["/", "/", "/", "/"], NumpadMultiply: ["*", "*", "*", "*"], NumpadSubtract: ["-", "-", "-", "-"], NumpadAdd: ["+", "+", "+", "+"], NumpadEnter: ["\r", "\r", "\r", "\r"], Numpad1: ["", "1", "", "1"], Numpad2: ["", "2", "", "2"], Numpad3: ["", "3", "", "3"], Numpad4: ["", "4", "", "4"], Numpad5: ["", "5", "", "5"], Numpad6: ["", "6", "", "6"], Numpad7: ["", "7", "", "7"], Numpad8: ["", "8", "", "8"], Numpad9: ["", "9", "", "9"], Numpad0: ["", "0", "", "0"], NumpadDecimal: ["", ".", "", "."], IntlBackslash: ["<", ">", "|", "\xA6"], NumpadEqual: ["=", "=", "=", "="], NumpadComma: [".", ".", ".", "."], NumpadParenLeft: ["(", "(", "(", "("], NumpadParenRight: [")", ")", ")", ")"] } }; // src/editor/keyboard-layout.ts function keystrokeModifiersFromString(key) { const segments = key.split("+"); const result = { shift: false, alt: false, cmd: false, win: false, meta: false, ctrl: false, key: segments.pop() }; if (segments.includes("shift")) result.shift = true; if (segments.includes("alt")) result.alt = true; if (segments.includes("ctrl")) result.ctrl = true; if (segments.includes("cmd")) result.cmd = true; if (segments.includes("win")) result.win = true; if (segments.includes("meta")) result.meta = true; return result; } function keystrokeModifiersToString(key) { let result = ""; if (key.shift) result += "shift+"; if (key.alt) result += "alt+"; if (key.ctrl) result += "ctrl+"; if (key.cmd) result += "cmd+"; if (key.win) result += "win+"; if (key.meta) result += "meta+"; return result + key.key; } var BASE_LAYOUT_MAPPING = { enter: "[Enter]", escape: "[Escape]", backspace: "[Backspace]", tab: "[Tab]", space: "[Space]", pausebreak: "[Pause]", insert: "[Insert]", home: "[Home]", pageup: "[PageUp]", delete: "[Delete]", end: "[End]", pagedown: "[PageDown]", right: "[ArrowRight]", left: "[ArrowLeft]", down: "[ArrowDown]", up: "[ArrowUp]", numpad0: "[Numpad0]", numpad1: "[Numpad1]", numpad2: "[Numpad2]", numpad3: "[Numpad3]", numpad4: "[Numpad4]", numpad5: "[Numpad5]", numpad6: "[Numpad6]", numpad7: "[Numpad7]", numpad8: "[Numpad8]", numpad9: "[Numpad9]", "numpad_divide": "[NumpadDivide]", "numpad_multiply": "[NumpadMultiply]", "numpad_subtract": "[NumpadSubtract]", "numpad_add": "[NumpadAdd]", "numpad_decimal": "[NumpadDecimal]", "numpad_separator": "[NumpadComma]", capslock: "[Capslock]", f1: "[F1]", f2: "[F2]", f3: "[F3]", f4: "[F4]", f5: "[F5]", f6: "[F6]", f7: "[F7]", f8: "[F8]", f9: "[F9]", f10: "[F10]", f11: "[F11]", f12: "[F12]", f13: "[F13]", f14: "[F14]", f15: "[F15]", f16: "[F16]", f17: "[F17]", f18: "[F18]", f19: "[F19]" }; var gKeyboardLayouts = []; var gKeyboardLayout; function platform() { switch (osPlatform()) { case "macos": case "ios": return "apple"; case "windows": return "windows"; } return "linux"; } function register(layout) { if (!layout.platform || layout.platform === platform()) gKeyboardLayouts.push(layout); } function getCodeForKey(k, layout) { var _a3; const result = { shift: false, alt: false, cmd: false, win: false, meta: false, ctrl: false, key: "" }; if (!k) return result; for (const [key, value] of Object.entries(layout.mapping)) { if (value[0] === k) { result.key = `[${key}]`; return result; } if (value[1] === k) { result.shift = true; result.key = `[${key}]`; return result; } if (value[2] === k) { result.alt = true; result.key = `[${key}]`; return result; } if (value[3] === k) { result.shift = true; result.alt = true; result.key = `[${key}]`; return result; } } result.key = (_a3 = BASE_LAYOUT_MAPPING[k]) != null ? _a3 : ""; return result; } function normalizeKeyboardEvent(evt) { if (evt.code) return evt; const mapping = Object.entries(getActiveKeyboardLayout().mapping); let altKey = false; let shiftKey = false; let code = ""; for (let index = 0; index < 4; index++) { for (const [key, value] of mapping) { if (value[index] === evt.key) { code = key; if (index === 3) { altKey = true; shiftKey = true; } else if (index === 2) altKey = true; else if (index === 1) shiftKey = true; break; } } if (code) break; } return new KeyboardEvent(evt.type, __spreadProps(__spreadValues({}, evt), { altKey, shiftKey, code })); } function validateKeyboardLayout(evt) { var _a3, _b3; if (!evt) return; if (evt.key === "Unidentified") return; if (evt.key === "Dead") return; const index = evt.shiftKey && evt.altKey ? 3 : evt.altKey ? 2 : evt.shiftKey ? 1 : 0; for (const layout of gKeyboardLayouts) { if (((_a3 = layout.mapping[evt.code]) == null ? void 0 : _a3[index]) === evt.key) { layout.score += 1; } else if ((_b3 = layout.mapping[evt.code]) == null ? void 0 : _b3[index]) { layout.score = 0; } } gKeyboardLayouts.sort((a, b) => b.score - a.score); } function setKeyboardLayoutLocale(locale) { gKeyboardLayout = gKeyboardLayouts.find((x) => locale.startsWith(x.locale)); } function getActiveKeyboardLayout() { return gKeyboardLayout != null ? gKeyboardLayout : gKeyboardLayouts[0]; } function getDefaultKeyboardLayout() { switch (platform()) { case "apple": return APPLE_ENGLISH; case "windows": return WINDOWS_ENGLISH; case "linux": return LINUX_ENGLISH; } return APPLE_ENGLISH; } switch (platform()) { case "apple": register(APPLE_ENGLISH); register(APPLE_FRENCH); register(APPLE_SPANISH); register(APPLE_GERMAN); break; case "windows": register(WINDOWS_ENGLISH); register(WINDOWS_FRENCH); register(WINDOWS_SPANISH); register(WINDOWS_GERMAN); break; case "linux": register(LINUX_ENGLISH); register(LINUX_FRENCH); register(LINUX_SPANISH); register(LINUX_GERMAN); break; } register(DVORAK); // src/ui/events/keyboard.ts function getKeybindingMarkup(keybinding) { var _a3; const useGlyph = /macos|ios/.test(osPlatform()); const segments = keybinding.split("+"); let result = ""; for (const segment of segments) { if (result) { result += useGlyph ? "\u2009" : '+'; } if (segment.startsWith("[Key")) result += segment.slice(4, 5); else if (segment.startsWith("Key")) result += segment.slice(3, 4); else if (segment.startsWith("[Digit")) result += segment.slice(6, 7); else if (segment.startsWith("Digit")) result += segment.slice(5, 6); else { result += (_a3 = { "cmd": "\u2318", "meta": useGlyph ? "\u2318" : "Ctrl", "shift": useGlyph ? "\u21E7" : "Shift", "alt": useGlyph ? "\u2325" : "Alt", "ctrl": useGlyph ? "\u2303" : "Ctrl", "\n": useGlyph ? "\u23CE" : "Return", "[return]": useGlyph ? "\u23CE" : "Return", "[enter]": useGlyph ? "\u2324" : "Enter", "[tab]": useGlyph ? "\u21E5" : "Tab", // 'Esc': useSymbol ? '\u238b' : 'esc', "[escape]": "Esc", "[backspace]": useGlyph ? "\u232B" : "Backspace", "[delete]": useGlyph ? "\u2326" : "Del", "[pageup]": useGlyph ? "\u21DE" : "Page Up", "[pagedown]": useGlyph ? "\u21DF" : "Page Down", "[home]": useGlyph ? "\u2912" : "Home", "[end]": useGlyph ? "\u2913" : "End", "[space]": "Space", "[equal]": "=", "[minus]": "-", "[comma]": ",", "[slash]": "/", "[backslash]": "\\", "[bracketleft]": "[", "[bracketright]": "]", "semicolon": ";", "period": ".", "comma": ",", "minus": "-", "equal": "=", "quote": "'", "backslash": "\\", "intlbackslash": "\\", "backquote": "`", "slash": "/", "numpadmultiply": "* 🔢", "numpaddivide": "/ 🔢", // Numeric keypad "numpadsubtract": "- 🔢", "numpadadd": "+ 🔢", "numpaddecimal": ". 🔢", "numpadcomma": ", 🔢", "help": "help", "left": "\u21E0", "up": "\u21E1", "right": "\u21E2", "down": "\u21E3", "[arrowleft]": "\u21E0", "[arrowup]": "\u21E1", "[arrowright]": "\u21E2", "[arrowdown]": "\u21E3" }[segment.toLowerCase()]) != null ? _a3 : segment.toUpperCase(); } } return result; } // src/ui/events/utils.ts function eventLocation(evt) { if (evt instanceof MouseEvent || evt instanceof PointerEvent) return { x: evt.clientX, y: evt.clientY }; if (evt instanceof TouchEvent) { const result = [...evt.touches].reduce( (acc, x) => ({ x: acc.x + x.clientX, y: acc.y + x.clientY }), { x: 0, y: 0 } ); const l = evt.touches.length; return { x: result.x / l, y: result.y / l }; } return void 0; } function keyboardModifiersFromEvent(ev) { const result = { alt: false, control: false, shift: false, meta: false }; if (ev instanceof MouseEvent || ev instanceof PointerEvent || ev instanceof TouchEvent || ev instanceof KeyboardEvent) { if (ev.altKey) result.alt = true; if (ev.ctrlKey) result.control = true; if (ev.metaKey) result.meta = true; if (ev.shiftKey) result.shift = true; } return result; } function equalKeyboardModifiers(a, b) { if (!a && b || a && !b) return false; if (!a || !b) return true; return a.alt === b.alt && a.control === b.control && a.shift === b.shift && a.meta === b.meta; } var PRINTABLE_KEYCODE = /* @__PURE__ */ new Set([ "Backquote", // Japanese keyboard: hankaku/zenkaku/kanji key, which is non-printable "Digit0", "Digit1", "Digit2", "Digit3", "Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9", "Minus", "Equal", "IntlYen", // Japanese Keyboard. Russian keyboard: \/ "KeyQ", // AZERTY keyboard: labeled 'a' "KeyW", // AZERTY keyboard: labeled 'z' "KeyE", "KeyR", "KeyT", "KeyY", // QWERTZ keyboard: labeled 'z' "KeyU", "KeyI", "KeyO", "KeyP", "BracketLeft", "BracketRight", "Backslash", // May be labeled #~ on UK 102 keyboard "KeyA", // AZERTY keyboard: labeled 'q' "KeyS", "KeyD", "KeyF", "KeyG", "KeyH", "KeyJ", "KeyK", "KeyL", "Semicolon", "Quote", "IntlBackslash", // QWERTZ keyboard '><' "KeyZ", // AZERTY: 'w', QWERTZ: 'y' "KeyX", "KeyC", "KeyV", "KeyB", "KeyN", "KeyM", "Comma", "Period", "Slash", "IntlRo", // Japanse keyboard '\ろ' "Space", "Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9", "NumpadAdd", "NumpadComma", "NumpadDecimal", "NumpadDivide", "NumpadEqual", "NumpadHash", "NumpadMultiply", "NumpadParenLeft", "NumpadParenRight", "NumpadStar", "NumpadSubstract" ]); function mightProducePrintableCharacter(evt) { if (evt.ctrlKey || evt.metaKey) return false; if (["Dead", "Process"].includes(evt.key)) return false; if (evt.code === "") return true; return PRINTABLE_KEYCODE.has(evt.code); } function deepActiveElement() { var _a3; let a = document.activeElement; while ((_a3 = a == null ? void 0 : a.shadowRoot) == null ? void 0 : _a3.activeElement) a = a.shadowRoot.activeElement; return a; } // src/ui/utils/scrim.ts var Scrim = class _Scrim { static get scrim() { if (!_Scrim._scrim) _Scrim._scrim = new _Scrim(); return _Scrim._scrim; } static open(options) { _Scrim.scrim.open(options); } static close() { _Scrim.scrim.close(); } static get state() { return _Scrim.scrim.state; } static get element() { return _Scrim.scrim.element; } /** * - If `lightDismiss` is true, the scrim is closed if the * user clicks on the scrim. That's the behavior for menus, for example. * When you need a fully modal situation until the user has made an * explicit choice (validating cookie usage, for example), set * `lightDismiss` to fallse. */ constructor(options) { var _a3, _b3; this.lightDismiss = (_a3 = options == null ? void 0 : options.lightDismiss) != null ? _a3 : true; this.translucent = (_b3 = options == null ? void 0 : options.translucent) != null ? _b3 : false; this.state = "closed"; } get element() { if (this._element) return this._element; const element = document.createElement("div"); element.setAttribute("role", "presentation"); element.style.position = "fixed"; element.style.contain = "content"; element.style.top = "0"; element.style.left = "0"; element.style.right = "0"; element.style.bottom = "0"; element.style.zIndex = "var(--scrim-zindex, 10099)"; element.style.outline = "none"; if (this.translucent) { element.style.background = "rgba(255, 255, 255, .2)"; element.style["backdropFilter"] = "contrast(40%)"; } else element.style.background = "transparent"; this._element = element; return element; } open(options) { var _a3; if (this.state !== "closed") return; this.state = "opening"; this.onDismiss = options == null ? void 0 : options.onDismiss; this.savedActiveElement = deepActiveElement(); const { element } = this; ((_a3 = options == null ? void 0 : options.root) != null ? _a3 : document.body).appendChild(element); element.addEventListener("click", this); document.addEventListener("touchmove", this, false); document.addEventListener("scroll", this, false); const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; this.savedMarginRight = document.body.style.marginRight; this.savedOverflow = document.body.style.overflow; document.body.style.overflow = "hidden"; const marginRight = Number.parseFloat( getComputedStyle(document.body).marginRight ); document.body.style.marginRight = `${marginRight + scrollbarWidth}px`; if (options == null ? void 0 : options.child) element.append(options.child); this.state = "open"; } close() { var _a3, _b3, _c2, _d2; if (this.state !== "open") { console.assert(this.element.parentElement !== null); return; } this.state = "closing"; if (typeof this.onDismiss === "function") this.onDismiss(); this.onDismiss = void 0; const { element } = this; element.removeEventListener("click", this); document.removeEventListener("touchmove", this, false); document.removeEventListener("scroll", this, false); element.remove(); document.body.style.overflow = (_a3 = this.savedOverflow) != null ? _a3 : ""; document.body.style.marginRight = (_b3 = this.savedMarginRight) != null ? _b3 : ""; if (deepActiveElement() !== this.savedActiveElement) (_d2 = (_c2 = this.savedActiveElement) == null ? void 0 : _c2.focus) == null ? void 0 : _d2.call(_c2); element.innerHTML = ""; this.state = "closed"; } handleEvent(ev) { if (this.lightDismiss) { if (ev.target === this._element && ev.type === "click") { this.close(); ev.preventDefault(); ev.stopPropagation(); } else if (ev.target === document && (ev.type === "touchmove" || ev.type === "scroll")) { this.close(); ev.preventDefault(); ev.stopPropagation(); } } } }; // src/editor/keyboard.ts function delegateKeyboardEvents(keyboardSink, element, delegate) { let keydownEvent = null; let keypressEvent = null; let compositionInProgress = false; let focusInProgress = false; let blurInProgress = false; const controller = new AbortController(); const signal = controller.signal; keyboardSink.addEventListener( "keydown", (event) => { if (compositionInProgress || event.key === "Process" || event.code === "CapsLock" || /(Control|Meta|Alt|Shift)(Left|Right)/.test(event.code)) { keydownEvent = null; return; } keydownEvent = event; keypressEvent = null; if (!delegate.onKeystroke(event)) keydownEvent = null; else keyboardSink.textContent = ""; }, { capture: true, signal } ); keyboardSink.addEventListener( "keypress", (event) => { if (compositionInProgress) return; if (keydownEvent && keypressEvent) delegate.onKeystroke(keydownEvent); keypressEvent = event; }, { capture: true, signal } ); keyboardSink.addEventListener( "compositionstart", (event) => { keyboardSink.textContent = ""; compositionInProgress = true; delegate.onCompositionStart(event.data); }, { capture: true, signal } ); keyboardSink.addEventListener( "compositionupdate", (ev) => { if (!compositionInProgress) return; delegate.onCompositionUpdate(ev.data); }, { capture: true, signal } ); keyboardSink.addEventListener( "compositionend", (ev) => { keyboardSink.textContent = ""; if (!compositionInProgress) return; compositionInProgress = false; delegate.onCompositionEnd(ev.data); }, { capture: true, signal } ); keyboardSink.addEventListener( "beforeinput", (ev) => ev.stopImmediatePropagation(), { signal } ); keyboardSink.addEventListener( "input", (ev) => { var _a3; if (compositionInProgress) return; keyboardSink.textContent = ""; if (ev.inputType === "insertCompositionText") return; if (ev.inputType === "insertFromPaste") { ev.preventDefault(); ev.stopPropagation(); return; } delegate.onInput((_a3 = ev.data) != null ? _a3 : ""); ev.preventDefault(); ev.stopPropagation(); }, { signal } ); keyboardSink.addEventListener( "paste", (event) => { keyboardSink.focus({ preventScroll: true }); keyboardSink.textContent = ""; if (!delegate.onPaste(event)) event.preventDefault(); event.stopImmediatePropagation(); }, { signal } ); keyboardSink.addEventListener("cut", (ev) => delegate.onCut(ev), { capture: true, signal }); keyboardSink.addEventListener("copy", (ev) => delegate.onCopy(ev), { capture: true, signal }); keyboardSink.addEventListener( "blur", (event) => { var _a3, _b3; if (((_b3 = (_a3 = event["relatedTarget"]) == null ? void 0 : _a3["_mathfield"]) == null ? void 0 : _b3["element"]) === element) { keyboardSink.focus({ preventScroll: true }); event.preventDefault(); event.stopPropagation(); return; } const scrimState = Scrim.state; if (scrimState === "open" || scrimState === "opening") { event.preventDefault(); event.stopPropagation(); return; } if (event.relatedTarget === event.target.getRootNode().host) { event.preventDefault(); event.stopPropagation(); return; } if (blurInProgress || focusInProgress) return; blurInProgress = true; keydownEvent = null; keypressEvent = null; delegate.onBlur(); blurInProgress = false; }, { capture: true, signal } ); keyboardSink.addEventListener( "focus", (_evt) => { if (blurInProgress || focusInProgress) return; focusInProgress = true; delegate.onFocus(); focusInProgress = false; }, { capture: true, signal } ); return { dispose: () => controller.abort(), cancelComposition: () => { if (!compositionInProgress) return; keyboardSink.blur(); requestAnimationFrame(() => keyboardSink.focus({ preventScroll: true })); }, blur: () => { if (typeof keyboardSink.blur === "function") keyboardSink.blur(); }, focus: () => { if (!focusInProgress && typeof keyboardSink.focus === "function") keyboardSink.focus({ preventScroll: true }); }, hasFocus: () => { return deepActiveElement() === keyboardSink; }, setAriaLabel: (value) => keyboardSink.setAttribute("aria-label", value), setValue: (value) => { var _a3; keyboardSink.textContent = value; keyboardSink.style.left = `-1000px`; (_a3 = window.getSelection()) == null ? void 0 : _a3.selectAllChildren(keyboardSink); }, moveTo: (x, y) => { keyboardSink.style.top = `${y}px`; keyboardSink.style.left = `${x}px`; } }; } function keyboardEventToChar(evt) { var _a3; if (!evt || !mightProducePrintableCharacter(evt)) return ""; let result; if (evt.key === "Unidentified") { if (evt.target) result = evt.target.value; } result = (_a3 = result != null ? result : evt.key) != null ? _a3 : evt.code; if (/^(Dead|Return|Enter|Tab|Escape|Delete|PageUp|PageDown|Home|End|Help|ArrowLeft|ArrowRight|ArrowUp|ArrowDown)$/.test( result )) result = ""; return result; } function keyboardEventToString(evt) { evt = normalizeKeyboardEvent(evt); const modifiers = []; if (evt.ctrlKey) modifiers.push("ctrl"); if (evt.metaKey) modifiers.push("meta"); if (evt.altKey) modifiers.push("alt"); if (evt.shiftKey) modifiers.push("shift"); if (modifiers.length === 0) return `[${evt.code}]`; modifiers.push(`[${evt.code}]`); return modifiers.join("+"); } // src/editor/keybindings.ts function matchPlatform(p) { if (isBrowser()) { const plat = osPlatform(); const isNeg = p.startsWith("!"); const isMatch = p.endsWith(plat); if (isNeg && !isMatch) return true; if (!isNeg && isMatch) return true; } if (p === "!other") return false; return p === "other"; } function getCommandForKeybinding(keybindings, mode, evt) { if (keybindings.length === 0) return ""; const keystroke = keystrokeModifiersToString( keystrokeModifiersFromString(keyboardEventToString(evt)) ); const altKeystroke = keystrokeModifiersToString({ key: evt.key, shift: evt.shiftKey, alt: evt.altKey, ctrl: evt.ctrlKey, meta: evt.metaKey || evt.ctrlKey && /macos|ios/.test(osPlatform()), cmd: false, win: false }); for (let i = keybindings.length - 1; i >= 0; i--) { if (keybindings[i].key === keystroke || keybindings[i].key === altKeystroke) { if (!keybindings[i].ifMode || keybindings[i].ifMode === mode) return keybindings[i].command; } } return ""; } function commandToString(command) { let result = command; if (isArray(result)) { result = result.length > 0 ? result[0] + "(" + result.slice(1).join("") + ")" : ""; } return result; } function getKeybindingsForCommand(keybindings, command) { let result = []; if (typeof command === "string") { const candidate = REVERSE_KEYBINDINGS[command]; if (isArray(candidate)) result = candidate.slice(); else if (candidate) result.push(candidate); } const normalizedCommand = commandToString(command); const regex = new RegExp( "^" + normalizedCommand.replace("\\", "\\\\").replace("|", "\\|").replace("*", "\\*").replace("$", "\\$").replace("^", "\\^") + "([^*a-zA-Z]|$)" ); for (const keybinding of keybindings) { if (regex.test(commandToString(keybinding.command))) result.push(keybinding.key); } return result.map(getKeybindingMarkup); } function normalizeKeybinding(keybinding, layout) { if (keybinding.ifPlatform && !/^!?(macos|windows|android|ios|chromeos|other)$/.test( keybinding.ifPlatform )) { throw new Error( `Unexpected platform "${keybinding.ifPlatform}" for keybinding ${keybinding.key}` ); } if (keybinding.ifLayout !== void 0 && (layout.score === 0 || !keybinding.ifLayout.includes(layout.id))) return void 0; const modifiers = keystrokeModifiersFromString(keybinding.key); let platform2 = keybinding.ifPlatform; if (modifiers.cmd) { if (platform2 && platform2 !== "macos" && platform2 !== "ios") { throw new Error( 'Unexpected "cmd" modifier with platform "' + platform2 + '"\n"cmd" modifier can only be used with macOS or iOS platform.' ); } if (!platform2) platform2 = osPlatform() === "ios" ? "ios" : "macos"; modifiers.win = false; modifiers.cmd = false; modifiers.meta = true; } if (modifiers.win) { if (platform2 && platform2 !== "windows") { throw new Error( 'Unexpected "win" modifier with platform "' + platform2 + '"\n"win" modifier can only be used with Windows platform.' ); } platform2 = "windows"; modifiers.win = false; modifiers.cmd = false; modifiers.meta = true; } if (platform2 && !matchPlatform(platform2)) return void 0; if (/^\[.+\]$/.test(modifiers.key)) return __spreadProps(__spreadValues({}, keybinding), { key: keystrokeModifiersToString(modifiers) }); const code = getCodeForKey(modifiers.key, layout); if (!code) return __spreadProps(__spreadValues({}, keybinding), { key: keystrokeModifiersToString(modifiers) }); if (code.shift && modifiers.shift || code.alt && modifiers.alt) { throw new Error( `The keybinding ${keybinding.key} (${selectorToString( keybinding.command )}) is conflicting with the key combination ${keystrokeModifiersToString( code )} using the ${layout.displayName} keyboard layout` ); } code.shift = code.shift || modifiers.shift; code.alt = code.alt || modifiers.alt; code.meta = modifiers.meta; code.ctrl = modifiers.ctrl; return __spreadProps(__spreadValues({}, keybinding), { key: keystrokeModifiersToString(code) }); } function selectorToString(selector) { if (Array.isArray(selector)) { const sel = [...selector]; return sel.shift() + "(" + sel.map((x) => typeof x === "string" ? `"${x}"` : x.toString()).join(", ") + ")"; } return selector; } function normalizeKeybindings(keybindings, layout) { const errors = []; const result = []; for (const x of keybindings) { try { const binding = normalizeKeybinding(x, layout); if (!binding) continue; const conflict = result.find( (x2) => x2.key === binding.key && x2.ifMode === binding.ifMode ); if (conflict) { throw new Error( `Ambiguous key binding ${x.key} (${selectorToString( x.command )}) matches ${conflict.key} (${selectorToString( conflict.command )}) with the ${layout.displayName} keyboard layout` ); } result.push(binding); } catch (error) { if (error instanceof Error) errors.push(error.message); } } return [result, errors]; } // src/editor-mathfield/mode-editor-latex.ts var LatexModeEditor = class extends ModeEditor { constructor() { super("latex"); } createAtom(command) { return new LatexAtom(command); } onPaste(mathfield, data) { if (!data) return false; const text = typeof data === "string" ? data : data.getData("application/x-latex") || data.getData("text/plain"); if (text && mathfield.model.contentWillChange({ inputType: "insertFromPaste", data: text })) { mathfield.stopCoalescingUndo(); mathfield.stopRecording(); if (this.insert(mathfield.model, text)) { mathfield.startRecording(); mathfield.snapshot("paste"); mathfield.model.contentDidChange({ inputType: "insertFromPaste" }); requestUpdate(mathfield); } mathfield.startRecording(); return true; } return false; } insert(model, text, options) { if (!model.contentWillChange({ data: text, inputType: "insertText" })) return false; if (!options) options = {}; if (!options.insertionMode) options.insertionMode = "replaceSelection"; if (!options.selectionMode) options.selectionMode = "placeholder"; const { silenceNotifications } = model; if (options.silenceNotifications) model.silenceNotifications = true; const saveSilenceNotifications = model.silenceNotifications; model.silenceNotifications = true; if (options.insertionMode === "replaceSelection" && !model.selectionIsCollapsed) model.deleteAtoms(range(model.selection)); else if (options.insertionMode === "replaceAll") { model.root.setChildren([], "body"); model.position = 0; } else if (options.insertionMode === "insertBefore") model.collapseSelection("backward"); else if (options.insertionMode === "insertAfter") model.collapseSelection("forward"); const newAtoms = []; for (const c of text) if (COMMAND_MODE_CHARACTERS.test(c)) newAtoms.push(new LatexAtom(c)); let cursor = model.at(model.position); if (cursor instanceof LatexGroupAtom) cursor = cursor.lastChild; if (!(cursor.parent instanceof LatexGroupAtom)) { const group = new LatexGroupAtom(""); cursor.parent.addChildAfter(group, cursor); cursor = group.firstChild; } const lastNewAtom = cursor.parent.addChildrenAfter(newAtoms, cursor); model.silenceNotifications = saveSilenceNotifications; if (options.selectionMode === "before") { } else if (options.selectionMode === "item") model.setSelection(model.anchor, model.offsetOf(lastNewAtom)); else if (lastNewAtom) model.position = model.offsetOf(lastNewAtom); model.contentDidChange({ data: text, inputType: "insertText" }); model.silenceNotifications = silenceNotifications; return true; } }; function getLatexGroup(model) { return model.atoms.find((x) => x.type === "latexgroup"); } function getLatexGroupBody(model) { var _a3, _b3; const atom = model.atoms.find((x) => x.type === "latexgroup"); if (!atom) return []; return (_b3 = (_a3 = atom.body) == null ? void 0 : _a3.filter((x) => x.type === "latex")) != null ? _b3 : []; } function getCommandSuggestionRange(model, options) { var _a3; let start = 0; let found = false; const last = Number.isFinite(options == null ? void 0 : options.before) ? (_a3 = options == null ? void 0 : options.before) != null ? _a3 : 0 : model.lastOffset; while (start <= last && !found) { const atom = model.at(start); found = atom instanceof LatexAtom && atom.isSuggestion; if (!found) start++; } if (!found) return [void 0, void 0]; let end = start; let done = false; while (end <= last && !done) { const atom = model.at(end); done = !(atom instanceof LatexAtom && atom.isSuggestion); if (!done) end++; } return [start - 1, end - 1]; } new LatexModeEditor(); // src/editor-mathfield/autocomplete.ts function removeSuggestion(mathfield) { const group = getLatexGroupBody(mathfield.model).filter( (x) => x.isSuggestion ); if (group.length === 0) return; mathfield.model.position = mathfield.model.offsetOf(group[0].leftSibling); for (const atom of group) atom.parent.removeChild(atom); } function updateAutocomplete(mathfield, options) { var _a3; const { model } = mathfield; removeSuggestion(mathfield); for (const atom2 of getLatexGroupBody(model)) atom2.isError = false; if (!model.selectionIsCollapsed || mathfield.options.popoverPolicy === "off") { hideSuggestionPopover(mathfield); return; } const commandAtoms = []; let atom = model.at(model.position); while (atom && atom instanceof LatexAtom && /^[a-zA-Z\*]$/.test(atom.value)) atom = atom.leftSibling; if (atom && atom instanceof LatexAtom && atom.value === "\\") { commandAtoms.push(atom); atom = atom.rightSibling; while (atom && atom instanceof LatexAtom && /^[a-zA-Z\*]$/.test(atom.value)) { commandAtoms.push(atom); atom = atom.rightSibling; } } const command = commandAtoms.map((x) => x.value).join(""); const suggestions = suggest(mathfield, command); if (suggestions.length === 0) { if (/^\\[a-zA-Z\*]+$/.test(command)) for (const atom2 of commandAtoms) atom2.isError = true; hideSuggestionPopover(mathfield); return; } const index = (_a3 = options == null ? void 0 : options.atIndex) != null ? _a3 : 0; mathfield.suggestionIndex = index < 0 ? suggestions.length - 1 : index % suggestions.length; const suggestion = suggestions[mathfield.suggestionIndex]; if (suggestion !== command) { const lastAtom = commandAtoms[commandAtoms.length - 1]; lastAtom.parent.addChildrenAfter( [...suggestion.slice(command.length - suggestion.length)].map( (x) => new LatexAtom(x, { isSuggestion: true }) ), lastAtom ); render(mathfield, { interactive: true }); } showSuggestionPopover(mathfield, suggestions); } function acceptCommandSuggestion(model) { const [from, to] = getCommandSuggestionRange(model, { before: model.position }); if (from === void 0 || to === void 0) return false; let result = false; model.getAtoms([from, to]).forEach((x) => { if (x.isSuggestion) { x.isSuggestion = false; result = true; } }); return result; } function complete(mathfield, completion = "accept", options) { var _a3, _b3; hideSuggestionPopover(mathfield); const latexGroup = getLatexGroup(mathfield.model); if (!latexGroup) return false; if (completion === "accept-suggestion" || completion === "accept-all") { const suggestions = getLatexGroupBody(mathfield.model).filter( (x) => x.isSuggestion ); if (suggestions.length !== 0) { for (const suggestion of suggestions) suggestion.isSuggestion = false; mathfield.model.position = mathfield.model.offsetOf( suggestions[suggestions.length - 1] ); } if (completion === "accept-suggestion") return suggestions.length !== 0; } const body = getLatexGroupBody(mathfield.model).filter( (x) => !x.isSuggestion ); const latex = body.map((x) => x.value).join(""); const newPos = latexGroup.leftSibling; latexGroup.parent.removeChild(latexGroup); mathfield.model.position = mathfield.model.offsetOf(newPos); mathfield.switchMode((_a3 = options == null ? void 0 : options.mode) != null ? _a3 : "math"); if (completion === "reject") return true; ModeEditor.insert(mathfield.model, latex, { selectionMode: ((_b3 = options == null ? void 0 : options.selectItem) != null ? _b3 : false) ? "item" : "placeholder", format: "latex", mode: "math" }); mathfield.snapshot(); mathfield.model.announce("replacement"); mathfield.switchMode("math"); return true; } // src/common/shared-element.ts function getSharedElement(id) { var _a3; let result = document.getElementById(id); if (result) { result.dataset.refcount = Number( Number.parseInt((_a3 = result.dataset.refcount) != null ? _a3 : "0") + 1 ).toString(); } else { result = document.createElement("div"); result.setAttribute("aria-hidden", "true"); result.dataset.refcount = "1"; result.id = id; document.body.append(result); } return result; } function releaseSharedElement(id) { var _a3; const element = document.getElementById(id); if (!element) return; const refcount = Number.parseInt( (_a3 = element.getAttribute("data-refcount")) != null ? _a3 : "0" ); if (refcount <= 1) element.remove(); else element.dataset.refcount = Number(refcount - 1).toString(); } // src/editor/suggestion-popover.ts function latexToMarkup(mf, latex) { const context = new Context({ from: mf.context }); const root = new Atom({ mode: "math", type: "root", body: parseLatex(latex, { context }) }); const box = coalesce( applyInterBoxSpacing( new Box(root.render(context), { classes: "ML__base" }), context ) ); return makeStruts(box, { classes: "ML__latex" }).toMarkup(); } function showSuggestionPopover(mf, suggestions) { var _a3; if (suggestions.length === 0) { hideSuggestionPopover(mf); return; } let template = ""; for (const [i, suggestion] of suggestions.entries()) { const command = suggestion; const commandMarkup = latexToMarkup(mf, suggestion); const keybinding = getKeybindingsForCommand(mf.keybindings, command).join( "
" ); template += `
  • ${command}${commandMarkup}`; if (keybinding) template += `${keybinding}`; template += "
  • "; } const panel = createSuggestionPopover(mf, `
      ${template}
    `); if (isSuggestionPopoverVisible()) { (_a3 = panel.querySelector(".ML__popover__current")) == null ? void 0 : _a3.scrollIntoView({ block: "nearest", inline: "nearest" }); } setTimeout(() => { var _a4; if (panel && !isSuggestionPopoverVisible()) { panel.classList.add("is-visible"); updateSuggestionPopoverPosition(mf); (_a4 = panel.querySelector(".ML__popover__current")) == null ? void 0 : _a4.scrollIntoView({ block: "nearest", inline: "nearest" }); } }, 32); } function isSuggestionPopoverVisible() { const panel = document.getElementById("mathlive-suggestion-popover"); if (!panel) return false; return panel.classList.contains("is-visible"); } function updateSuggestionPopoverPosition(mf, options) { var _a3; if (!mf.element || mf.element.mathfield !== mf) return; if (!isSuggestionPopoverVisible()) return; if (((_a3 = mf.model.at(mf.model.position)) == null ? void 0 : _a3.type) !== "latex") { hideSuggestionPopover(mf); return; } if (options == null ? void 0 : options.deferred) { setTimeout(() => updateSuggestionPopoverPosition(mf), 32); return; } const position = getCaretPoint(mf.field); if (!position) return; const viewportHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; const viewportWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; const scrollbarHeight = window.innerHeight - document.documentElement.clientHeight; const virtualkeyboardHeight = window.mathVirtualKeyboard.boundingRect.height; const panel = document.getElementById("mathlive-suggestion-popover"); if (position.x + panel.offsetWidth / 2 > viewportWidth - scrollbarWidth) { panel.style.left = `${viewportWidth - panel.offsetWidth - scrollbarWidth}px`; } else if (position.x - panel.offsetWidth / 2 < 0) panel.style.left = "0"; else panel.style.left = `${position.x - panel.offsetWidth / 2}px`; const spaceAbove = position.y - position.height; const spaceBelow = viewportHeight - scrollbarHeight - virtualkeyboardHeight - position.y; if (spaceBelow < spaceAbove) { panel.classList.add("ML__popover--reverse-direction"); panel.classList.remove("top-tip"); panel.classList.add("bottom-tip"); panel.style.top = `${position.y - position.height - panel.offsetHeight - 15}px`; } else { panel.classList.remove("ML__popover--reverse-direction"); panel.classList.add("top-tip"); panel.classList.remove("bottom-tip"); panel.style.top = `${position.y + 15}px`; } } function hideSuggestionPopover(mf) { mf.suggestionIndex = 0; const panel = document.getElementById("mathlive-suggestion-popover"); if (panel) { panel.classList.remove("is-visible"); panel.innerHTML = ""; } } function createSuggestionPopover(mf, html) { let panel = document.getElementById("mathlive-suggestion-popover"); if (!panel) { panel = getSharedElement("mathlive-suggestion-popover"); injectStylesheet("suggestion-popover"); injectStylesheet("core"); panel.addEventListener("pointerdown", (ev) => ev.preventDefault()); panel.addEventListener("click", (ev) => { let el = ev.target; while (el && !el.dataset.command) el = el.parentElement; if (!el) return; complete(mf, "reject"); ModeEditor.insert(mf.model, el.dataset.command, { selectionMode: "placeholder", format: "latex", mode: "math" }); mf.dirty = true; mf.focus(); }); } panel.innerHTML = window.MathfieldElement.createHTML(html); return panel; } function disposeSuggestionPopover() { if (!document.getElementById("mathlive-suggestion-popover")) return; releaseSharedElement("mathlive-suggestion-popover"); releaseStylesheet("suggestion-popover"); releaseStylesheet("core"); } // src/common/script-url.ts function getFileUrl() { const stackTraceFrames = String(new Error().stack).replace(/^Error.*\n/, "").split("\n"); if (stackTraceFrames.length === 0) { console.error( `Can't use relative paths to specify assets location because the sourcefile location could not be determined (unexpected stack trace format "${new Error().stack}").` ); return ""; } let callerFrame = stackTraceFrames[1]; let m = callerFrame.match(/http.*\.ts[\?:]/); if (m) { callerFrame = stackTraceFrames[2]; } m = callerFrame.match(/(https?:.*):[0-9]+:[0-9]+/); if (!m) { m = callerFrame.match(/at (.*(\.ts))[\?:]/); if (!m) m = callerFrame.match(/at (.*(\.mjs|\.js))[\?:]/); } if (!m) { console.error(stackTraceFrames); console.error( `Can't use relative paths to specify assets location because the source file location could not be determined (unexpected location "${callerFrame}").` ); return ""; } return m[1]; } var gResolvedScriptUrl = null; var _a, _b; var gScriptUrl = ((_b = (_a = globalThis == null ? void 0 : globalThis.document) == null ? void 0 : _a.currentScript) == null ? void 0 : _b.src) || getFileUrl(); async function resolveUrl(url) { if (/^(?:[a-z+]+:)?\/\//i.test(url)) return new URL(url).href; if (gResolvedScriptUrl === null) { try { const response = await fetch(gScriptUrl, { method: "HEAD" }); if (response.status === 200) gResolvedScriptUrl = response.url; } catch (e) { console.error(`Invalid URL "${url}" (relative to "${gScriptUrl}")`); } } return new URL(url, gResolvedScriptUrl != null ? gResolvedScriptUrl : gScriptUrl).href; } // src/core/fonts.ts function makeFontFace(name, source, descriptors = {}) { return new FontFace( name, `url(${source}.woff2) format('woff2')`, descriptors ); } var gFontsState = "not-loaded"; async function reloadFonts() { gFontsState = "not-loaded"; return loadFonts(); } async function loadFonts() { var _a3; if (gFontsState !== "not-loaded") return; gFontsState = "loading"; const useStaticFonts = (_a3 = getComputedStyle(document.documentElement).getPropertyValue( "--ML__static-fonts" )) != null ? _a3 : false; if (useStaticFonts) { gFontsState = "ready"; return; } document.body.classList.remove("ML__fonts-did-not-load"); if ("fonts" in document) { const fontFamilies = [ "KaTeX_Main", "KaTeX_Math", "KaTeX_AMS", "KaTeX_Caligraphic", "KaTeX_Fraktur", "KaTeX_SansSerif", "KaTeX_Script", "KaTeX_Typewriter", "KaTeX_Size1", "KaTeX_Size2", "KaTeX_Size3", "KaTeX_Size4" ]; const fontsInDocument = Array.from(document.fonts).map((f) => f.family); if (fontFamilies.every((x) => fontsInDocument.includes(x))) { gFontsState = "ready"; return; } if (!window.MathfieldElement.fontsDirectory) { gFontsState = "not-loaded"; return; } const fontsFolder = await resolveUrl( window.MathfieldElement.fontsDirectory ); if (!fontsFolder) { document.body.classList.add("ML__fonts-did-not-load"); gFontsState = "error"; return; } const fonts = [ ["KaTeX_Main-Regular"], ["KaTeX_Main-BoldItalic", { style: "italic", weight: "bold" }], ["KaTeX_Main-Bold", { weight: "bold" }], ["KaTeX_Main-Italic", { style: "italic" }], ["KaTeX_Math-Italic", { style: "italic" }], ["KaTeX_Math-BoldItalic", { style: "italic", weight: "bold" }], ["KaTeX_AMS-Regular"], ["KaTeX_Caligraphic-Regular"], ["KaTeX_Caligraphic-Bold", { weight: "bold" }], ["KaTeX_Fraktur-Regular"], ["KaTeX_Fraktur-Bold", { weight: "bold" }], ["KaTeX_SansSerif-Regular"], ["KaTeX_SansSerif-Bold", { weight: "bold" }], ["KaTeX_SansSerif-Italic", { style: "italic" }], ["KaTeX_Script-Regular"], ["KaTeX_Typewriter-Regular"], ["KaTeX_Size1-Regular"], ["KaTeX_Size2-Regular"], ["KaTeX_Size3-Regular"], ["KaTeX_Size4-Regular"] ].map( (x) => makeFontFace( x[0].replace(/-[a-zA-Z]+$/, ""), `${fontsFolder}/${x[0]}`, x[1] ) ); try { const loadedFonts = await Promise.all( fonts.map((x) => { try { return x.load(); } catch (e) { } return void 0; }) ); loadedFonts.forEach((font) => document.fonts.add(font)); gFontsState = "ready"; return; } catch (error) { console.error( `MathLive 0.98.5: The math fonts could not be loaded from "${fontsFolder}"`, { cause: error } ); document.body.classList.add("ML__fonts-did-not-load"); } gFontsState = "error"; } } // src/editor-mathfield/render.ts function hash(latex) { let result = 0; for (let i = 0; i < latex.length; i++) { result = result * 31 + latex.charCodeAt(i); result = result | 0; } return Math.abs(result); } function requestUpdate(mathfield, options) { if (!mathfield) return; if (mathfield.dirty) return; mathfield.dirty = true; requestAnimationFrame(() => { if (isValidMathfield(mathfield) && mathfield.dirty) { mathfield.atomBoundsCache = /* @__PURE__ */ new Map(); render(mathfield, options); mathfield.atomBoundsCache = void 0; } }); } function makeBox(mathfield, renderOptions) { var _a3; renderOptions = renderOptions != null ? renderOptions : {}; const context = new Context({ from: __spreadProps(__spreadValues({}, mathfield.context), { atomIdsSettings: { // Using the hash as a seed for the ID // keeps the IDs the same until the content of the field changes. seed: renderOptions.forHighlighting ? hash( Atom.serialize([mathfield.model.root], { expandMacro: false, defaultMode: mathfield.options.defaultMode }) ) : "random", // The `groupNumbers` flag indicates that extra boxes should be generated // to represent group of atoms, for example, a box to group // consecutive digits to represent a number. groupNumbers: (_a3 = renderOptions.forHighlighting) != null ? _a3 : false }, letterShapeStyle: mathfield.options.letterShapeStyle }), mathstyle: mathfield.options.defaultMode === "inline-math" ? "textstyle" : "displaystyle" }); const base = mathfield.model.root.render(context); const wrapper = makeStruts(applyInterBoxSpacing(base, context), { classes: mathfield.hasEditablePrompts ? "ML__latex ML__prompting" : "ML__latex", attributes: { // Sometimes Google Translate kicks in an attempts to 'translate' math // This doesn't work very well, so turn off translate "translate": "no", // Hint to screen readers to not attempt to read this . // They should use instead the 'aria-label' attribute. "aria-hidden": "true" } }); return wrapper; } function contentMarkup(mathfield, renderOptions) { const { model } = mathfield; model.root.caret = void 0; model.root.isSelected = false; model.root.containsCaret = true; for (const atom of model.atoms) { atom.caret = void 0; atom.isSelected = false; atom.containsCaret = false; } if (model.selectionIsCollapsed) { const atom = model.at(model.position); atom.caret = mathfield.model.mode; let ancestor = atom.parent; while (ancestor) { ancestor.containsCaret = true; ancestor = ancestor.parent; } } else { const atoms = model.getAtoms(model.selection, { includeChildren: true }); for (const atom of atoms) atom.isSelected = true; } const box = makeBox(mathfield, renderOptions); return box.toMarkup(); } function render(mathfield, renderOptions) { if (!isValidMathfield(mathfield)) return; renderOptions != null ? renderOptions : renderOptions = {}; const keyboardToggle = mathfield.element.querySelector( "[part=virtual-keyboard-toggle]" ); if (keyboardToggle) keyboardToggle.style.display = mathfield.hasEditableContent ? "" : "none"; const field = mathfield.field; if (!field) return; const hasFocus = mathfield.isSelectionEditable && mathfield.hasFocus(); const isFocused = field.classList.contains("ML__focused"); if (isFocused && !hasFocus) field.classList.remove("ML__focused"); else if (!isFocused && hasFocus) field.classList.add("ML__focused"); let content = contentMarkup(mathfield, renderOptions); const menuToggle = mathfield.element.querySelector("[part=menu-toggle]"); if (menuToggle) { if (mathfield.model.atoms.length <= 1 || mathfield.disabled || mathfield.readOnly && !mathfield.hasEditableContent || mathfield.userSelect === "none") menuToggle.style.display = "none"; else menuToggle.style.display = ""; } if (mathfield.model.atoms.length <= 1) { const placeholder = mathfield.options.contentPlaceholder; if (placeholder) { content += `${convertLatexToMarkup( placeholder )}`; } } field.innerHTML = window.MathfieldElement.createHTML(content); renderSelection(mathfield, renderOptions.interactive); mathfield.dirty = false; } function renderSelection(mathfield, interactive) { const field = mathfield.field; if (!field) return; for (const element of field.querySelectorAll( ".ML__selection, .ML__contains-highlight" )) element.remove(); if (!(interactive != null ? interactive : false) && gFontsState !== "error" && gFontsState !== "ready") { setTimeout(() => { if (gFontsState === "ready") renderSelection(mathfield); else setTimeout(() => renderSelection(mathfield), 128); }, 32); } const model = mathfield.model; const offsetWidth = field.offsetWidth; const actualWidth = field.getBoundingClientRect().width; let scaleFactor = Math.floor(actualWidth) / offsetWidth; scaleFactor = isNaN(scaleFactor) ? 1 : scaleFactor; if (model.selectionIsCollapsed) { updateSuggestionPopoverPosition(mathfield, { deferred: true }); let atom = model.at(model.position); while (atom && atom.type !== "prompt" && !(atom.containsCaret && atom.displayContainsHighlight)) atom = atom.parent; if ((atom == null ? void 0 : atom.containsCaret) && atom.displayContainsHighlight) { const bounds = adjustForScrolling( mathfield, getAtomBounds(mathfield, atom), scaleFactor ); if (bounds) { bounds.left /= scaleFactor; bounds.right /= scaleFactor; bounds.top /= scaleFactor; bounds.bottom /= scaleFactor; const element = document.createElement("div"); element.classList.add("ML__contains-highlight"); element.style.position = "absolute"; element.style.left = `${bounds.left + 1}px`; element.style.top = `${Math.ceil(bounds.top)}px`; element.style.width = `${Math.ceil(bounds.right - bounds.left)}px`; element.style.height = `${Math.ceil(bounds.bottom - bounds.top)}px`; field.insertBefore(element, field.childNodes[0]); } } return; } for (const x of unionRects( getSelectionBounds(mathfield, { excludeAtomsWithBackground: true }) )) { x.left /= scaleFactor; x.right /= scaleFactor; x.top /= scaleFactor; x.bottom /= scaleFactor; const selectionElement = document.createElement("div"); selectionElement.classList.add("ML__selection"); selectionElement.style.position = "absolute"; selectionElement.style.left = `${x.left}px`; selectionElement.style.top = `${x.top}px`; selectionElement.style.width = `${Math.ceil(x.right - x.left)}px`; selectionElement.style.height = `${Math.ceil(x.bottom - x.top - 1)}px`; field.insertBefore(selectionElement, field.childNodes[0]); } } function unionRects(rects) { let result = []; for (const rect of rects) { let found = false; for (const rect2 of result) { if (rect.left === rect2.left && rect.right === rect2.right && rect.top === rect2.top && rect.bottom === rect2.bottom) { found = true; break; } } if (!found) result.push(rect); } rects = result; result = []; for (const rect of rects) { let count = 0; for (const rect2 of rects) { if (rect.left >= rect2.left && rect.right <= rect2.right && rect.top >= rect2.top && rect.bottom <= rect2.bottom) { count += 1; if (count > 1) break; } } if (count === 1) result.push(rect); } return result; } // src/editor/commands.ts var HAPTIC_FEEDBACK_DURATION = 3; var COMMANDS; function register2(commands, options) { options = __spreadValues({ target: "mathfield", canUndo: false, audioFeedback: void 0, changeContent: false, changeSelection: false }, options != null ? options : {}); if (!COMMANDS) COMMANDS = {}; for (const selector of Object.keys(commands)) { console.assert(!COMMANDS[selector], "Selector already defined: ", selector); COMMANDS[selector] = __spreadProps(__spreadValues({}, options), { fn: commands[selector] }); } } function getCommandInfo(command) { let selector; if (Array.isArray(command)) { if (command[0] === "performWithFeedback") return getCommandInfo(command[1]); selector = command[0]; } else selector = command; selector = selector.replace( /-\w/g, (m) => m[1].toUpperCase() ); return COMMANDS[selector]; } function getCommandTarget(command) { var _a3; return (_a3 = getCommandInfo(command)) == null ? void 0 : _a3.target; } function perform(mathfield, command) { var _a3; if (!command) return false; let selector; let args = []; let handled = false; let dirty = false; if (isArray(command)) { selector = command[0]; args = command.slice(1); } else selector = command; selector = selector.replace( /-\w/g, (m) => m[1].toUpperCase() ); const info = COMMANDS[selector]; const commandTarget = info == null ? void 0 : info.target; if (commandTarget === "model") { if (!mathfield.isSelectionEditable && (info == null ? void 0 : info.changeContent)) { mathfield.model.announce("plonk"); return false; } if (/^(delete|add)/.test(selector)) { if (selector !== "deleteBackward") mathfield.flushInlineShortcutBuffer(); mathfield.snapshot(selector); } if (!/^complete/.test(selector)) removeSuggestion(mathfield); COMMANDS[selector].fn(mathfield.model, ...args); updateAutocomplete(mathfield); dirty = true; handled = true; } else if (commandTarget === "virtual-keyboard") { dirty = (_a3 = window.mathVirtualKeyboard.executeCommand(command)) != null ? _a3 : false; handled = true; } else if (COMMANDS[selector]) { if (!mathfield.isSelectionEditable && (info == null ? void 0 : info.changeContent)) { mathfield.model.announce("plonk"); return false; } if (/^(undo|redo)/.test(selector)) mathfield.flushInlineShortcutBuffer(); dirty = COMMANDS[selector].fn(mathfield, ...args); handled = true; } else throw new Error(`Unknown command "${selector}"`); if (commandTarget !== "virtual-keyboard") { if (!mathfield.model.selectionIsCollapsed || (info == null ? void 0 : info.changeSelection) && command !== "deleteBackward") { mathfield.flushInlineShortcutBuffer(); if (!(info == null ? void 0 : info.changeContent)) mathfield.stopCoalescingUndo(); mathfield.defaultStyle = {}; } } if (dirty) requestUpdate(mathfield); return handled; } function performWithFeedback(mathfield, selector) { var _a3; if (!mathfield) return false; mathfield.focus(); if (mathfield_element_default.keypressVibration && canVibrate()) navigator.vibrate(HAPTIC_FEEDBACK_DURATION); const info = getCommandInfo(selector); window.MathfieldElement.playSound((_a3 = info == null ? void 0 : info.audioFeedback) != null ? _a3 : "keypress"); const result = mathfield.executeCommand(selector); mathfield.scrollIntoView(); return result; } register2({ performWithFeedback: (mathfield, command) => performWithFeedback(mathfield, command) }); function nextSuggestion(mathfield) { updateAutocomplete(mathfield, { atIndex: mathfield.suggestionIndex + 1 }); return false; } function previousSuggestion(mathfield) { updateAutocomplete(mathfield, { atIndex: mathfield.suggestionIndex - 1 }); return false; } register2( { complete }, { target: "mathfield", audioFeedback: "return", canUndo: true, changeContent: true, changeSelection: true } ); register2( { nextSuggestion, previousSuggestion }, { target: "mathfield", audioFeedback: "keypress", changeSelection: true } ); // src/virtual-keyboard/proxy.ts var VIRTUAL_KEYBOARD_MESSAGE = "mathlive#virtual-keyboard-message"; function isVirtualKeyboardMessage(evt) { var _a3; if (evt.type !== "message") return false; const msg = evt; return ((_a3 = msg.data) == null ? void 0 : _a3.type) === VIRTUAL_KEYBOARD_MESSAGE; } var VirtualKeyboardProxy = class _VirtualKeyboardProxy { constructor() { this.targetOrigin = window.origin; this.originValidator = "none"; this._boundingRect = new DOMRect(0, 0, 0, 0); this._isShifted = false; window.addEventListener("message", this); this.sendMessage("proxy-created"); this.listeners = {}; } static get singleton() { if (!this._singleton) this._singleton = new _VirtualKeyboardProxy(); return this._singleton; } set alphabeticLayout(value) { this.sendMessage("update-setting", { alphabeticLayout: value }); } set layouts(value) { this.sendMessage("update-setting", { layouts: value }); } get normalizedLayouts() { return []; } set editToolbar(value) { this.sendMessage("update-setting", { editToolbar: value }); } set actionKeycap(value) { this.sendMessage("update-setting", { actionKeycap: value }); } set shiftKeycap(value) { this.sendMessage("update-setting", { shiftKeycap: value }); } set backspaceKeycap(value) { this.sendMessage("update-setting", { backspaceKeycap: value }); } set tabKeycap(value) { this.sendMessage("update-setting", { tabKeycap: value }); } set container(value) { throw new Error("Container inside an iframe cannot be changed"); } show(options) { this.sendMessage("show", options); } hide(options) { this.sendMessage("hide", options); } get isShifted() { return this._isShifted; } get visible() { return this._boundingRect.height > 0; } set visible(value) { if (value) this.show(); else this.hide(); } get boundingRect() { return this._boundingRect; } executeCommand(command) { this.sendMessage("execute-command", { command }); return true; } updateToolbar(mf) { this.sendMessage("update-toolbar", mf); } update(mf) { this.sendMessage("update-setting", mf); } connect() { this.sendMessage("connect"); } disconnect() { this.sendMessage("disconnect"); } addEventListener(type, callback, _options) { if (!this.listeners[type]) this.listeners[type] = /* @__PURE__ */ new Set(); if (!this.listeners[type].has(callback)) this.listeners[type].add(callback); } dispatchEvent(event) { if (!this.listeners[event.type] || this.listeners[event.type].size === 0) return true; this.listeners[event.type].forEach((x) => { if (typeof x === "function") x(event); else x == null ? void 0 : x.handleEvent(event); }); return !event.defaultPrevented; } removeEventListener(type, callback, _options) { if (this.listeners[type]) this.listeners[type].delete(callback); } handleEvent(evt) { if (isVirtualKeyboardMessage(evt)) { if (!validateOrigin(evt.origin, this.originValidator)) { throw new DOMException( `Message from unknown origin (${evt.origin}) cannot be handled`, "SecurityError" ); } this.handleMessage(evt.data); } } handleMessage(msg) { const { action } = msg; if (action === "execute-command") { const { command } = msg; const commandTarget = getCommandTarget(command); if (commandTarget === "virtual-keyboard") this.executeCommand(command); return; } if (action === "synchronize-proxy") { this._boundingRect = msg.boundingRect; this._isShifted = msg.isShifted; return; } if (action === "geometry-changed") { this._boundingRect = msg.boundingRect; this.dispatchEvent(new Event("geometrychange")); return; } } sendMessage(action, payload = {}) { if (!window.top) { throw new DOMException( `A frame does not have access to the top window and can\u2018t communicate with the keyboard. Review virtualKeyboardTargetOrigin and originValidator on mathfields embedded in an iframe`, "SecurityError" ); } window.top.postMessage( __spreadValues({ type: VIRTUAL_KEYBOARD_MESSAGE, action }, payload), this.targetOrigin ); } }; // src/virtual-keyboard/data.ts var LAYOUTS = { "numeric": { label: "123", labelClass: "MLK__tex-math", tooltip: "keyboard.tooltip.numeric", rows: [ [ { latex: "x", shift: "y", variants: [ "y", "z", "t", "r", "x^2", "x^n", "x^{#?}", "x_n", "x_i", "x_{#?}", { latex: "f(#?)", class: "small" }, { latex: "g(#?)", class: "small" } ] }, { latex: "n", shift: "a", variants: ["i", "j", "p", "k", "a", "u"] }, "[separator-5]", "[7]", "[8]", "[9]", "[/]", "[separator-5]", { latex: "\\exponentialE", shift: "\\ln", variants: ["\\exp", "\\times 10^{#?}", "\\ln", "\\log_{10}", "\\log"] }, { latex: "\\imaginaryI", variants: ["\\Re", "\\Im", "\\imaginaryJ", "\\Vert #0 \\Vert"] }, { latex: "\\pi", shift: "\\sin", variants: [ "\\prod", { latex: "\\theta", aside: "theta" }, { latex: "\\rho", aside: "rho" }, { latex: "\\tau", aside: "tau" }, "\\sin", "\\cos", "\\tan" ] } ], [ { label: "<", latex: "<", class: "hide-shift", shift: { latex: "\\le", label: "\u2264" } }, { label: ">", latex: ">", class: "hide-shift", shift: { latex: "\\ge", label: "\u2265" } }, "[separator-5]", "[4]", "[5]", "[6]", "[*]", "[separator-5]", { class: "hide-shift", latex: "#@^2}", shift: "#@^{\\prime}}" }, { latex: "#@^{#0}}", class: "hide-shift", shift: "#@_{#?}" }, { class: "hide-shift", latex: "\\sqrt{#0}", shift: { latex: "\\sqrt[#0]{#?}}" } } ], [ "[(]", "[)]", "[separator-5]", "[1]", "[2]", "[3]", "[-]", "[separator-5]", { latex: "\\int^{\\infty}_{0}\\!#?\\,\\mathrm{d}x", class: "small hide-shift", shift: "\\int", variants: [ { latex: "\\int_{#?}^{#?}", class: "small" }, { latex: "\\int", class: "small" }, { latex: "\\iint", class: "small" }, { latex: "\\iiint", class: "small" }, { latex: "\\oint", class: "small" }, "\\mathrm{d}x", { latex: "\\dfrac{\\mathrm{d}}{\\mathrm{d} x}", class: "small" }, { latex: "\\frac{\\partial}{\\partial x}", class: "small" }, "\\partial" ] }, { class: "hide-shift", latex: "\\forall", shift: "\\exists" }, { label: "[backspace]", width: 1 } ], [ { label: "[shift]", width: 2 }, "[separator-5]", "[0]", "[.]", "[=]", "[+]", "[separator-5]", "[left]", "[right]", { label: "[action]", width: 1 } ] ] }, "greek": { label: "αβγ", labelClass: "MLK__tex-math", tooltip: "keyboard.tooltip.greek", rows: [ [ { label: "φ", class: "MLK__tex hide-shift", insert: "\\varphi", aside: "phi var.", shift: "\\Phi" }, { label: "ς", class: "MLK__tex hide-shift", insert: "\\varsigma", aside: "sigma var.", shift: "\\Sigma" }, { label: "ϵ", class: "MLK__tex hide-shift", insert: "\\epsilon", aside: "espilon", shift: '\\char"0190' }, { label: "ρ", class: "MLK__tex hide-shift", insert: "\\rho", aside: "rho", shift: '\\char"3A1' }, { label: "τ", class: "MLK__tex hide-shift", insert: "\\tau", aside: "tau", shift: '\\char"3A4' }, { label: "υ", class: "MLK__tex hide-shift", insert: "\\upsilon", aside: "upsilon", shift: "\\Upsilon" }, { label: "θ", class: "MLK__tex hide-shift", insert: "\\theta", aside: "theta", shift: "\\Theta" }, { label: "ι", class: "MLK__tex hide-shift", insert: "\\iota", aside: "iota", shift: '\\char"399' }, { label: "ο", class: "MLK__tex hide-shift", insert: "\\omicron", aside: "omicron", shift: '\\char"39F' }, { label: "π", class: "MLK__tex hide-shift", insert: "\\pi", aside: "pi", shift: "\\Pi" } ], [ "[separator-5]", { label: "α", class: "MLK__tex hide-shift", insert: "\\alpha", aside: "alpha", shift: '\\char"391' }, { label: "σ", class: "MLK__tex hide-shift", insert: "\\sigma", aside: "sigma", shift: "\\Sigma" }, { label: "δ", class: "MLK__tex hide-shift", insert: "\\delta", aside: "delta", shift: "\\Delta" }, { latex: "\\phi", class: "MLK__tex hide-shift", insert: "\\phi", aside: "phi", shift: "\\Phi" }, { label: "γ", class: "MLK__tex hide-shift", insert: "\\gamma", aside: "gamma", shift: "\\Gamma" }, { label: "η", class: "MLK__tex hide-shift", insert: "\\eta", aside: "eta", shift: '\\char"397' }, { label: "ξ", class: "MLK__tex hide-shift", insert: "\\xi", aside: "xi", shift: "\\Xi" }, { label: "κ", class: "MLK__tex hide-shift", insert: "\\kappa", aside: "kappa", shift: "\\Kappa" }, { label: "λ", class: "MLK__tex hide-shift", insert: "\\lambda", aside: "lambda", shift: "\\Lambda" }, "[separator-5]" ], [ "[shift]", { label: "ζ", class: "MLK__tex hide-shift", insert: "\\zeta", aside: "zeta", shift: '\\char"396' }, { label: "χ", class: "MLK__tex hide-shift", insert: "\\chi", aside: "chi", shift: '\\char"3A7' }, { label: "ψ", class: "MLK__tex hide-shift", insert: "\\psi", aside: "zeta", shift: "\\Psi" }, { label: "ω", class: "MLK__tex hide-shift", insert: "\\omega", aside: "omega", shift: "\\Omega" }, { label: "β", class: "MLK__tex hide-shift", insert: "\\beta", aside: "beta", shift: '\\char"392' }, { label: "ν", class: "MLK__tex hide-shift", insert: "\\nu", aside: "nu", shift: '\\char"39D' }, { label: "μ", class: "MLK__tex hide-shift", insert: "\\mu", aside: "mu", shift: '\\char"39C' }, "[backspace]" ], [ "[separator]", { label: "ε", class: "MLK__tex", insert: "\\varepsilon", aside: "espilon var." }, { label: "ϑ", class: "MLK__tex", insert: "\\vartheta", aside: "theta var." }, { label: "ϰ", class: "MLK__tex", insert: "\\varkappa", aside: "kappa var." }, { label: "ϖ", class: "MLK__tex", insert: "\\varpi", aside: "pi var." }, { label: "ϱ", class: "MLK__tex", insert: "\\varrho", aside: "rho var." }, "[left]", "[right]", "[action]" ] ] }, "symbols": { label: "∞\u2260\u2208", labelClass: "MLK__tex", tooltip: "keyboard.tooltip.symbols", rows: [ [ { latex: "\\sin", shift: "\\sin^{-1}", variants: [ { class: "small", latex: "\\sinh" }, { class: "small", latex: "\\sin^{-1}" }, { class: "small", latex: "\\arsinh" } ] }, "\\ln", { latex: "\\mathrm{abs}", insert: "\\mathrm{abs}\\left(#0\\right)" }, { latex: "\\rarr", shift: "\\rArr", variants: [ { latex: "\\implies", aside: "implies" }, { latex: "\\to", aside: "to" }, "\\dashv", { latex: "\\roundimplies", aside: "round implies" } ] }, { latex: "\\exists", variants: ["\\nexists"], shift: "\\nexists" }, { latex: "\\in", shift: "\\notin", variants: ["\\notin", "\\owns"] }, "\\cup", { latex: "\\overrightarrow{#@}", shift: "\\overleftarrow{#@}", variants: [ "\\overleftarrow{#@}", "\\bar{#@}", "\\vec{#@}", "\\hat{#@}", "\\check{#@}", "\\dot{#@}", "\\ddot{#@}", "\\mathring{#@}", "\\breve{#@}", "\\acute{#@}", "\\tilde{#@}", "\\grave{#@}" ] }, { class: "small", latex: "\\lim_{#?}", shift: "\\lim_{x\\to\\infty}", variants: [ { class: "small", latex: "\\liminf_{#?}" }, { class: "small", latex: "\\limsup_{#?}" } ] }, "\\exponentialE" ], [ { latex: "\\cos", shift: "\\cos^{-1}", variants: [ { class: "small", latex: "\\cosh" }, { class: "small", latex: "\\cos^{-1}" }, { class: "small", latex: "\\arcosh" } ] }, { latex: "\\log", shift: "\\log_{10}", variants: ["\\log_{#0}", "\\log_{10}"] }, "\\left\\vert#0\\right\\vert", { latex: "\\larr", shift: "\\lArr", variants: [ { latex: "\\impliedby", aside: "implied by" }, { latex: "\\gets", aside: "gets" }, "\\lArr", "\\vdash", { latex: "\\models", aside: "models" } ] }, { latex: "\\forall", shift: "\\lnot", variants: [ { latex: "\\land", aside: "and" }, { latex: "\\lor", aside: "or" }, { latex: "\\oplus", aside: "xor" }, { latex: "\\lnot", aside: "not" }, { latex: "\\downarrow", aside: "nor" }, { latex: "\\uparrow", aside: "nand" }, { latex: "\\curlywedge", aside: "nor" }, { latex: "\\bar\\curlywedge", aside: "nand" } // {latex:'\\barwedge', aside:'bar wedge'}, // {latex:'\\curlyvee', aside:'curly vee'}, // {latex:'\\veebar', aside:'vee bar'}, ] }, { latex: "\\ni", shift: "\\not\\owns" }, "\\cap", { latex: "\\overline{#@}", shift: "\\underline{#@}", variants: [ "\\overbrace{#@}", "\\overlinesegment{#@}", "\\overleftrightarrow{#@}", "\\overrightarrow{#@}", "\\overleftarrow{#@}", "\\overgroup{#@}", "\\underbrace{#@}", "\\underlinesegment{#@}", "\\underleftrightarrow{#@}", "\\underrightarrow{#@}", "\\underleftarrow{#@}", "\\undergroup{#@}" ] }, { class: "hide-shift", latex: "\\int", shift: "\\iint", variants: [ { latex: "\\int_{#?}^{#?}", class: "small" }, { latex: "\\int", class: "small" }, { latex: "\\smallint", class: "small" }, { latex: "\\iint", class: "small" }, { latex: "\\iiint", class: "small" }, { latex: "\\oint", class: "small" }, "\\intop", "\\iiint", "\\oiint", "\\oiiint", "\\intclockwise", "\\varointclockwise", "\\ointctrclockwise", "\\intctrclockwise" ] }, { latex: "\\pi", shift: "\\tau", variants: ["\\tau"] } ], [ { latex: "\\tan", shift: "\\tan^{-1}", variants: [ { class: "small", latex: "\\tanh" }, { class: "small", latex: "\\tan^{-1}" }, { class: "small", latex: "\\artanh" }, { class: "small", latex: "\\arctan" }, { class: "small", latex: "\\arctg" }, { class: "small", latex: "\\tg" } ] }, { latex: "\\exp", insert: "\\exp\\left(#0\\right)", variants: ["\\exponentialE^{#0}"] }, "\\left\\Vert#0\\right\\Vert", { latex: "\\lrArr", shift: "\\leftrightarrow", variants: [ { latex: "\\iff", aside: "if and only if" }, "\\leftrightarrow", "\\leftrightarrows", "\\Leftrightarrow", { latex: "^\\biconditional", aside: "biconditional" } ] }, { latex: "\\vert", shift: "!" }, { latex: "#@^{\\complement}", aside: "complement", variants: [ { latex: "\\setminus", aside: "set minus" }, { latex: "\\smallsetminus", aside: "small set minus" } ] }, { latex: "\\subset", shift: "\\subseteq", variants: [ "\\subset", "\\subseteq", "\\subsetneq", "\\varsubsetneq", "\\subsetneqq", "\\nsubset", "\\nsubseteq", "\\supset", "\\supseteq", "\\supsetneq", "\\supsetneqq", "\\nsupset", "\\nsupseteq" ] }, { latex: "#@^{\\prime}", shift: "#@^{\\doubleprime}", variants: ["#@^{\\doubleprime}", "#@\\degree"] }, { latex: "\\mathrm{d}", shift: "\\partial", variants: [ "\\mathrm{d}x", { latex: "\\dfrac{\\mathrm{d}}{\\mathrm{d} x}", class: "small" }, { latex: "\\frac{\\partial}{\\partial x}", class: "small" }, "\\partial" ] }, { latex: "\\infty", variants: ["\\aleph_0", "\\aleph_1", "\\omega", "\\mathfrak{m}"] } ], [ { label: "[shift]", width: 2 }, { class: "box", latex: ",", shift: ";", variants: [";", "?"] }, { class: "box", latex: "\\colon", shift: "\\Colon", variants: [ { latex: "\\Colon", aside: "such that", class: "box" }, { latex: ":", aside: "ratio", class: "box" }, { latex: "\\vdots", aside: "", class: "box" }, { latex: "\\ddots", aside: "", class: "box" }, { latex: "\\ldotp", aside: "low dot", class: "box" }, { latex: "\\cdotp", aside: "center dot", class: "box" }, { latex: "\\ldots", aside: "low ellipsis", class: "box" }, { latex: "\\cdots", aside: "center ellipsis", class: "box" }, { latex: "\\therefore", aside: "therefore", class: "box" }, { latex: "\\because", aside: "because", class: "box" } ] }, { class: "box", latex: "\\cdot", aside: "centered dot", shift: "\\ast", variants: [ "\\circ", "\\bigcirc", "\\bullet", "\\odot", "\\oslash", "\\circledcirc", "\\ast", "\\star", "\\times", "\\doteq", "\\doteqdot" ] }, "[separator]", "[left]", "[right]", { label: "[backspace]", width: 1, class: "action hide-shift" }, { label: "[action]", width: 1 } ] ] }, "compact": { label: "compact", rows: [ [ "[+]", "[-]", "[*]", "[/]", "[=]", "[.]", "[(]", "[)]", "\\sqrt{#0}", "#@^{#?}" ], ["[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]", "[8]", "[9]", "[0]"], ["[hr]"], [ "[undo]", "[redo]", "[separator]", "[separator]", "[separator]", "[left]", "[right]", { label: "[backspace]", class: "action hide-shift" }, "[hide-keyboard]" ] ] }, "minimalist": { label: "minimalist", layers: [ { style: ` .minimalist-backdrop { display: flex; justify-content: center; } .minimalist-container { --keycap-height: 40px; --keycap-max-width: 53px; --keycap-small-font-size: 12px; background: var(--keyboard-background); padding: 20px; border-top-left-radius: 8px; border-top-right-radius: 8px; border: 1px solid var(--keyboard-border); box-shadow: 0 0 32px rgb(0 0 0 / 30%); } `, backdrop: "minimalist-backdrop", container: "minimalist-container", rows: [ [ "+", "-", "\\times", { latex: "\\frac{#@}{#0}", class: "small" }, "=", "[.]", "(", ")", { latex: "\\sqrt{#0}", class: "small" }, { latex: "#@^{#?}", class: "small" } ], ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], ["[hr]"], [ "[undo]", "[redo]", "[separator]", "[separator]", "[separator]", "[left]", "[right]", { label: "[backspace]", class: "action hide-shift" }, "[hide-keyboard]" ] ] } ] }, "numeric-only": { label: "123", labelClass: "MLK__tex-math", tooltip: "keyboard.tooltip.numeric", id: "numeric-only", rows: [ ["7", "8", "9", "[separator]", { label: "[backspace]", width: 2 }], ["4", "5", "6", "[separator]", "[separator]", "[separator]"], ["1", "2", "3", "[separator]", "[separator]", "[separator]"], [ "0", { label: "[.]", variants: [] }, "-", "[separator]", "[left]", "[right]" ] ] } }; // src/virtual-keyboard/variants.ts var VARIANTS2 = { // '0-extended': [ // '\\emptyset', // '\\varnothing', // '\\infty', // { latex: '#?_0', insert: '#@_0' }, // '\\circ', // '\\bigcirc', // '\\bullet', // ], "0": ["\\varnothing", "\\infty"], "1": ["\\frac{1}{#@}", "#@^{-1}", "\\times 10^{#?}", "\\phi", "\\imaginaryI"], "2": ["\\frac{1}{2}", "#@^2", "\\sqrt2", "\\exponentialE"], "3": ["\\frac{1}{3}", "#@^3", "\\sqrt3", "\\pi"], "4": ["\\frac{1}{4}", "#@^4"], "5": ["\\frac{1}{5}", "#@^5", "\\sqrt5"], "6": ["\\frac{1}{6}", "#@^6"], "7": ["\\frac{1}{7}", "#@^7"], "8": ["\\frac{1}{8}", "#@^8"], "9": ["\\frac{1}{9}", "#@^9"], ".": [".", ",", ";", "\\colon"], ",": ["{,}", ".", ";", "\\colon"], "a": [ { latex: "\\aleph", aside: "aleph" }, { latex: "\\forall", aside: "for all" }, "\xE0", "\xE1", "\xE2", "\xE4", "\xE6" ], "b": [{ latex: "\\beth", aside: "beth" }], "c": [{ latex: "\\C", aside: "set of complex numbers" }, "\xE7"], "d": [{ latex: "\\daleth", aside: "daleth" }], "e": [ { latex: "\\exponentialE", aside: "exponential e" }, { latex: "\\exists", aside: "there is" }, { latex: "\\nexists", aside: "there isn\u2019t" }, "\xE8", "\xE9", "\xEA", "\xEB" ], "g": [{ latex: "\\gimel", aside: "gimel" }], "h": [ { latex: "\\hbar", aside: "h bar" }, { latex: "\\hslash", aside: "h slash" } ], "i": [{ latex: "\\imaginaryI", aside: "imaginary i" }, "\xEC", "\xED", "\xEE", "\xEF"], "j": [{ latex: "\\imaginaryJ", aside: "imaginary j" }], "l": [{ latex: "\\ell", aside: "ell" }], "n": [{ latex: "\\mathbb{N}", aside: "set of natural numbers" }, "\xF1"], "o": ["\xF8", "\u0153", "\xF2", "\xF3", "\xF4", "\xF6", "\u0153"], "p": [{ latex: "\\mathbb{P}", aside: "set of primes" }], "q": [{ latex: "\\mathbb{Q}", aside: "set of rational numbers" }], "r": [{ latex: "\\mathbb{R}", aside: "set of real numbers" }], "u": ["\xF9", "\xFA", "\xFB", "\xFC"], "z": [{ latex: "\\mathbb{Z}", aside: "set of integers" }], "y": ["\xFD", "\xFF"], "space": [ { latex: '\\char"203A\\!\\char"2039', insert: "\\!", aside: "negative thin space
    \u207B\xB3\u29F8\u2081\u2088 em" }, { latex: '\\char"203A\\,\\char"2039', insert: "\\,", aside: "thin space
    \xB3\u29F8\u2081\u2088 em" }, { latex: '\\char"203A\\:\\char"2039', insert: "\\:", aside: "medium space
    \u2074\u29F8\u2081\u2088 em" }, { latex: '\\char"203A\\;\\char"2039', insert: "\\;", aside: "thick space
    \u2075\u29F8\u2081\u2088 em" }, { latex: '\\char"203A\\ \\char"2039', insert: "\\ ", aside: "\u2153 em" }, { latex: '\\char"203A\\enspace\\char"2039', insert: "\\enspace", aside: "\xBD em" }, { latex: '\\char"203A\\quad\\char"2039', insert: "\\quad", aside: "1 em" }, { latex: '\\char"203A\\qquad\\char"2039', insert: "\\qquad", aside: "2 em" } ] }; var gVariantPanelController; function showVariantsPanel(element, onClose) { var _a3, _b3, _c2; const keyboard = VirtualKeyboard.singleton; if (!keyboard) return; const keycap = parentKeycap(element); const variantDef = (_b3 = (_a3 = keyboard.getKeycap(keycap == null ? void 0 : keycap.id)) == null ? void 0 : _a3.variants) != null ? _b3 : ""; if (typeof variantDef === "string" && !hasVariants(variantDef) || Array.isArray(variantDef) && variantDef.length === 0) { onClose == null ? void 0 : onClose(); return; } const variants = {}; let markup = ""; for (const variant of getVariants(variantDef)) { const keycap2 = normalizeKeycap(variant); const id = Date.now().toString(36).slice(-2) + Math.floor(Math.random() * 1e5).toString(36); variants[id] = keycap2; const [keycapMarkup, keycapCls] = renderKeycap(keycap2); markup += `
    ${keycapMarkup}
    `; } const variantPanel = document.createElement("div"); variantPanel.setAttribute("aria-hidden", "true"); variantPanel.className = "MLK__variant-panel"; variantPanel.style.height = "auto"; const l = Object.keys(variants).length; let w = 5; if (l === 1) w = 1; else if (l === 2 || l === 4) w = 2; else if (l === 3 || l === 5 || l === 6) w = 3; else if (l >= 7 && l < 14) w = 4; variantPanel.style.width = `calc(var(--variant-keycap-length) * ${w} + 12px)`; variantPanel.innerHTML = mathfield_element_default.createHTML(markup); Scrim.open({ root: (_c2 = keyboard == null ? void 0 : keyboard.container) == null ? void 0 : _c2.querySelector(".ML__keyboard"), child: variantPanel }); gVariantPanelController = new AbortController(); const { signal } = gVariantPanelController; const position = element == null ? void 0 : element.getBoundingClientRect(); if (position) { if (position.top - variantPanel.clientHeight < 0) { variantPanel.style.width = "auto"; if (l <= 6) variantPanel.style.height = "56px"; else if (l <= 12) variantPanel.style.height = "108px"; else if (l <= 18) variantPanel.style.height = "205px"; else variantPanel.classList.add("compact"); } const left = Math.max( 0, Math.min( window.innerWidth - variantPanel.offsetWidth, (position.left + position.right - variantPanel.offsetWidth) / 2 ) ); const top = position.top - variantPanel.clientHeight + 5; variantPanel.style.transform = `translate(${left}px, ${top}px)`; variantPanel.classList.add("is-visible"); requestAnimationFrame(() => { variantPanel.addEventListener( "pointerup", (ev) => { const target = parentKeycap(ev.target); if (!(target == null ? void 0 : target.id) || !variants[target.id]) return; executeKeycapCommand(variants[target.id]); hideVariantsPanel(); onClose == null ? void 0 : onClose(); ev.preventDefault(); }, { capture: true, passive: false, signal } ); variantPanel.addEventListener( "pointerenter", (ev) => { const target = parentKeycap(ev.target); if (!(target == null ? void 0 : target.id) || !variants[target.id]) return; target.classList.add("is-active"); }, { capture: true, signal } ); variantPanel.addEventListener( "pointerleave", (ev) => { const target = parentKeycap(ev.target); if (!(target == null ? void 0 : target.id) || !variants[target.id]) return; target.classList.remove("is-active"); }, { capture: true, signal } ); window.addEventListener( "pointercancel", () => { hideVariantsPanel(); onClose == null ? void 0 : onClose(); }, { signal } ); window.addEventListener( "pointerup", () => { hideVariantsPanel(); onClose == null ? void 0 : onClose(); }, { signal } ); }); } return; } function hideVariantsPanel() { gVariantPanelController == null ? void 0 : gVariantPanelController.abort(); gVariantPanelController = null; if (Scrim.state === "open") Scrim.close(); } function makeVariants(id) { if (id === "foreground-color") { const result = []; for (const color of Object.keys(FOREGROUND_COLORS)) { result.push({ class: "swatch-button", label: '', command: ["applyStyle", { color }] }); } return result; } if (id === "background-color") { const result = []; for (const color of Object.keys(BACKGROUND_COLORS)) { result.push({ class: "swatch-button", label: '', command: ["applyStyle", { backgroundColor: color }] }); } return result; } return void 0; } function hasVariants(id) { return VARIANTS2[id] !== void 0; } function getVariants(id) { var _a3; if (typeof id !== "string") return id; if (!VARIANTS2[id]) VARIANTS2[id] = (_a3 = makeVariants(id)) != null ? _a3 : []; return VARIANTS2[id]; } // src/virtual-keyboard/utils.ts function jsonToCssProps(json) { if (typeof json === "string") return json; return Object.entries(json).map(([k, v]) => `${k}:${v} !important`).join(";"); } function jsonToCss(json) { return Object.keys(json).map((k) => { return `${k} {${jsonToCssProps(json[k])}}`; }).join(""); } function latexToMarkup2(latex) { if (!latex) return ""; const context = new Context(); const root = new Atom({ mode: "math", type: "root", body: parseLatex(latex, { context, args: (arg) => arg === "@" ? "{\\class{ML__box-placeholder}{\\blacksquare}}" : "\\placeholder{}" }) }); const box = coalesce( applyInterBoxSpacing( new Box(root.render(context), { classes: "ML__base" }), context ) ); return makeStruts(box, { classes: "ML__latex" }).toMarkup(); } function normalizeLayer(layer) { var _a3; if (Array.isArray(layer)) return layer.map((x) => normalizeLayer(x)).flat(); const result = typeof layer === "string" ? { markup: layer } : layer; if ("rows" in result && Array.isArray(result.rows)) result.rows = result.rows.map((row) => row.map((x) => normalizeKeycap(x))); (_a3 = result.id) != null ? _a3 : result.id = "ML__layer_" + Date.now().toString(36).slice(-2) + Math.floor(Math.random() * 1e5).toString(36); return [result]; } function alphabeticLayout() { var _a3, _b3; const keyboard = window.mathVirtualKeyboard; let layoutName = keyboard.alphabeticLayout; if (layoutName === "auto") { const activeLayout = getActiveKeyboardLayout(); if (activeLayout) layoutName = activeLayout.virtualLayout; if (!layoutName || layoutName === "auto") { layoutName = (_a3 = { fr: "azerty", be: "azerty", al: "qwertz", ba: "qwertz", cz: "qwertz", de: "qwertz", hu: "qwertz", sk: "qwertz", ch: "qwertz" }[l10n.locale.slice(0, 2)]) != null ? _a3 : "qwerty"; } } const ALPHABETIC_TEMPLATE = { qwerty: ["qwertyuiop", " asdfghjkl ", "^zxcvbnm~"], azerty: ["azertyuiop", "qsdfghjklm", "^ wxcvbn ~"], qwertz: ["qwertzuiop", " asdfghjkl ", "^yxcvbnm~"], dvorak: ["^ pyfgcrl ", "aoeuidhtns", "qjkxbmwvz~"], colemak: [" qwfpgjluy ", "arstdhneio", "^zxcvbkm~"] }; const template = (_b3 = ALPHABETIC_TEMPLATE[layoutName]) != null ? _b3 : ALPHABETIC_TEMPLATE.qwerty; const rows = layoutName === "azerty" ? [ [ { label: "1", variants: "1" }, { label: "2", shift: { latex: "\xE9" }, variants: "2" }, { label: "3", shift: { latex: "\xF9" }, variants: "3" }, { label: "4", variants: "4" }, { label: "5", shift: { label: "(", latex: "(" }, variants: "5" }, { label: "6", shift: { label: ")", latex: ")" }, variants: "6" }, { label: "7", shift: { latex: "\xE8" }, variants: "7" }, { label: "8", shift: { latex: "\xEA" }, variants: "8" }, { label: "9", shift: { latex: "\xE7" }, variants: "9" }, { label: "0", shift: { latex: "\xE0" }, variants: "0" } ] ] : [ [ { label: "1", variants: "1" }, { label: "2", variants: "2" }, { label: "3", variants: "3" }, { label: "4", variants: "4" }, { label: "5", shift: { latex: "\\frac{#@}{#?}" }, variants: "5" }, { label: "6", shift: { latex: "#@^#?" }, variants: "6" }, { label: "7", variants: "7" }, { label: "8", shift: { latex: "\\times" }, variants: "8" }, { label: "9", shift: { label: "(", latex: "(" }, variants: "9" }, { label: "0", shift: { label: ")", latex: ")" }, variants: "0" } ] ]; for (const templateRow of template) { const row = []; for (const k of templateRow) { if (/[a-z]/.test(k)) { row.push({ label: k, class: "hide-shift", shift: { label: k.toUpperCase() }, variants: hasVariants(k) ? k : void 0 }); } else if (k === "~") { if (layoutName !== "dvorak") row.push("[backspace]"); else row.push({ label: "[backspace]", width: 1 }); } else if (k === "^") row.push("[shift]"); else if (k === " ") row.push("[separator-5]"); } rows.push(row); } rows.push([ // { // class: 'action', // label: 'text mode', // command: ['performWithFeedback', ['switchMode', 'text', '', '']], // }, "[-]", "[+]", "[=]", { label: " ", width: 1.5 }, { label: ",", shift: ";", variants: ".", class: "hide-shift" }, "[.]", "[left]", "[right]", { label: "[action]", width: 1.5 } ]); return { label: "abc", labelClass: "MLK__tex-math", tooltip: "keyboard.tooltip.alphabetic", layers: normalizeLayer({ rows }) }; } function normalizeLayout(layout) { if (layout === "alphabetic") return alphabeticLayout(); if (typeof layout === "string") { console.assert( LAYOUTS[layout] !== void 0, `MathLive 0.98.5: unknown keyboard layout "${layout}"` ); return normalizeLayout(LAYOUTS[layout]); } let result; if ("rows" in layout && Array.isArray(layout.rows)) { console.assert( !("layers" in layout || "markup" in layout), `MathLive 0.98.5: when providing a "rows" property, "layers" and "markup" are ignored` ); const _a3 = layout, { rows } = _a3, partialLayout = __objRest(_a3, ["rows"]); result = __spreadProps(__spreadValues({}, partialLayout), { layers: normalizeLayer({ rows: layout.rows }) }); } else if ("markup" in layout && typeof layout.markup === "string") { const _b3 = layout, { markup } = _b3, partialLayout = __objRest(_b3, ["markup"]); result = __spreadProps(__spreadValues({}, partialLayout), { layers: normalizeLayer(layout.markup) }); } else { result = __spreadValues({}, layout); if ("layers" in layout) result.layers = normalizeLayer(layout.layers); else { console.error( `MathLive 0.98.5: provide either a "rows", "markup" or "layers" property` ); } } let hasShift = false; let hasEdit = false; for (const layer of result.layers) { if (layer.rows) { for (const keycap of layer.rows.flat()) { if (isShiftKey(keycap)) hasShift = true; const command = keycap.command; if (typeof command === "string" && ["undo", "redo", "cut", "copy", "paste"].includes(command)) hasEdit = true; } } } if (!("displayShiftedKeycaps" in layout) || layout.displayShiftedKeycaps === void 0) result.displayShiftedKeycaps = hasShift; if (!("displayEditToolbar" in layout) || layout.displayEditToolbar === void 0) result.displayEditToolbar = !hasEdit; return result; } function makeLayoutsToolbar(keyboard, index) { var _a3, _b3; let markup = `
    `; if (keyboard.normalizedLayouts.length > 1) { for (const [i, l] of keyboard.normalizedLayouts.entries()) { const layout = l; const classes = [i === index ? "selected" : "layer-switch"]; if (layout.tooltip) classes.push("MLK__tooltip"); if (layout.labelClass) classes.push(...layout.labelClass.split(" ")); markup += `
    ${(_b3 = layout.label) != null ? _b3 : "untitled"}
    `; } } markup += "
    "; return markup; } function makeEditToolbar(options, mathfield) { let result = ""; const toolbarOptions = options.editToolbar; if (toolbarOptions === "none") return ""; const availableActions = []; if (mathfield.selectionIsCollapsed) availableActions.push("undo", "redo", "pasteFromClipboard"); else { availableActions.push( "cutToClipboard", "copyToClipboard", "pasteFromClipboard" ); } const actionsMarkup = { undo: `
    `, redo: `
    `, cutToClipboard: `
    `, copyToClipboard: `
    `, pasteFromClipboard: `
    ` }; result += availableActions.map((action) => actionsMarkup[action]).join(""); return result; } function makeSyntheticKeycaps(elementList) { for (const element of elementList) makeSyntheticKeycap(element); } function makeSyntheticKeycap(element) { const keyboard = VirtualKeyboard.singleton; if (!keyboard) return; const keycap = {}; if (!element.id) { if (element.hasAttribute("data-label")) keycap.label = element.dataset.label; if (element.hasAttribute("data-latex")) keycap.latex = element.dataset.latex; if (element.hasAttribute("data-key")) keycap.key = element.dataset.key; if (element.hasAttribute("data-insert")) keycap.insert = element.dataset.insert; if (element.hasAttribute("data-variants")) keycap.variants = element.dataset.variants; if (element.hasAttribute("data-aside")) keycap.aside = element.dataset.aside; if (element.className) keycap.class = element.className; if (!keycap.label && !keycap.latex && !keycap.key && !keycap.insert) { keycap.latex = element.innerText; keycap.label = element.innerHTML; } if (element.hasAttribute("data-command")) { try { keycap.command = JSON.parse(element.dataset.command); } catch (e) { } } element.id = keyboard.registerKeycap(keycap); } if (!element.innerHTML) { const [markup, _] = renderKeycap(keycap); element.innerHTML = window.MathfieldElement.createHTML(markup); } } function injectStylesheets() { injectStylesheet("virtual-keyboard"); injectStylesheet("core"); void loadFonts(); } function releaseStylesheets() { releaseStylesheet("core"); releaseStylesheet("virtual-keyboard"); } var SVG_ICONS = ` `; function makeKeyboardElement(keyboard) { keyboard.resetKeycapRegistry(); injectStylesheets(); const result = document.createElement("div"); result.className = "ML__keyboard"; const plate = document.createElement("div"); plate.className = "MLK__plate"; plate.innerHTML = window.MathfieldElement.createHTML( SVG_ICONS + keyboard.normalizedLayouts.map((x, i) => makeLayout(keyboard, x, i)).join("") ); const backdrop = document.createElement("div"); backdrop.className = "MLK__backdrop"; backdrop.appendChild(plate); result.appendChild(backdrop); result.addEventListener("pointerdown", handlePointerDown, { passive: false }); const toolbars = result.querySelectorAll(".ML__edit-toolbar"); if (toolbars) { for (const toolbar of toolbars) { toolbar.addEventListener("click", (ev) => { var _a3, _b3; let target = ev.target; let command = ""; while (target && !command) { command = (_a3 = target == null ? void 0 : target.getAttribute("data-command")) != null ? _a3 : ""; target = (_b3 = target == null ? void 0 : target.parentElement) != null ? _b3 : null; } if (command) keyboard.executeCommand(JSON.parse(command)); }); } } makeSyntheticKeycaps( result.querySelectorAll( ".MLK__keycap, .action, .fnbutton, .bigfnbutton" ) ); const layerElements = result.querySelectorAll(".MLK__layer"); console.assert(layerElements.length > 0, "No virtual keyboards available"); for (const x of layerElements) x.addEventListener("pointerdown", (evt) => evt.preventDefault()); keyboard.currentLayer = keyboard.latentLayer; return result; } function makeLayout(keyboard, layout, index) { const markup = []; if (!("layers" in layout)) return ""; for (const layer of layout.layers) { markup.push(`
    `); if (keyboard.normalizedLayouts.length > 1 || layout.displayEditToolbar) { markup.push(``); } markup.push(makeLayer(keyboard, layer)); markup.push("
    "); } return markup.join(""); } function makeLayer(keyboard, layer) { if (typeof layer === "string") return layer; let layerMarkup = ""; if (typeof layer.style === "string") layerMarkup += ``; else if (typeof layer.style === "object") layerMarkup += ``; if (layer.backdrop) layerMarkup += `
    `; if (layer.container) layerMarkup += `
    `; if (layer.rows) { layerMarkup += `
    `; for (const row of layer.rows) { layerMarkup += `
    `; for (const keycap of row) { if (keycap) { const keycapId = keyboard.registerKeycap(keycap); const [markup, cls] = renderKeycap(keycap); if (/(^|\s)separator/.test(cls)) layerMarkup += `
    ${markup}
    `; } } layerMarkup += `
    `; } layerMarkup += `
    `; } else if (layer.markup) layerMarkup += layer.markup; if (layer.container) layerMarkup += "
    "; if (layer.backdrop) layerMarkup += "
    "; return layerMarkup; } function renderKeycap(keycap, options = { shifted: false }) { var _a3, _b3, _c2, _d2, _e, _f, _g; let markup = ""; let cls = (_a3 = keycap.class) != null ? _a3 : ""; if (options.shifted && isShiftKey(keycap)) cls += " is-active"; if (options.shifted && "shift" in keycap) { if (typeof keycap.shift === "string") markup = latexToMarkup2(keycap.shift); else if (typeof keycap.shift === "object") { markup = keycap.shift.label ? keycap.shift.label : ( // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing (_b3 = latexToMarkup2(keycap.shift.latex || keycap.shift.insert || "") || keycap.shift.key) != null ? _b3 : "" ); } if (typeof keycap.shift === "object") cls = (_d2 = (_c2 = keycap.shift.class) != null ? _c2 : keycap.class) != null ? _d2 : ""; } else { markup = keycap.label ? keycap.label : ( // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing (_e = latexToMarkup2(keycap.latex || keycap.insert || "") || keycap.key) != null ? _e : "" ); if (keycap.shift) { let shiftLabel; if (typeof keycap.shift === "string") shiftLabel = latexToMarkup2(keycap.shift); else if (keycap.shift.label) shiftLabel = keycap.shift.label; else { shiftLabel = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing (_f = latexToMarkup2(keycap.shift.latex || keycap.shift.insert || "") || keycap.shift.key) != null ? _f : ""; } markup += `${shiftLabel}`; } if (keycap.aside) markup += ``; } if (keycap.layer && !/layer-switch/.test(cls)) cls += " layer-switch"; if (!/(^|\s)(separator|action|shift|fnbutton|bigfnbutton)($|\s)/.test(cls)) cls += " MLK__keycap"; if (!/\bw[0-9]+\b/.test(cls) && keycap.width) { cls += (_g = { 0: " w0", 0.5: " w5", 1.5: " w15", 2: " w20", 5: " w50" }[keycap.width]) != null ? _g : ""; } return [markup, cls || "MLK__keycap"]; } var KEYCAP_SHORTCUTS = { "[left]": { class: "action hide-shift", label: "", command: ["performWithFeedback", "moveToPreviousChar"], shift: { label: "", command: ["performWithFeedback", "extendSelectionBackward"] } }, "[right]": { class: "action hide-shift", label: "", command: ["performWithFeedback", "moveToNextChar"], shift: { label: "", command: ["performWithFeedback", "extendSelectionForward"] } }, "[up]": { class: "action hide-shift", label: "\u2191", command: ["performWithFeedback", "moveUp"], shift: { label: "\u219F", command: ["performWithFeedback", "extendSelectionUpward"] } }, "[down]": { class: "action hide-shift", label: "\u2193", command: ["performWithFeedback", "moveDown"], shift: { label: "\u21A1", command: ["performWithFeedback", "extendSelectionDownward"] } }, "[return]": { class: "action hide-shift", command: ["performWithFeedback", "commit"], shift: { command: ["performWithFeedback", "addRowAfter"] }, width: 1.5, label: "" }, "[action]": { class: "action hide-shift", command: ["performWithFeedback", "commit"], shift: { label: "", command: ["performWithFeedback", "addRowAfter"] }, width: 1.5, label: "" }, "[hr]": { class: "separator horizontal-rule" }, "[hide-keyboard]": { class: "action", command: ["hideVirtualKeyboard"], width: 1.5, label: "" }, "[.]": { variants: ".", command: ["performWithFeedback", "insertDecimalSeparator"], shift: ",", class: "big-op hide-shift", label: "." }, "[,]": { variants: ",", command: ["performWithFeedback", "insertDecimalSeparator"], shift: ".", class: "big-op hide-shift", label: "," }, "[+]": { variants: [{ latex: "\\sum_{#0}^{#0}", class: "small" }, "\\oplus"], latex: "+", label: "+", class: "big-op hide-shift", shift: { latex: "\\sum", insert: "\\sum", class: "small" } }, "[-]": { variants: ["\\pm", "\\ominus"], latex: "-", label: "−", shift: "\\pm", class: "big-op hide-shift" }, "[/]": { class: "big-op hide-shift", shift: { class: "", latex: "\\frac{1}{#@}" }, variants: ["/", "\\div", "\\%", "\\oslash"], latex: "\\frac{#@}{#?}", label: "÷" }, "[*]": { variants: [ { latex: "\\prod_{#0}^{#0}", class: "small" }, "\\otimes", "\\cdot" ], latex: "\\cdot", label: "×", shift: { latex: "\\times" }, class: "big-op hide-shift" }, "[=]": { variants: [ "\\neq", "\\equiv", "\\varpropto", "\\thickapprox", "\\lt", "\\gt", "\\le", "\\ge" ], latex: "=", label: "=", shift: { label: "\u2260", latex: "\\ne" }, class: "big-op hide-shift" }, "[backspace]": { class: "action bottom right hide-shift", width: 1.5, command: ["performWithFeedback", "deleteBackward"], label: "", shift: { class: "action warning", label: "", command: "deleteAll" } }, "[undo]": { class: "ghost if-can-undo", command: "undo", label: "", tooltip: "tooltip.undo" }, "[redo]": { class: "ghost if-can-redo", command: "redo", label: "", tooltip: "tooltip.redo" }, "[(]": { variants: [ // We insert the fences as "keys" so they can be handled by smartFence. // They will be sent via `onKeystroke` instead of inserted directly in // the model { latex: "\\lbrack", key: "[" }, "\\langle", "\\lfloor", "\\lceil", { latex: "\\lbrace", key: "{" } ], key: "(", label: "(", shift: { label: "[", key: "[" }, class: "hide-shift" }, "[)]": { variants: [ { latex: "\\rbrack", key: "]" }, "\\rangle", "\\rfloor", "\\rceil", { latex: "\\rbrace", key: "]" } ], key: ")", label: ")", shift: { label: "]", latex: "\\rbrack" }, class: "hide-shift" }, "[0]": { variants: "0", latex: "0", label: "0", shift: "\\infty", class: "hide-shift" }, "[1]": { variants: "1", latex: "1", label: "1", shift: "#@^{-1}", class: "hide-shift" }, "[2]": { variants: "2", latex: "2", label: "2", shift: "#@^2", class: "hide-shift" }, "[3]": { variants: "3", latex: "3", label: "3", shift: "#@^3", class: "hide-shift" }, "[4]": { variants: "4", latex: "4", label: "4", shift: "#@^4", class: "hide-shift" }, "[5]": { variants: "5", latex: "5", label: "5", shift: "#@^5", class: "hide-shift" }, "[6]": { variants: "6", latex: "6", label: "6", shift: "#@^6", class: "hide-shift" }, "[7]": { variants: "7", latex: "7", label: "7", shift: "#@^7", class: "hide-shift" }, "[8]": { variants: "8", latex: "8", label: "8", shift: "#@^8", class: "hide-shift" }, "[9]": { variants: "9", latex: "9", label: "9", shift: "#@^9", class: "hide-shift" }, "[separator-5]": { class: "separator", width: 0.5 }, "[separator]": { class: "separator" }, "[separator-10]": { class: "separator" }, "[separator-15]": { class: "separator", width: 1.5 }, "[separator-20]": { class: "separator", width: 2 }, "[separator-50]": { class: "separator", width: 5 }, "[shift]": { class: "shift bottom left", width: 1.5, label: "" }, "[foreground-color]": { variants: "foreground-color", command: ["applyStyle", { color: "red" }], label: "" }, "[background-color]": { variants: "background-color", command: ["applyStyle", { backgroundColor: "yellow" }], label: "" } }; function normalizeKeycap(keycap) { var _a3; if (typeof keycap === "string") { if (keycap === "[.]" && window.MathfieldElement.decimalSeparator === ",") keycap = "[,]"; if (!KEYCAP_SHORTCUTS[keycap]) return { latex: keycap }; keycap = { label: keycap }; } let shortcut = void 0; if ("label" in keycap && keycap.label && KEYCAP_SHORTCUTS[keycap.label]) { shortcut = __spreadProps(__spreadValues(__spreadValues({}, KEYCAP_SHORTCUTS[keycap.label]), keycap), { label: KEYCAP_SHORTCUTS[keycap.label].label }); } if ("key" in keycap && keycap.key && KEYCAP_SHORTCUTS[keycap.key]) { shortcut = __spreadProps(__spreadValues(__spreadValues({}, KEYCAP_SHORTCUTS[keycap.key]), keycap), { key: KEYCAP_SHORTCUTS[keycap.key].key }); } if (shortcut) { if (shortcut.command === "insertDecimalSeparator") shortcut.label = (_a3 = window.MathfieldElement.decimalSeparator) != null ? _a3 : "."; if (keycap.label === "[action]") { shortcut = __spreadValues(__spreadValues({}, shortcut), window.mathVirtualKeyboard.actionKeycap); } if (keycap.label === "[shift]") { shortcut = __spreadValues(__spreadValues({}, shortcut), window.mathVirtualKeyboard.shiftKeycap); } if (keycap.label === "[backspace]") { shortcut = __spreadValues(__spreadValues({}, shortcut), window.mathVirtualKeyboard.backspaceKeycap); } if (keycap.label === "[tab]") { shortcut = __spreadValues(__spreadValues({}, shortcut), window.mathVirtualKeyboard.tabKeycap); } return shortcut; } return keycap; } var pressAndHoldTimer; function handlePointerDown(ev) { var _a3; if (ev.button !== 0) return; const keyboard = VirtualKeyboard.singleton; if (!keyboard) return; let layerButton = ev.target; while (layerButton && !layerButton.getAttribute("data-layer")) layerButton = layerButton.parentElement; if (layerButton) { keyboard.currentLayer = (_a3 = layerButton.getAttribute("data-layer")) != null ? _a3 : ""; ev.preventDefault(); return; } const target = parentKeycap(ev.target); if (!(target == null ? void 0 : target.id)) return; const keycap = keyboard.getKeycap(target.id); if (!keycap) return; console.assert(ev.type === "pointerdown"); const controller = new AbortController(); const signal = controller.signal; target.classList.add("is-pressed"); target.addEventListener( "pointerenter", handleVirtualKeyboardEvent(controller), { capture: true, signal } ); target.addEventListener( "pointerleave", handleVirtualKeyboardEvent(controller), { capture: true, signal } ); target.addEventListener( "pointercancel", handleVirtualKeyboardEvent(controller), { signal } ); target.addEventListener("pointerup", handleVirtualKeyboardEvent(controller), { signal }); if (isShiftKey(keycap)) { target.classList.add("is-active"); keyboard.shiftPressCount++; } if (keycap.variants) { if (pressAndHoldTimer) clearTimeout(pressAndHoldTimer); pressAndHoldTimer = setTimeout(() => { if (target.classList.contains("is-pressed")) { target.classList.remove("is-pressed"); target.classList.add("is-active"); if (ev.target && "releasePointerCapture" in ev.target) ev.target.releasePointerCapture(ev.pointerId); showVariantsPanel(target, () => { controller.abort(); target == null ? void 0 : target.classList.remove("is-active"); }); } }, 300); } ev.preventDefault(); } function handleVirtualKeyboardEvent(controller) { return (ev) => { const target = parentKeycap(ev.target); if (!(target == null ? void 0 : target.id)) return; const keyboard = VirtualKeyboard.singleton; if (!keyboard) return; const keycap = keyboard.getKeycap(target.id); if (!keycap) return; if (ev.type === "pointerenter" && ev.target === target) { const pev = ev; if (pev.isPrimary) target.classList.add("is-pressed"); } if (ev.type === "pointercancel") { target.classList.remove("is-pressed"); if (isShiftKey(keycap)) { keyboard.shiftPressCount--; target.classList.toggle("is-active", keyboard.isShifted); } controller.abort(); return; } if (ev.type === "pointerleave" && ev.target === target) { target.classList.remove("is-pressed"); if (isShiftKey(keycap)) { keyboard.shiftPressCount--; target.classList.toggle("is-active", keyboard.isShifted); } return; } if (ev.type === "pointerup") { if (pressAndHoldTimer) clearTimeout(pressAndHoldTimer); if (isShiftKey(keycap)) { target.classList.toggle("is-active", keyboard.isShifted); } else if (target.classList.contains("is-pressed")) { target.classList.remove("is-pressed"); if (keyboard.isShifted && keycap.shift) { if (typeof keycap.shift === "string") { keyboard.executeCommand([ "insert", keycap.shift, { focus: true, feedback: true, scrollIntoView: true, mode: "math", format: "latex" } ]); } else executeKeycapCommand(keycap.shift); } else executeKeycapCommand(keycap); if (keyboard.shiftPressCount === 1 && !ev.shiftKey) keyboard.shiftPressCount = 0; } controller.abort(); ev.preventDefault(); return; } }; } function executeKeycapCommand(keycap) { var _a3; let command = keycap.command; if (!command && keycap.insert) { command = [ "insert", keycap.insert, { focus: true, feedback: true, scrollIntoView: true, mode: "math", format: "latex" } ]; } if (!command && keycap.key) { command = [ "typedText", keycap.key, { focus: true, feedback: true, simulateKeystroke: true } ]; } if (!command && keycap.latex) { command = [ "insert", keycap.latex, { focus: true, feedback: true, scrollIntoView: true, mode: "math", format: "latex" } ]; } if (!command) { command = [ "typedText", keycap.label, { focus: true, feedback: true, simulateKeystroke: true } ]; } (_a3 = VirtualKeyboard.singleton) == null ? void 0 : _a3.executeCommand(command); } function isKeycapElement(el) { if (el.nodeType !== 1) return false; const classes = el.classList; return classes.contains("MLK__keycap") || classes.contains("shift") || classes.contains("action") || classes.contains("fnbutton") || classes.contains("bigfnbutton"); } function parentKeycap(el) { if (!el) return void 0; let node = el; while (node && !isKeycapElement(node)) node = node.parentElement; return node != null ? node : void 0; } function isShiftKey(k) { return !!k.class && /(^|\s)shift($|\s)/.test(k.class); } // src/virtual-keyboard/virtual-keyboard.ts var VirtualKeyboard = class _VirtualKeyboard { constructor() { this.originalContainerBottomPadding = null; this.keycapRegistry = {}; /** * `0`: not pressed * `1`: Shift is locked for next char only * `2`: Shift is locked for all characters */ this._shiftPressCount = 0; var _a3, _b3, _c2; this.targetOrigin = window.origin; this.originValidator = "none"; this._alphabeticLayout = "auto"; this._layouts = Object.freeze(["default"]); this._editToolbar = "default"; this._container = (_b3 = (_a3 = window.document) == null ? void 0 : _a3.body) != null ? _b3 : null; this._visible = false; this._rebuilding = false; this.observer = new ResizeObserver((_entries) => { this.adjustBoundingRect(); this.dispatchEvent(new Event("geometrychange")); this.sendMessage("geometry-changed", { boundingRect: this.boundingRect }); }); this.listeners = {}; try { (_c2 = window.top) == null ? void 0 : _c2.addEventListener("message", this); } catch (e) { window.addEventListener("message", this); } document.body.addEventListener("focusin", (event) => { const target = event.target; if (!(target == null ? void 0 : target.isConnected)) return; setTimeout(() => { const mf = focusedMathfield(); if (mf && !mf.readOnly && mf.mathVirtualKeyboardPolicy === "auto" && isTouchCapable()) this.show({ animate: true }); }, 300); }); document.addEventListener("focusout", (evt) => { const target = evt.target; if (target.mathVirtualKeyboardPolicy !== "manual") { setTimeout(() => { if (!focusedMathfield()) this.hide(); }, 300); } }); } get currentLayer() { var _a3, _b3, _c2; return (_c2 = (_b3 = (_a3 = this._element) == null ? void 0 : _a3.querySelector(".MLK__layer.is-visible")) == null ? void 0 : _b3.id) != null ? _c2 : ""; } set currentLayer(id) { var _a3; if (!this._element) { this.latentLayer = id; return; } let newActive = id ? this._element.querySelector(`#${id}.MLK__layer`) : null; if (!newActive) newActive = this._element.querySelector(".MLK__layer"); if (newActive) { (_a3 = this._element.querySelector(".MLK__layer.is-visible")) == null ? void 0 : _a3.classList.remove("is-visible"); newActive.classList.add("is-visible"); } this.render(); } get shiftPressCount() { return this._shiftPressCount; } set shiftPressCount(count) { var _a3; this._shiftPressCount = count > 2 || count < 0 ? 0 : count; (_a3 = this._element) == null ? void 0 : _a3.classList.toggle("is-caps-lock", this.shiftPressCount === 2); this.render(); } get isShifted() { return this._shiftPressCount > 0; } resetKeycapRegistry() { this.keycapRegistry = {}; } registerKeycap(keycap) { const id = "ML__k" + Date.now().toString(36).slice(-2) + Math.floor(Math.random() * 1e5).toString(36); this.keycapRegistry[id] = keycap; return id; } getKeycap(id) { return id ? this.keycapRegistry[id] : void 0; } getLayer(id) { const layouts = this.normalizedLayouts; for (const layout of layouts) for (const layer of layout.layers) if (layer.id === id) return layer; return void 0; } get alphabeticLayout() { return this._alphabeticLayout; } set alphabeticLayout(value) { this._alphabeticLayout = value; this.rebuild(); } get actionKeycap() { return this._actionKeycap; } set actionKeycap(value) { this._actionKeycap = typeof value === "string" ? { label: value } : value; } get shiftKeycap() { return this._shiftKeycap; } set shiftKeycap(value) { this._shiftKeycap = typeof value === "string" ? { label: value } : value; } get backspaceKeycap() { return this._backspaceKeycap; } set backspaceKeycap(value) { this._backspaceKeycap = typeof value === "string" ? { label: value } : value; } get tabKeycap() { return this._tabKeycap; } set tabKeycap(value) { this._tabKeycap = typeof value === "string" ? { label: value } : value; } get layouts() { return this._layouts; } set layouts(value) { this.updateNormalizedLayouts(value); this.rebuild(); } updateNormalizedLayouts(value) { const layouts = Array.isArray(value) ? [...value] : [value]; const defaultIndex = layouts.findIndex((x) => x === "default"); if (defaultIndex >= 0) { layouts.splice( defaultIndex, 1, "numeric", "symbols", "alphabetic", "greek" ); } this._layouts = Object.freeze(layouts); this._normalizedLayouts = layouts.map((x) => normalizeLayout(x)); } get normalizedLayouts() { if (!this._normalizedLayouts) this.updateNormalizedLayouts(this._layouts); return this._normalizedLayouts; } get editToolbar() { return this._editToolbar; } set editToolbar(value) { this._editToolbar = value; this.rebuild(); } get container() { return this._container; } set container(value) { this._container = value; this.rebuild(); } static get singleton() { if (this._singleton === void 0) { try { this._singleton = new _VirtualKeyboard(); } catch (e) { this._singleton = null; } } return this._singleton; } get style() { return this._style; } addEventListener(type, callback, _options) { if (!this.listeners[type]) this.listeners[type] = /* @__PURE__ */ new Set(); if (!this.listeners[type].has(callback)) this.listeners[type].add(callback); } dispatchEvent(event) { if (!this.listeners[event.type] || this.listeners[event.type].size === 0) return true; this.listeners[event.type].forEach((x) => { if (typeof x === "function") x(event); else x == null ? void 0 : x.handleEvent(event); }); return !event.defaultPrevented; } removeEventListener(type, callback, _options) { if (this.listeners[type]) this.listeners[type].delete(callback); } get element() { return this._element; } set element(val) { var _a3; if (this._element === val) return; (_a3 = this._element) == null ? void 0 : _a3.remove(); this._element = val; } get visible() { return this._visible; } set visible(val) { if (val) this.show(); else this.hide(); } get boundingRect() { var _a3; if (!this._visible) return new DOMRect(); const plate = (_a3 = this._element) == null ? void 0 : _a3.getElementsByClassName("MLK__plate")[0]; if (plate) return plate.getBoundingClientRect(); return new DOMRect(); } adjustBoundingRect() { var _a3, _b3; const h = this.boundingRect.height; if (this.container === document.body) { (_a3 = this._element) == null ? void 0 : _a3.style.setProperty( "--_keyboard-height", `calc(${h}px + var(--_padding-top) + var(--_padding-bottom) + env(safe-area-inset-bottom, 0))` ); const keyboardHeight = h - 1; this.container.style.paddingBottom = this.originalContainerBottomPadding ? `calc(${this.originalContainerBottomPadding} + ${keyboardHeight}px)` : `${keyboardHeight}px`; } else (_b3 = this._element) == null ? void 0 : _b3.style.setProperty("--_keyboard-height", `${h}px`); } rebuild() { if (this._rebuilding || !this._element) return; this._rebuilding = true; const currentLayerId = this.currentLayer; requestAnimationFrame(() => { this._rebuilding = false; if (this._element) { this._element.remove(); this._element = void 0; } if (this.visible) { this.buildAndAttachElement(); this.currentLayer = currentLayerId; this.render(); this.adjustBoundingRect(); this._element.classList.add("is-visible"); } }); } /** Update the keycaps to account for the current state */ render() { if (!this._element) return; const layer = this.getLayer(this.currentLayer); this._element.classList.toggle( "backdrop-is-transparent", Boolean(layer && (layer.backdrop || layer.container)) ); const keycaps = this._element.querySelectorAll( ".MLK__layer.is-visible .MLK__keycap, .MLK__layer.is-visible .action, .fnbutton, .MLK__layer.is-visible .bigfnbutton, .MLK__layer.is-visible .shift" ); if (!keycaps) return; for (const keycapElement of keycaps) { const keycap = this.getKeycap(keycapElement.id); if (keycap) { const [markup, cls] = renderKeycap(keycap, { shifted: this.isShifted }); keycapElement.innerHTML = window.MathfieldElement.createHTML(markup); keycapElement.className = cls; } } } show(options) { var _a3; if (this._visible) return; const container = this.container; if (!container) return; if (!window.mathVirtualKeyboard) return; if (!this.stateWillChange(true)) return; if (!this._element) { this.buildAndAttachElement(); this.adjustBoundingRect(); } if (!this._visible) { const plate = this._element.getElementsByClassName( "MLK__plate" )[0]; if (plate) this.observer.observe(plate); if (container === window.document.body) { const padding2 = container.style.paddingBottom; this.originalContainerBottomPadding = padding2; const keyboardHeight = plate.offsetHeight - 1; container.style.paddingBottom = padding2 ? `calc(${padding2} + ${keyboardHeight}px)` : `${keyboardHeight}px`; } window.addEventListener("mouseup", this); window.addEventListener("blur", this); window.addEventListener("keydown", this, { capture: true }); window.addEventListener("keyup", this, { capture: true }); (_a3 = this._element) == null ? void 0 : _a3.classList.toggle( "is-caps-lock", this.shiftPressCount === 2 ); this.currentLayer = this.latentLayer; } this._visible = true; if (options == null ? void 0 : options.animate) { requestAnimationFrame(() => { if (this._element) { this._element.classList.add("animate"); this._element.addEventListener( "transitionend", () => { var _a4; return (_a4 = this._element) == null ? void 0 : _a4.classList.remove("animate"); }, { once: true } ); this._element.classList.add("is-visible"); this.stateChanged(); } }); } else { this._element.classList.add("is-visible"); this.stateChanged(); } } hide(_options) { var _a3; const container = this.container; if (!container) return; if (!this._visible) return; if (!this.stateWillChange(false)) return; this._visible = false; if (this._element) { this.latentLayer = this.currentLayer; const plate = this._element.getElementsByClassName("MLK__plate")[0]; if (plate) this.observer.unobserve(plate); window.removeEventListener("mouseup", this); window.removeEventListener("blur", this); window.removeEventListener("keydown", this, { capture: true }); window.removeEventListener("keyup", this, { capture: true }); window.removeEventListener("contextmenu", this, { capture: true }); hideVariantsPanel(); releaseStylesheets(); (_a3 = this._element) == null ? void 0 : _a3.remove(); this._element = void 0; if (this.originalContainerBottomPadding !== null) container.style.paddingBottom = this.originalContainerBottomPadding; } this.stateChanged(); } get height() { var _a3, _b3; return (_b3 = (_a3 = this.element) == null ? void 0 : _a3.offsetHeight) != null ? _b3 : 0; } buildAndAttachElement() { var _a3; console.assert(!this.element); this.element = makeKeyboardElement(this); window.addEventListener("contextmenu", this, { capture: true }); this.element.addEventListener( "contextmenu", (ev) => { if (!ev.shiftKey) { if (ev.ctrlKey || ev.button === 2) showVariantsPanel(ev.target); ev.preventDefault(); ev.stopPropagation(); } }, { capture: true } ); (_a3 = this.container) == null ? void 0 : _a3.appendChild(this.element); } handleEvent(evt) { if (isVirtualKeyboardMessage(evt)) { if (!validateOrigin(evt.origin, this.originValidator)) { throw new DOMException( `Message from unknown origin (${evt.origin}) cannot be handled`, "SecurityError" ); } if (evt.data.action === "disconnect") this.connectedMathfieldWindow = void 0; else if (evt.data.action !== "update-setting" && evt.data.action !== "proxy-created" && evt.data.action !== "execute-command") { console.assert(evt.source !== void 0); this.connectedMathfieldWindow = evt.source; } this.handleMessage(evt.data, evt.source); } if (!this._element) return; switch (evt.type) { case "mouseup": case "blur": document.body.style.userSelect = ""; this.shiftPressCount = 0; break; case "contextmenu": if (evt.button !== 2) evt.preventDefault(); break; case "keydown": { if (evt.key === "Shift" && !evt.repeat) this.shiftPressCount = 1; break; } case "keyup": { if (evt.key === "Shift" || !evt.getModifierState("Shift") && this.shiftPressCount !== 2) this.shiftPressCount = 0; break; } } } handleMessage(msg, source) { const { action } = msg; if (action === "execute-command") { const { command } = msg; const commandTarget = getCommandTarget(command); if (window.top !== void 0 && commandTarget !== "virtual-keyboard") return; this.executeCommand(command); return; } if (action === "connect" || action === "show") { this.sendMessage( "synchronize-proxy", { boundingRect: this.boundingRect, alphabeticLayout: this._alphabeticLayout, layouts: this._layouts, editToolbar: this._editToolbar }, source ); } if (action === "disconnect") return; if (window !== window.top) return; if (action === "show") { if (typeof msg.animate !== "undefined") this.show({ animate: msg.animate }); else this.show(); return; } if (action === "hide") { if (typeof msg.animate !== "undefined") this.hide({ animate: msg.animate }); else this.hide(); return; } if (action === "update-setting") { if (msg.alphabeticLayout) this.alphabeticLayout = msg.alphabeticLayout; if (msg.layouts) this.layouts = msg.layouts; if (msg.editToolbar) this.editToolbar = msg.editToolbar; return; } if (action === "proxy-created") { this.sendMessage( "synchronize-proxy", { boundingRect: this.boundingRect, alphabeticLayout: this._alphabeticLayout, layouts: this._layouts, editToolbar: this._editToolbar }, source ); return; } } sendMessage(action, payload, target) { if (!target) target = this.connectedMathfieldWindow; if (this.targetOrigin === null || this.targetOrigin === "null" || target === window) { window.dispatchEvent( new MessageEvent("message", { source: window, data: __spreadValues({ type: VIRTUAL_KEYBOARD_MESSAGE, action }, payload) }) ); return; } if (target) { target.postMessage( __spreadValues({ type: VIRTUAL_KEYBOARD_MESSAGE, action }, payload), { targetOrigin: this.targetOrigin } ); } else { if (payload.command) { this.dispatchEvent( new CustomEvent("math-virtual-keyboard-command", { detail: payload.command }) ); } if (action === "execute-command" && Array.isArray(payload.command) && payload.command[0] === "insert") { const s = payload.command[1].split(""); for (const c of s) { this.dispatchEvent( new KeyboardEvent("keydown", { key: c, bubbles: true }) ); this.dispatchEvent( new KeyboardEvent("keyup", { key: c, bubbles: true }) ); } } } } stateWillChange(visible) { const defaultNotPrevented = this.dispatchEvent( new CustomEvent("before-virtual-keyboard-toggle", { detail: { visible }, bubbles: true, cancelable: true, composed: true }) ); return defaultNotPrevented; } stateChanged() { this.dispatchEvent(new Event("virtual-keyboard-toggle")); if (!this._visible) { this.dispatchEvent(new Event("geometrychange")); this.sendMessage("geometry-changed", { boundingRect: this.boundingRect }); } } /** * @category Focus */ focus() { this.sendMessage("focus", {}); } /** * @category Focus */ blur() { this.sendMessage("blur", {}); } updateToolbar(mf) { const el = this._element; if (!el) return; el.classList.toggle("is-math-mode", mf.mode === "math"); el.classList.toggle("is-text-mode", mf.mode === "text"); el.classList.toggle("can-undo", mf.canUndo); el.classList.toggle("can-redo", mf.canRedo); el.classList.toggle("can-copy", !mf.selectionIsCollapsed); el.classList.toggle("can-copy", !mf.selectionIsCollapsed); el.classList.toggle("can-paste", true); const toolbars = el.querySelectorAll(".ML__edit-toolbar"); if (!toolbars) return; for (const toolbar of toolbars) toolbar.innerHTML = makeEditToolbar(this, mf); } update(mf) { this._style = mf.style; this.updateToolbar(mf); } connect() { this.connectedMathfieldWindow = window; } disconnect() { this.connectedMathfieldWindow = void 0; } executeCommand(command) { let selector; let args = []; let target = getCommandTarget(command); if (isArray(command)) { selector = command[0]; if (selector === "performWithFeedback") { command = command.slice(1); target = getCommandTarget(command); } args = command.slice(1); } else selector = command; selector = selector.replace( /-\w/g, (m) => m[1].toUpperCase() ); if (target === "virtual-keyboard") return COMMANDS[selector].fn(void 0, ...args); this.sendMessage("execute-command", { command }); return false; } dispose() { window.removeEventListener("mouseup", this); window.removeEventListener("blur", this); window.removeEventListener("message", this); } }; function focusedMathfield() { var _a3, _b3; let target = deepActiveElement(); let mf = null; while (target) { if ("host" in target && ((_b3 = (_a3 = target.host) == null ? void 0 : _a3.tagName) == null ? void 0 : _b3.toLowerCase()) === "math-field") { mf = target.host; break; } target = target.parentNode; } return mf; } // src/virtual-keyboard/global.ts if (isBrowser() && !("mathVirtualKeyboard" in window)) { if (window === window["top"]) { const kbd = VirtualKeyboard.singleton; Object.defineProperty(window, "mathVirtualKeyboard", { get: () => kbd }); } else { Object.defineProperty(window, "mathVirtualKeyboard", { get: () => VirtualKeyboardProxy.singleton, configurable: true }); } } // src/editor-mathfield/options.ts function update(updates) { const result = {}; for (const key of Object.keys(updates)) { switch (key) { case "scriptDepth": const scriptDepth = updates.scriptDepth; if (isArray(scriptDepth)) result.scriptDepth = [scriptDepth[0], scriptDepth[1]]; else if (typeof scriptDepth === "number") result.scriptDepth = [scriptDepth, scriptDepth]; else if (typeof scriptDepth === "string") { const [from, to] = scriptDepth.split(",").map((x) => parseInt(x.trim())); result.scriptDepth = [from, to]; } else throw new TypeError("Unexpected value for scriptDepth"); break; case "mathVirtualKeyboardPolicy": let keyboardPolicy = updates.mathVirtualKeyboardPolicy.toLowerCase(); if (keyboardPolicy === "sandboxed") { if (window !== window["top"]) { const kbd = VirtualKeyboard.singleton; Object.defineProperty(window, "mathVirtualKeyboard", { get: () => kbd }); } keyboardPolicy = "manual"; } result.mathVirtualKeyboardPolicy = keyboardPolicy; break; case "letterShapeStyle": if (updates.letterShapeStyle === "auto") { if (l10n.locale.startsWith("fr")) result.letterShapeStyle = "french"; else result.letterShapeStyle = "tex"; } else result.letterShapeStyle = updates.letterShapeStyle; break; case "defaultMode": if (!["text", "math", "inline-math"].includes( updates.defaultMode )) { console.error( `MathLive 0.98.5: valid values for defaultMode are "text", "math" or "inline-math"` ); result.defaultMode = "math"; } else result.defaultMode = updates.defaultMode; break; case "macros": result.macros = normalizeMacroDictionary(updates.macros); break; default: if (isArray(updates[key])) result[key] = [...updates[key]]; else if (typeof updates[key] === "object" && !(updates[key] instanceof Element) && key !== "computeEngine") result[key] = __spreadValues({}, updates[key]); else result[key] = updates[key]; } } return result; } function get(config, keys) { let resolvedKeys; if (typeof keys === "string") resolvedKeys = [keys]; else if (keys === void 0) resolvedKeys = Object.keys(config); else resolvedKeys = keys; const result = {}; for (const x of resolvedKeys) { if (config[x] === null) result[x] = null; else if (isArray(config[x])) result[x] = [...config[x]]; else if (typeof config[x] === "object" && !(config[x] instanceof Element) && x !== "computeEngine") { result[x] = __spreadValues({}, config[x]); } else result[x] = config[x]; } if (typeof keys === "string") return result[keys]; return result; } function getDefault() { return { readOnly: false, defaultMode: "math", macros: {}, registers: {}, colorMap: defaultColorMap, backgroundColorMap: defaultBackgroundColorMap, letterShapeStyle: l10n.locale.startsWith("fr") ? "french" : "tex", minFontScale: 0, smartMode: false, smartFence: true, smartSuperscript: true, scriptDepth: [Infinity, Infinity], removeExtraneousParentheses: true, isImplicitFunction: (x) => [ "\\sin", "\\cos", "\\tan", "\\arcsin", "\\arccos", "\\arctan", "\\arcsec", "\\arccsc", "\\arsinh", "\\arcosh", "\\artanh", "\\arcsech", "\\arccsch", "\\arg", "\\ch", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\sec", "\\sinh", "\\sh", "\\tanh", "\\tg", "\\th", "\\lg", "\\lb", "\\log", "\\ln" ].includes(x), mathModeSpace: "", placeholderSymbol: "\u25A2", contentPlaceholder: "", popoverPolicy: "auto", environmentPopoverPolicy: "off", keybindings: DEFAULT_KEYBINDINGS, inlineShortcuts: INLINE_SHORTCUTS, inlineShortcutTimeout: 0, mathVirtualKeyboardPolicy: "auto", virtualKeyboardTargetOrigin: window == null ? void 0 : window.origin, originValidator: "none", onInlineShortcut: () => "", onScrollIntoView: null, onExport: defaultExportHook, value: "" }; } function effectiveMode(options) { if (options.defaultMode === "inline-math") return "math"; return options.defaultMode; } // src/editor-model/styling.ts function applyStyleToUnstyledAtoms(atom, style) { if (!atom || !style) return; if (isArray(atom)) { atom.forEach((x) => applyStyleToUnstyledAtoms(x, style)); } else if (typeof atom === "object") { if (!atom.style.color && !atom.style.backgroundColor && !atom.style.fontFamily && !atom.style.fontShape && !atom.style.fontSeries && !atom.style.fontSize && !atom.style.variant && !atom.style.variantStyle) { atom.applyStyle(style); applyStyleToUnstyledAtoms(atom.body, style); applyStyleToUnstyledAtoms(atom.above, style); applyStyleToUnstyledAtoms(atom.below, style); applyStyleToUnstyledAtoms(atom.subscript, style); applyStyleToUnstyledAtoms(atom.superscript, style); } } } function applyStyle(model, range2, style, options) { function everyStyle(property, value) { for (const atom of atoms) if (atom.style[property] !== value) return false; return true; } range2 = model.normalizeRange(range2); if (range2[0] === range2[1]) return false; const atoms = model.getAtoms(range2, { includeChildren: true }); if (options.operation === "toggle") { if (style.color && everyStyle("color", style.color)) { style.color = "none"; delete style.verbatimColor; } if (style.backgroundColor && everyStyle("backgroundColor", style.backgroundColor)) { style.backgroundColor = "none"; delete style.verbatimBackgroundColor; } if (style.fontFamily && everyStyle("fontFamily", style.fontFamily)) { style.fontFamily = "none"; } if (style.fontSeries && everyStyle("fontSeries", style.fontSeries)) { style.fontSeries = "auto"; } if (style.fontShape && everyStyle("fontShape", style.fontShape)) { style.fontShape = "auto"; } if (style.fontSize && everyStyle("fontSize", style.fontSize)) { style.fontSize = DEFAULT_FONT_SIZE; } if (style.variant && everyStyle("variant", style.variant)) { style.variant = "normal"; } if (style.variantStyle && everyStyle("variantStyle", style.variantStyle)) { style.variantStyle = ""; } } for (const atom of atoms) atom.applyStyle(style); return true; } // src/editor-model/composition.ts function updateComposition(model, s) { const cursor = model.at(model.position); if (cursor.type === "composition") { cursor.value = s; } else { const { caret } = cursor; cursor.caret = void 0; const atom = new CompositionAtom(s, { mode: cursor.mode }); atom.caret = caret; cursor.parent.addChildAfter(atom, cursor); model.position += 1; } } function removeComposition(model) { const cursor = model.at(model.position); if (cursor.type === "composition") { cursor.parent.removeChild(cursor); model.position -= 1; } } // src/latex-commands/environments.ts defineEnvironment(["math", "displaymath"], makeEnvironment); defineEnvironment("center", makeEnvironment); defineFunction("displaylines", "", { parse: (parser) => { const lines = []; let line = []; parser.beginContext({ tabular: true }); do { if (parser.end()) break; if (parser.match("<}>")) break; if (parser.matchColumnSeparator() || parser.matchRowSeparator()) { lines.push([line]); line = []; } else { line.push( ...parser.scan( (token) => ["<}>", "&", "\\cr", "\\\\", "\\tabularnewline"].includes(token) ) ); } } while (true); parser.endContext(); lines.push([line]); return lines; }, createAtom: (options) => new ArrayAtom("lines", options.args, [], { // arraystretch: 1.2, leftDelim: ".", rightDelim: ".", columns: [{ align: "l" }] }) }); defineTabularEnvironment( "array", "{columns:colspec}", (name, array, rowGaps, args) => { return new ArrayAtom(name, defaultContent(array), rowGaps, { columns: args[0], mathstyleName: "textstyle" }); } ); defineTabularEnvironment( ["equation", "equation*", "subequations"], "", (name, array, rowGaps) => { return new ArrayAtom(name, defaultContent(array), rowGaps, { columns: [{ align: "c" }] }); } ); defineTabularEnvironment(["multline", "multline*"], "", makeEnvironment); defineTabularEnvironment( ["align", "align*", "aligned", "eqnarray"], "", makeEnvironment ); defineTabularEnvironment("split", "", makeEnvironment); defineTabularEnvironment(["gather", "gathered"], "", makeEnvironment); defineTabularEnvironment( [ "matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*" ], "[columns:colspec]", makeEnvironment ); defineTabularEnvironment( ["smallmatrix", "smallmatrix*"], "[columns:colspec]", makeEnvironment ); defineTabularEnvironment(["cases", "dcases", "rcases"], "", makeEnvironment); function isContentEmpty(array) { for (const row of array) for (const col of row) if (col.length > 0) return false; return true; } function defaultContent(array, count = 1) { if (isContentEmpty(array)) { return Array(count).fill([ [new Atom({ type: "first" }), new PlaceholderAtom()] ]); } return array.map((row) => { if (row.length === 0) return [[new Atom({ type: "first" })]]; return row.map((cell) => { if (cell.length === 0) return [new Atom({ type: "first" })]; if (cell[0].type !== "first") cell.unshift(new Atom({ type: "first" })); return cell; }); }); } function makeEnvironment(name, content = [[[]]], rowGaps = [], args = []) { content = defaultContent( content, ["split", "align", "align*", "aligned", "eqnarray"].includes(name) ? 2 : 1 ); switch (name) { case "math": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle" }); case "displaymath": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle" }); case "center": return new ArrayAtom(name, content, rowGaps, { columns: [{ align: "c" }] }); case "multline": case "multline*": return new ArrayAtom(name, content, rowGaps, { columns: [{ align: "m" }], leftDelim: ".", rightDelim: "." }); case "split": return new ArrayAtom(name, content, rowGaps, { columns: [{ align: "r" }, { align: "l" }], minColumns: 2 }); case "gather": case "gathered": return new ArrayAtom(name, content, rowGaps, { columns: [{ gap: 0.25 }, { align: "c" }, { gap: 0 }] // colSeparationType: 'gather', }); case "pmatrix": case "pmatrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle", leftDelim: "(", rightDelim: ")", columns: defaultColumns(args[0]) }); case "bmatrix": case "bmatrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle", leftDelim: "[", rightDelim: "]", columns: defaultColumns(args[0]) }); case "Bmatrix": case "Bmatrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle", leftDelim: "\\lbrace", rightDelim: "\\rbrace", columns: defaultColumns(args[0]) }); case "vmatrix": case "vmatrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle", leftDelim: "\\vert", rightDelim: "\\vert", columns: defaultColumns(args[0]) }); case "Vmatrix": case "Vmatrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle", leftDelim: "\\Vert", rightDelim: "\\Vert", columns: defaultColumns(args[0]) }); case "matrix": case "matrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle", leftDelim: ".", rightDelim: ".", columns: defaultColumns(args == null ? void 0 : args[0]) }); case "smallmatrix": case "smallmatrix*": return new ArrayAtom(name, content, rowGaps, { mathstyleName: "scriptstyle", columns: defaultColumns(args == null ? void 0 : args[0]), colSeparationType: "small", arraystretch: 0.5 }); case "cases": case "dcases": return new ArrayAtom(name, content, rowGaps, { mathstyleName: name === "dcases" ? "displaystyle" : "textstyle", arraystretch: 1.2, leftDelim: "\\lbrace", rightDelim: ".", columns: [{ align: "l" }, { gap: 1 }, { align: "l" }] }); case "rcases": return new ArrayAtom(name, content, rowGaps, { arraystretch: 1.2, leftDelim: ".", rightDelim: "\\rbrace", columns: [{ align: "l" }, { gap: 1 }, { align: "l" }] }); case "lines": return new ArrayAtom(name, content, rowGaps, { // arraystretch: 1.2, leftDelim: ".", rightDelim: ".", columns: [{ align: "l" }] }); case "align": case "align*": case "aligned": case "eqnarray": { let colCount = 0; for (const row of content) colCount = Math.max(colCount, row.length); const columns = [ { gap: 0 }, { align: "r" }, { gap: 0.25 }, { align: "l" } ]; let i = 2; while (i < colCount) { columns.push({ gap: 1 }, { align: "r" }, { gap: 0.25 }, { align: "l" }); i += 2; } columns.push({ gap: 0 }); return new ArrayAtom(name, content, rowGaps, { arraycolsep: 0, columns, // colSeparationType: 'align', minColumns: 2 }); } } return new ArrayAtom(name, content, rowGaps, { mathstyleName: "textstyle" }); } function defaultColumns(args) { return args != null ? args : [ { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" }, { align: "c" } ]; } // src/editor-model/array.ts function parentArray(model, where) { let atom = model.at(model.position); while (atom && !(atom.parent instanceof ArrayAtom)) atom = atom.parent; if (atom && atom.type === "array") { const array = atom; if (array.environmentName === "lines") { } } if (!atom || !(atom.parent instanceof ArrayAtom)) { const cursor = model.at(model.position); atom = cursor; if (!atom.parent.parent) { let secondCell = model.extractAtoms([model.position, model.lastOffset]); let firstCell = model.extractAtoms([0, model.position]); if (firstCell.length === 0) firstCell = placeholderCell(); if (secondCell.length === 0) secondCell = placeholderCell(); let array; if (where.endsWith("column")) { array = makeEnvironment("split", [[firstCell, secondCell]]); model.root = array; if (isPlaceholderCell(array, 0, 0)) selectCell(model, array, 0, 0); else if (isPlaceholderCell(array, 0, 1)) selectCell(model, array, 0, 1); else model.position = model.offsetOf(cursor); } else { array = makeEnvironment("lines", [[firstCell], [secondCell]]); model.root = array; if (isPlaceholderCell(array, 0, 0)) selectCell(model, array, 0, 0); else if (isPlaceholderCell(array, 1, 0)) selectCell(model, array, 1, 0); else model.position = model.offsetOf(cursor); } return [void 0, [0, 0]]; } if (atom.parent instanceof LeftRightAtom) { const parent = atom.parent; let secondCell = model.extractAtoms([ model.position, model.offsetOf(parent.lastChild) ]); let firstCell = model.extractAtoms([ model.offsetOf(parent.firstChild), model.position ]); if (firstCell.length === 0) firstCell = placeholderCell(); if (secondCell.length === 0) secondCell = placeholderCell(); let envName = "pmatrix"; const lDelim = parent.leftDelim; const rDelim = parent.rightDelim; if (lDelim === "(" && (rDelim === ")" || rDelim === "?")) envName = "pmatrix"; else if ((lDelim === "[" || lDelim === "\\lbrack") && (rDelim === "]" || rDelim === "\\rbrack" || rDelim === "?")) envName = "bmatrix"; else if (lDelim === "\\vert" && rDelim === "\\vert") envName = "vmatrix"; else if (lDelim === "\\Vert" && rDelim === "\\Vert") envName = "Vmatrix"; else if ((lDelim === "{" || lDelim === "\\lbrace") && (rDelim === "." || rDelim === "?")) envName = "cases"; const array = makeEnvironment( envName, where.endsWith("column") ? [[firstCell, secondCell]] : [[firstCell], [secondCell]] ); parent.parent.addChildBefore(array, parent); parent.parent.removeChild(parent); if (isPlaceholderCell(array, 0, 0)) selectCell(model, array, 0, 0); else if (where.endsWith("column")) { if (isPlaceholderCell(array, 0, 1)) selectCell(model, array, 0, 1); else model.position = model.offsetOf(atom); } else { if (isPlaceholderCell(array, 1, 0)) selectCell(model, array, 1, 0); else model.position = model.offsetOf(atom); } return [void 0, [0, 0]]; } } return atom && atom.parent instanceof ArrayAtom ? [atom.parent, atom.parentBranch] : [void 0, [0, 0]]; } function isPlaceholderCell(array, row, column) { const cell = array.getCell(row, column); if (!cell || cell.length !== 2) return false; return cell[1].type === "placeholder"; } function cellRange(model, array, row, column) { const cell = array.getCell(row, column); if (!cell) return -1; return [model.offsetOf(cell[0]), model.offsetOf(cell[cell.length - 1])]; } function selectCell(model, array, row, column) { const range2 = cellRange(model, array, row, column); if (typeof range2 !== "number") model.setSelection(range2); } function setPositionInCell(model, array, row, column, pos) { const cell = array.getCell(row, column); if (!cell) return; model.setPositionHandlingPlaceholder( model.offsetOf(cell[pos === "start" ? 0 : cell.length - 1]) ); } function addCell(model, where) { const [arrayAtom, [row, column]] = parentArray(model, where); if (!arrayAtom) return; switch (where) { case "after row": arrayAtom.addRowAfter(row); setPositionInCell(model, arrayAtom, row + 1, 0, "end"); break; case "after column": if (arrayAtom.maxColumns <= arrayAtom.colCount) { model.announce("plonk"); return; } arrayAtom.addColumnAfter(column); setPositionInCell(model, arrayAtom, row, column + 1, "end"); break; case "before row": arrayAtom.addRowBefore(row); setPositionInCell(model, arrayAtom, row, 0, "start"); break; case "before column": if (arrayAtom.maxColumns <= arrayAtom.colCount) { model.announce("plonk"); return; } arrayAtom.addColumnBefore(column); setPositionInCell(model, arrayAtom, row, column, "start"); break; } } function addRowAfter(model) { if (!model.contentWillChange({ inputType: "insertText" })) return false; addCell(model, "after row"); model.contentDidChange({ inputType: "insertText" }); return true; } function addRowBefore(model) { if (!model.contentWillChange({ inputType: "insertText" })) return false; addCell(model, "before row"); model.contentDidChange({ inputType: "insertText" }); return true; } function addColumnAfter(model) { if (!model.contentWillChange({ inputType: "insertText" })) return false; addCell(model, "after column"); model.contentDidChange({ inputType: "insertText" }); return true; } function addColumnBefore(model) { if (!model.contentWillChange({ inputType: "insertText" })) return false; addCell(model, "before column"); model.contentDidChange({ inputType: "insertText" }); return true; } function setEnvironment(model, environment) { if (!model.contentWillChange({})) return false; model.mathfield.snapshot(); let leftDelim = "."; let rightDelim = "."; switch (environment) { case "pmatrix": case "pmatrix*": leftDelim = "("; rightDelim = ")"; break; case "bmatrix": case "bmatrix*": leftDelim = "["; rightDelim = "]"; break; case "Bmatrix": case "Bmatrix*": leftDelim = "\\lbrace"; rightDelim = "\\rbrace"; break; case "vmatrix": case "vmatrix*": leftDelim = "\\vert"; rightDelim = "\\vert"; break; case "Vmatrix": case "Vmatrix*": leftDelim = "\\Vert"; rightDelim = "\\Vert"; break; case "matrix": case "matrix*": leftDelim = "."; rightDelim = "."; break; case "cases": case "dcases": leftDelim = "\\lbrace"; break; case "rcases": rightDelim = "\\rbrace"; break; } const atom = model.at(model.position); const arrayAtom = atom.type === "array" ? atom : model.parentEnvironment; arrayAtom.environmentName = environment; arrayAtom.leftDelim = leftDelim; arrayAtom.rightDelim = rightDelim; model.contentDidChange({}); return true; } function removeCell(model, where) { let atom = model.at(model.position); while (atom && !(Array.isArray(atom.parentBranch) && atom.parent instanceof ArrayAtom)) atom = atom.parent; if (Array.isArray(atom == null ? void 0 : atom.parentBranch) && (atom == null ? void 0 : atom.parent) instanceof ArrayAtom) { const arrayAtom = atom.parent; const treeBranch = atom.parentBranch; let pos; switch (where) { case "row": if (arrayAtom.rowCount > 1) { arrayAtom.removeRow(treeBranch[0]); const cell = arrayAtom.getCell( Math.max(0, treeBranch[0] - 1), treeBranch[1] ); pos = model.offsetOf(cell[cell.length - 1]); } break; case "column": if (arrayAtom.colCount > arrayAtom.minColumns) { arrayAtom.removeColumn(treeBranch[1]); const cell = arrayAtom.getCell( treeBranch[0], Math.max(0, treeBranch[1] - 1) ); pos = model.offsetOf(cell[cell.length - 1]); } break; } if (pos) model.setPositionHandlingPlaceholder(pos); } } function removeRow(model) { if (!model.contentWillChange({ inputType: "deleteContent" })) return false; removeCell(model, "row"); model.contentDidChange({ inputType: "deleteContent" }); return true; } function removeColumn(model) { if (!model.contentWillChange({ inputType: "deleteContent" })) return false; removeCell(model, "column"); model.contentDidChange({ inputType: "deleteContent" }); return true; } register2( { addRowAfter, addColumnAfter, addRowBefore, addColumnBefore, removeRow, removeColumn, setEnvironment }, { target: "model", canUndo: true, changeContent: true, changeSelection: true } ); function placeholderCell() { return [new PlaceholderAtom()]; } // src/editor/undo.ts var _UndoManager = class _UndoManager { constructor(model) { this.recording = false; this.model = model; this.reset(); } reset() { this.stack = []; this.index = -1; this.lastOp = ""; } startRecording() { this.recording = true; } stopRecording() { this.recording = false; } canUndo() { return this.index - 1 >= 0; } canRedo() { return this.stack.length - 1 > this.index; } /** Call this to stop coalescing future ops, for example when the selection * changes */ stopCoalescing(selection) { if (selection && this.index >= 0) this.stack[this.index].selection = selection; this.lastOp = ""; } undo() { if (!this.canUndo()) return false; this.model.setState(this.stack[this.index - 1], { silenceNotifications: false, type: "undo" }); this.index -= 1; this.lastOp = ""; return true; } redo() { if (!this.canRedo()) return false; this.index += 1; this.model.setState(this.stack[this.index], { silenceNotifications: false, type: "redo" }); this.lastOp = ""; return true; } pop() { if (!this.canUndo()) return; this.stack.splice(this.index, this.stack.length - this.index); this.index -= 1; } /** * Push a snapshot of the content and selection of the mathfield onto the * undo stack so that it can potentially be reverted to later. * * **Return** `true` if the undo state changed */ snapshot(op) { if (!this.recording) return false; if (op && op === this.lastOp) this.pop(); this.stack.splice(this.index + 1, this.stack.length - this.index - 1); this.stack.push(this.model.getState()); this.index += 1; if (this.stack.length > _UndoManager.maximumDepth) { this.stack.shift(); this.index -= 1; } this.lastOp = op != null ? op : ""; return true; } }; // Maximum number of undo/redo states _UndoManager.maximumDepth = 1e3; var UndoManager = _UndoManager; // src/editor-model/commands.ts function wordBoundaryOffset(model, offset, direction) { if (model.at(offset).mode !== "text") return offset; const dir = direction === "backward" ? -1 : 1; let result; if (LETTER_AND_DIGITS.test(model.at(offset).value)) { let i = offset; let match; do { match = model.at(i).mode === "text" && LETTER_AND_DIGITS.test(model.at(i).value); i += dir; } while (model.at(i) && match); result = model.at(i) ? i - 2 * dir : i - dir; } else if (/\s/.test(model.at(offset).value)) { let i = offset; while (model.at(i) && model.at(i).mode === "text" && /\s/.test(model.at(i).value)) i += dir; if (!model.at(i)) { result = i - dir; } else { let match = true; do { match = model.at(i).mode === "text" && !/\s/.test(model.at(i).value); i += dir; } while (model.at(i) && match); result = model.at(i) ? i - 2 * dir : i - dir; } } else { let i = offset; while (model.at(i) && model.at(i).mode === "text" && !/\s/.test(model.at(i).value)) i += dir; result = model.at(i) ? i : i - dir; let match = true; while (model.at(i) && match) { match = model.at(i).mode === "text" && /\s/.test(model.at(i).value); if (match) result = i; i += dir; } result = model.at(i) ? i - 2 * dir : i - dir; } return result - (dir > 0 ? 0 : 1); } function skip(model, direction, options) { var _a3, _b3, _c2, _d2, _e, _f, _g; const previousPosition = model.position; if (!((_a3 = options == null ? void 0 : options.extend) != null ? _a3 : false)) model.collapseSelection(direction); let atom = model.at(model.position); if (direction === "forward") { if (atom.type === "subsup") { atom = atom.rightSibling; if (!atom) atom = model.at(model.position + 1); } else atom = model.at(model.position + 1); } if (!atom) { model.announce("plonk"); return false; } let offset = model.offsetOf(atom); if (atom instanceof TextAtom) { offset = wordBoundaryOffset(model, offset, direction); } else if (atom instanceof LatexAtom) { if (atom.isSuggestion) { console.assert(direction === "forward"); while (atom && atom instanceof LatexAtom) { atom.isSuggestion = false; offset = model.offsetOf(atom); atom = atom.rightSibling; } } else if (direction === "forward") { atom = atom.rightSibling; if (!atom || !(atom instanceof LatexAtom)) { model.announce("plonk"); return false; } while (atom && atom instanceof LatexAtom && /[a-zA-Z\*]/.test(atom.value)) { offset = model.offsetOf(atom); atom = atom.rightSibling; } } else { atom = atom.leftSibling; if (!atom || !(atom instanceof LatexAtom)) { model.announce("plonk"); return false; } while (atom && atom instanceof LatexAtom && /[a-zA-Z\*]/.test(atom.value)) { offset = model.offsetOf(atom); atom = atom.leftSibling; } } } else if (direction === "forward" && atom.type === "mopen") { let level = 0; do { if (atom.type === "mopen") level += 1; else if (atom.type === "mclose") level -= 1; atom = atom.rightSibling; } while (!atom.isLastSibling && level !== 0); offset = model.offsetOf(atom.leftSibling); } else if (direction === "backward" && atom.type === "mclose") { let level = 0; do { if (atom.type === "mopen") level += 1; else if (atom.type === "mclose") level -= 1; atom = atom.leftSibling; } while (!atom.isFirstSibling && level !== 0); offset = model.offsetOf(atom); } else if (direction === "backward") { if (atom.type === "first") { while (offset > 0 && atom.type === "first") { offset -= 1; atom = model.at(offset); } } else { const type = atom.type; if (atom.type === "subsup") { offset = model.offsetOf(model.at(offset).leftSibling); } offset -= 1; let nextType = (_b3 = model.at(offset)) == null ? void 0 : _b3.type; while (offset >= 0 && nextType === type) { if (((_c2 = model.at(offset)) == null ? void 0 : _c2.type) === "subsup") offset = model.offsetOf(model.at(offset).leftSibling); else offset -= 1; nextType = model.at(offset).type; } } } else { const { type } = atom; let nextType = (_d2 = model.at(offset)) == null ? void 0 : _d2.type; const { lastOffset } = model; while (offset <= lastOffset && (nextType === type || nextType === "subsup")) { while (((_e = model.at(offset).rightSibling) == null ? void 0 : _e.type) === "subsup") offset = model.offsetOf(model.at(offset).rightSibling); offset += 1; nextType = (_f = model.at(offset)) == null ? void 0 : _f.type; } offset -= 1; } if ((_g = options == null ? void 0 : options.extend) != null ? _g : false) { if (!model.setSelection(model.anchor, offset)) { model.announce("plonk"); return false; } } else { if (offset === model.position) { model.announce("plonk"); return false; } model.position = offset; } model.announce("move", previousPosition); model.mathfield.stopCoalescingUndo(); return true; } function move(model, direction, options) { var _a3, _b3; options = options != null ? options : { extend: false }; model.mathfield.adoptStyle = direction === "backward" ? "right" : "left"; if (direction !== "forward") { const [from, to] = getCommandSuggestionRange(model); if (from !== void 0 && to !== void 0) model.deleteAtoms([from, to]); } if (direction === "upward") return moveUpward(model, options); if (direction === "downward") return moveDownward(model, options); if (options.extend) { let pos2 = nextValidPosition(model, model.position, direction); if (pos2 < 0) pos2 = 0; if (pos2 > model.lastOffset) pos2 = model.lastOffset; const result = model.setSelection(model.anchor, pos2); model.mathfield.stopCoalescingUndo(); return result; } if (model.selectionIsPlaceholder) { model.collapseSelection(direction); const result = move(model, direction); model.mathfield.stopCoalescingUndo(); return result; } let pos = model.position; const previousPosition = pos; if (model.collapseSelection(direction)) { pos = model.position; if (!isValidPosition(model, pos)) pos = nextValidPosition(model, pos, direction); } else pos = nextValidPosition(model, pos, direction); if (pos < 0 || pos > model.lastOffset) { let result = true; if (!model.silenceNotifications) { result = (_b3 = (_a3 = model.mathfield.host) == null ? void 0 : _a3.dispatchEvent( new CustomEvent("move-out", { detail: { direction }, cancelable: true, bubbles: true, composed: true }) )) != null ? _b3 : true; } if (result) model.announce("plonk"); return result; } model.setPositionHandlingPlaceholder(pos); model.mathfield.stopCoalescingUndo(); model.announce("move", previousPosition); return true; } function nextValidPosition(model, pos, direction) { pos = pos + (direction === "forward" ? 1 : -1); if (pos < 0 || pos > model.lastOffset) return pos; if (!isValidPosition(model, pos)) return nextValidPosition(model, pos, direction); return pos; } function isValidPosition(model, pos) { var _a3; const atom = model.at(pos); let parent = atom.parent; while (parent && !parent.inCaptureSelection) parent = parent.parent; if (parent == null ? void 0 : parent.inCaptureSelection) return false; if ((_a3 = atom.parent) == null ? void 0 : _a3.skipBoundary) { if (!atom.isFirstSibling && atom.isLastSibling) return false; if (atom.type === "first") return false; } if (model.mathfield.hasEditablePrompts && !atom.parentPrompt) return false; return true; } function getClosestAtomToXPosition(mathfield, search, x) { let prevX = Infinity; let i = 0; for (; i < search.length; i++) { const toX = getLocalDOMRect(mathfield.getHTMLElement(search[i])).right; const abs = Math.abs(x - toX); if (abs <= prevX) { prevX = abs; } else { break; } } return search[i - 1]; } function moveToClosestAtomVertically(model, fromAtom, toAtoms, extend, direction) { const hasEditablePrompts = model.mathfield.hasEditablePrompts; const editableAtoms = !hasEditablePrompts ? toAtoms : toAtoms.filter((a) => a.type === "prompt" && !a.captureSelection); const fromX = getLocalDOMRect(model.mathfield.getHTMLElement(fromAtom)).right; const targetSelection = model.offsetOf( getClosestAtomToXPosition(model.mathfield, editableAtoms, fromX) ) - (hasEditablePrompts ? 1 : 0); if (extend) { const [left, right] = model.selection.ranges[0]; let newSelection; const cmp = direction === "up" ? left : right; if (targetSelection < cmp) { newSelection = { ranges: [[targetSelection, right]], direction: "backward" }; } else { newSelection = { ranges: [[left, targetSelection]], direction: "forward" }; } model.setSelection(newSelection); } else { model.setPositionHandlingPlaceholder(targetSelection); } model.announce(`move ${direction}`); } function moveUpward(model, options) { var _a3, _b3; const extend = (_a3 = options == null ? void 0 : options.extend) != null ? _a3 : false; if (!extend) model.collapseSelection("backward"); const handleDeadEnd = () => { var _a4, _b4; let result = true; if (!model.silenceNotifications) { result = (_b4 = (_a4 = model.mathfield.host) == null ? void 0 : _a4.dispatchEvent( new CustomEvent("move-out", { detail: { direction: "upward" }, cancelable: true, bubbles: true, composed: true }) )) != null ? _b4 : true; } model.announce(result ? "plonk" : "line"); return result; }; const baseAtom = model.at(model.position); let atom = baseAtom; while (atom && atom.parentBranch !== "below" && !(Array.isArray(atom.parentBranch) && atom.parent instanceof ArrayAtom)) atom = atom.parent; if (Array.isArray(atom == null ? void 0 : atom.parentBranch) && atom.parent instanceof ArrayAtom) { const arrayAtom = atom.parent; if (atom.parentBranch[0] < 1) return handleDeadEnd(); const rowAbove = atom.parentBranch[0] - 1; const aboveCell = arrayAtom.array[rowAbove][atom.parentBranch[1]]; const cellHasPrompt = aboveCell.some( (a) => a.type === "prompt" && !a.captureSelection ); if (!cellHasPrompt && model.mathfield.hasEditablePrompts) return handleDeadEnd(); moveToClosestAtomVertically(model, baseAtom, aboveCell, extend, "up"); } else if (atom) { const branch = (_b3 = atom.parent.branch("above")) != null ? _b3 : atom.parent.createBranch("above"); const branchHasPrompt = branch.some( (a) => a.type === "prompt" && a.placeholderId ); if (!branchHasPrompt && model.mathfield.hasEditablePrompts) return handleDeadEnd(); moveToClosestAtomVertically(model, baseAtom, branch, extend, "up"); } else return handleDeadEnd(); model.mathfield.stopCoalescingUndo(); return true; } function moveDownward(model, options) { var _a3, _b3; const extend = (_a3 = options == null ? void 0 : options.extend) != null ? _a3 : false; if (!extend) model.collapseSelection("forward"); const handleDeadEnd = () => { var _a4, _b4; let result = true; if (!model.silenceNotifications) { result = (_b4 = (_a4 = model.mathfield.host) == null ? void 0 : _a4.dispatchEvent( new CustomEvent("move-out", { detail: { direction: "downward" }, cancelable: true, bubbles: true, composed: true }) )) != null ? _b4 : true; } model.announce(result ? "plonk" : "line"); return result; }; const baseAtom = model.at(model.position); let atom = baseAtom; while (atom && atom.parentBranch !== "above" && !(Array.isArray(atom.parentBranch) && atom.parent instanceof ArrayAtom)) atom = atom.parent; if (Array.isArray(atom == null ? void 0 : atom.parentBranch) && atom.parent instanceof ArrayAtom) { const arrayAtom = atom.parent; if (atom.parentBranch[0] + 1 > arrayAtom.array.length - 1) return handleDeadEnd(); const rowBelow = atom.parentBranch[0] + 1; const belowCell = arrayAtom.array[rowBelow][atom.parentBranch[1]]; const cellHasPrompt = belowCell.some( (a) => a.type === "prompt" && !a.captureSelection ); if (!cellHasPrompt && model.mathfield.hasEditablePrompts) return handleDeadEnd(); moveToClosestAtomVertically(model, baseAtom, belowCell, extend, "down"); } else if (atom) { const branch = (_b3 = atom.parent.branch("below")) != null ? _b3 : atom.parent.createBranch("below"); const branchHasPrompt = branch.some((a) => a.type === "prompt"); if (!branchHasPrompt && model.mathfield.hasEditablePrompts) return handleDeadEnd(); moveToClosestAtomVertically(model, baseAtom, branch, extend, "down"); } else return handleDeadEnd(); return true; } // src/editor-model/commands-move.ts function moveAfterParent(model) { const previousPosition = model.position; const parent = model.at(previousPosition).parent; if (!(parent == null ? void 0 : parent.parent)) { model.announce("plonk"); return false; } model.position = model.offsetOf(parent); model.mathfield.stopCoalescingUndo(); model.announce("move", previousPosition); return true; } function superscriptDepth(model) { let result = 0; let atom = model.at(model.position); let wasSuperscript = false; while (atom) { if (!atom.hasEmptyBranch("superscript") || !atom.hasEmptyBranch("subscript")) result += 1; if (!atom.hasEmptyBranch("superscript")) wasSuperscript = true; else if (!atom.hasEmptyBranch("subscript")) wasSuperscript = false; atom = atom.parent; } return wasSuperscript ? result : 0; } function subscriptDepth(model) { let result = 0; let atom = model.at(model.position); let wasSubscript = false; while (atom) { if (!atom.hasEmptyBranch("superscript") || !atom.hasEmptyBranch("subscript")) result += 1; if (!atom.hasEmptyBranch("superscript")) wasSubscript = false; else if (!atom.hasEmptyBranch("subscript")) wasSubscript = true; atom = atom.parent; } return wasSubscript ? result : 0; } function moveToSuperscript(model) { var _a3; model.collapseSelection(); if (superscriptDepth(model) >= model.mathfield.options.scriptDepth[1]) { model.announce("plonk"); return false; } let target = model.at(model.position); if (target.subsupPlacement === void 0) { if (((_a3 = target.rightSibling) == null ? void 0 : _a3.type) !== "subsup") { target.parent.addChildAfter( new SubsupAtom({ style: target.computedStyle }), target ); } target = target.rightSibling; } target.createBranch("superscript"); model.setSelection( model.getSiblingsRange(model.offsetOf(target.superscript[0])) ); return true; } function moveToSubscript(model) { var _a3; model.collapseSelection(); if (subscriptDepth(model) >= model.mathfield.options.scriptDepth[0]) { model.announce("plonk"); return false; } let target = model.at(model.position); if (target.subsupPlacement === void 0) { if (((_a3 = model.at(model.position + 1)) == null ? void 0 : _a3.type) !== "subsup") { target.parent.addChildAfter( new SubsupAtom({ style: model.at(model.position).computedStyle }), target ); } target = model.at(model.position + 1); } target.createBranch("subscript"); model.setSelection( model.getSiblingsRange(model.offsetOf(target.subscript[0])) ); return true; } function getTabbableElements() { function tabbable(element) { const regularTabbables = []; const orderedTabbables = []; const candidates = [ ...element.querySelectorAll(`input, select, textarea, a[href], button, [tabindex], audio[controls], video[controls], [contenteditable]:not([contenteditable="false"]), details>summary`) ].filter(isNodeMatchingSelectorTabbable); candidates.forEach((candidate, i) => { const candidateTabindex = getTabindex(candidate); if (candidateTabindex === 0) regularTabbables.push(candidate); else { orderedTabbables.push({ documentOrder: i, tabIndex: candidateTabindex, node: candidate }); } }); return orderedTabbables.sort( (a, b) => a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex ).map((a) => a.node).concat(regularTabbables); } function isNodeMatchingSelectorTabbable(element) { if (!isNodeMatchingSelectorFocusable(element) || isNonTabbableRadio(element) || getTabindex(element) < 0) return false; return true; } function isNodeMatchingSelectorFocusable(node) { if (node.disabled || node.type === "hidden" && node.tagName.toUpperCase() === "INPUT" || isHidden(node)) return false; return true; } function getTabindex(node) { var _a3; const tabindexAttr = Number.parseInt( (_a3 = node.getAttribute("tabindex")) != null ? _a3 : "NaN", 10 ); if (!Number.isNaN(tabindexAttr)) return tabindexAttr; if (node.contentEditable === "true") return 0; if ((node.nodeName === "AUDIO" || node.nodeName === "VIDEO") && node.getAttribute("tabindex") === null) return 0; return node.tabIndex; } function isNonTabbableRadio(node) { return node.tagName.toUpperCase() === "INPUT" && node.type === "radio" && !isTabbableRadio(node); } function getCheckedRadio(nodes, form) { for (const node of nodes) if (node.checked && node.form === form) return node; return null; } function isTabbableRadio(node) { var _a3; if (!node.name) return true; const radioScope = (_a3 = node.form) != null ? _a3 : node.ownerDocument; const radioSet = radioScope.querySelectorAll( 'input[type="radio"][name="' + node.name + '"]' ); const checked = getCheckedRadio(radioSet, node.form); return !checked || checked === node; } function isHidden(element) { if (!isBrowser() || element === document.activeElement || element.contains(document.activeElement)) return false; if (getComputedStyle(element).visibility === "hidden") return true; const bounds = element.getBoundingClientRect(); if (bounds.width === 0 || bounds.height === 0) return true; while (element) { if (getComputedStyle(element).display === "none") return true; element = element.parentElement; } return false; } if (!isBrowser()) return []; return tabbable(document.body); } function select(model, target, direction = "forward") { const previousPosition = model.position; if (Array.isArray(target)) { const first = model.offsetOf(target[0]); const last = model.offsetOf(target[target.length - 1]); if (direction === "forward") model.setSelection(first, last); else model.setSelection(last, first); model.announce("move", previousPosition); model.mathfield.stopCoalescingUndo(); return true; } if (direction === "forward") return select(model, [target.leftSibling, target]); return select(model, [target, target.leftSibling]); } function leapTo(model, target) { const previousPosition = model.position; if (typeof target === "number") target = model.at(target); if (target.type === "prompt") { model.setSelection( model.offsetOf(target.firstChild), model.offsetOf(target.lastChild) ); } else { const newPosition = model.offsetOf(target); if (target.type === "placeholder") model.setSelection(newPosition - 1, newPosition); else model.position = newPosition; } model.announce("move", previousPosition); model.mathfield.stopCoalescingUndo(); return true; } function leap(model, dir, callHooks = true) { var _a3, _b3; const dist = dir === "forward" ? 1 : -1; if (model.at(model.anchor).type === "placeholder") move(model, dir); let origin; const parentPrompt = model.at(model.anchor).parentPrompt; if (parentPrompt) { if (dir === "forward") origin = model.offsetOf(parentPrompt) + 1; else origin = model.offsetOf(parentPrompt.leftSibling); } else origin = Math.max(model.position + dist, 0); const target = leapTarget(model, origin, dir); if (!target || dir === "forward" && model.offsetOf(target) < origin || dir === "backward" && model.offsetOf(target) > origin) { const handled = !callHooks || !((_b3 = (_a3 = model.mathfield.host) == null ? void 0 : _a3.dispatchEvent( new CustomEvent("move-out", { detail: { direction: dir }, cancelable: true, bubbles: true, composed: true }) )) != null ? _b3 : true); if (handled) { model.announce("plonk"); return false; } const tabbable = getTabbableElements(); if (!document.activeElement || tabbable.length <= 1) { model.announce("plonk"); return false; } let index = tabbable.indexOf(document.activeElement) + dist; if (index < 0) index = tabbable.length - 1; if (index >= tabbable.length) index = 0; tabbable[index].focus(); model.mathfield.stopCoalescingUndo(); return true; } leapTo(model, target); return true; } function leapTarget(model, origin = 0, dir = "forward") { return model.findAtom( (atom) => atom.type === "placeholder" || atom.type === "prompt" || !model.mathfield.readOnly && atom.treeDepth > 2 && atom.isFirstSibling && atom.isLastSibling, origin, dir ); } register2( { moveToOpposite: (model) => { const OPPOSITE_RELATIONS = { superscript: "subscript", subscript: "superscript", above: "below", below: "above" }; const cursor = model.at(model.position); const { parent } = cursor; if (!parent) { model.announce("plonk"); return false; } const relation = cursor.parentBranch; let oppositeRelation; if (typeof relation === "string") oppositeRelation = OPPOSITE_RELATIONS[relation]; if (!oppositeRelation) { const result2 = cursor.subsupPlacement ? moveToSubscript(model) : moveToSuperscript(model); model.mathfield.stopCoalescingUndo(); return result2; } if (!parent.branch(oppositeRelation)) { parent.createBranch(oppositeRelation); } const result = model.setSelection( model.getBranchRange(model.offsetOf(parent), oppositeRelation) ); model.mathfield.stopCoalescingUndo(); return result; }, moveBeforeParent: (model) => { const { parent } = model.at(model.position); if (!parent) { model.announce("plonk"); return false; } model.position = model.offsetOf(parent); model.mathfield.stopCoalescingUndo(); return true; }, moveAfterParent: (model) => moveAfterParent(model), moveToNextChar: (model) => move(model, "forward"), moveToPreviousChar: (model) => move(model, "backward"), moveUp: (model) => move(model, "upward"), moveDown: (model) => move(model, "downward"), moveToNextWord: (model) => skip(model, "forward"), moveToPreviousWord: (model) => skip(model, "backward"), moveToGroupStart: (model) => { const pos = model.offsetOf(model.at(model.position).firstSibling); if (pos === model.position) { model.announce("plonk"); return false; } model.position = pos; model.mathfield.stopCoalescingUndo(); return true; }, moveToGroupEnd: (model) => { const pos = model.offsetOf(model.at(model.position).lastSibling); if (pos === model.position) { model.announce("plonk"); return false; } model.position = pos; model.mathfield.stopCoalescingUndo(); return true; }, moveToNextGroup: (model) => { var _a3, _b3, _c2, _d2; if (model.position === model.lastOffset && model.anchor === model.lastOffset) return leap(model, "forward"); const atom = model.at(model.position); const mode = atom.mode; if (mode === "text") { if (model.selectionIsCollapsed) { let first = atom; while (first && first.mode === "text") first = first.leftSibling; let last = atom; while (((_a3 = last.rightSibling) == null ? void 0 : _a3.mode) === "text") last = last.rightSibling; if (first && last) return select(model, [first, last]); } if (atom.rightSibling.mode === "text") { let next = atom; while (next && next.mode === "text") next = next.rightSibling; if (next) { leapTo(model, (_b3 = next.leftSibling) != null ? _b3 : next); model.mathfield.switchMode("math"); return true; } return leapTo(model, model.lastOffset); } } const parentPrompt = model.at(model.anchor).parentPrompt; const origin = parentPrompt ? model.offsetOf(parentPrompt) + 1 : Math.max(model.position + 1, 0); const target = leapTarget(model, origin, "forward"); if (target) return leapTo(model, target); const sibling = findSibling( model, atom, (x) => x.type === "leftright" || x.type === "text", "forward" ); if (sibling) { if (sibling.mode === "text") { let last = sibling; while (last && last.mode === "text") last = last.rightSibling; return select(model, [ (_c2 = sibling.leftSibling) != null ? _c2 : sibling, (_d2 = last.leftSibling) != null ? _d2 : last ]); } return select(model, sibling); } const parent = atom.parent; if (parent) { if (parent.type === "leftright" || parent.type === "surd") return select(model, parent); if (atom.parentBranch === "superscript" && parent.subscript) return select(model, parent.subscript); if (atom.parentBranch === "above" && parent.below) return select(model, parent.below); if (atom.parentBranch === "superscript" || atom.parentBranch === "subscript") return leapTo(model, parent); if (atom.parentBranch === "above" || atom.parentBranch === "below") return select(model, parent); } return leapTo(model, model.lastOffset); }, moveToPreviousGroup: (model) => { var _a3; if (model.position === 0 && model.anchor === 0) return leap(model, "backward"); let atom = model.at(model.position); const mode = atom.mode; if (mode === "text") { if (model.selectionIsCollapsed) { let first = atom; while (first && first.mode === "text") first = first.leftSibling; let last = atom; while (((_a3 = last.rightSibling) == null ? void 0 : _a3.mode) === "text") last = last.rightSibling; if (first && last) return select(model, [first, last]); } while (atom && atom.mode === "text") atom = atom.leftSibling; if (atom) return leapTo(model, atom); return leapTo(model, 0); } const parentPrompt = model.at(model.anchor).parentPrompt; const origin = parentPrompt ? model.offsetOf(parentPrompt.leftSibling) : Math.max(model.position - 1, 0); const target = leapTarget(model, origin, "backward"); if (target) return leapTo(model, target); if (mode === "math") { const sibling = findSibling( model, atom, (x) => x.type === "leftright" || x.type === "text", "backward" ); if (sibling) { if (sibling.mode === "text") { let first = sibling; while (first && first.mode === "text") first = first.leftSibling; return select(model, [sibling, first]); } return select(model, sibling); } const parent = atom.parent; if (parent) { if (parent.type === "leftright" || parent.type === "surd") return select(model, parent); if (atom.parentBranch === "subscript" && parent.superscript) return select(model, parent.superscript); if (atom.parentBranch === "below" && parent.above) return select(model, parent.above); if (atom.parentBranch === "superscript" || atom.parentBranch === "subscript") return leapTo(model, parent); if (atom.parentBranch === "above" || atom.parentBranch === "below") return select(model, parent); } return leapTo(model, 0); } return false; }, moveToMathfieldStart: (model) => { if (model.selectionIsCollapsed && model.position === 0) { model.announce("plonk"); return false; } model.position = 0; model.mathfield.stopCoalescingUndo(); return true; }, moveToMathfieldEnd: (model) => { if (model.selectionIsCollapsed && model.position === model.lastOffset) { model.announce("plonk"); return false; } model.position = model.lastOffset; model.mathfield.stopCoalescingUndo(); return true; }, moveToSuperscript, moveToSubscript }, { target: "model", changeSelection: true } ); register2( { moveToNextPlaceholder: (model) => leap(model, "forward"), moveToPreviousPlaceholder: (model) => leap(model, "backward") }, { target: "model", changeSelection: true, audioFeedback: "return" } ); function findSibling(model, atom, pred, dir) { if (dir === "forward") { let result2 = atom.rightSibling; while (result2 && !pred(result2)) result2 = result2.rightSibling; return result2; } let result = atom.leftSibling; while (result && !pred(result)) result = result.leftSibling; return result; } // src/editor-mathfield/smartmode.ts function convertLastAtomsToText(model, count, until) { if (typeof count === "function") { until = count; count = Infinity; } if (count === void 0) count = Infinity; let i = model.position; let done = false; let text = ""; while (!done) { const atom = model.at(i); done = count === 0 || atom === void 0 || atom.type === "first" || atom.mode !== "math" || !(atom.type && /mord|mpunct|operator/.test(atom.type) || atom.type === "mop" && /[a-zA-Z ]+/.test(atom.value)) || !atom.hasEmptyBranch("superscript") || !atom.hasEmptyBranch("subscript") || typeof until === "function" && !until(atom); if (!done) { atom.mode = "text"; atom.command = atom.value; atom.verbatimLatex = void 0; text += atom.value; } i -= 1; count -= 1; } model.contentDidChange({ data: text, inputType: "insertText" }); } function convertLastAtomsToMath(model, count, until) { if (typeof count === "function") { until = count; count = Infinity; } if (count === void 0) count = Infinity; let i = model.position; let done = false; const data = []; while (!done) { const atom = model.at(i); done = count === 0 || !atom || atom.type === "first" || atom.isFirstSibling || atom.mode !== "text" || atom.value === " " || typeof until === "function" && !until(atom); if (!done) { data.push(Atom.serialize([atom], { defaultMode: "math" })); atom.mode = "math"; } i -= 1; count -= 1; } removeIsolatedSpace(model); model.contentDidChange({ data: joinLatex(data), inputType: "insertText" }); } function removeIsolatedSpace(model) { var _a3; let i = model.position - 1; while (i >= 0 && ((_a3 = model.at(i)) == null ? void 0 : _a3.mode) === "math") i -= 1; if (i < 0) return; if (model.at(i).mode === "text" && model.at(i).value === " " && model.at(i - 1).mode === "math") { model.at(i - 1).parent.removeChild(model.at(i - 1)); const save = model.silenceNotifications; model.silenceNotifications = true; model.position -= 1; model.silenceNotifications = save; model.contentDidChange({ inputType: "deleteContent" }); } } function getTextBeforePosition(model) { let result = ""; let i = model.position; let done = false; while (!done) { const atom = model.at(i); done = !(atom && (atom.mode === "text" || atom.mode === "math" && atom.type && /mord|mpunct/.test(atom.type))); if (!done) result = atom.value + result; i -= 1; } return result; } function smartMode(mathfield, keystroke, evt) { const { model } = mathfield; if (model.mode === "latex") return false; if (!model.at(model.position).isLastSibling) return false; if (!evt || !mightProducePrintableCharacter(evt)) return false; const c = keyboardEventToChar(evt); if (!model.selectionIsCollapsed) { if (mathfield.model.mode === "text") { if (/[/_^]/.test(c)) return true; } return false; } const context = getTextBeforePosition(model) + c; if (mathfield.model.mode === "text") { if (keystroke === "Esc" || /[/\\]/.test(c)) { return true; } if (/[\^_]/.test(c)) { if (/(^|\s)[a-zA-Z][^_]$/.test(context)) { convertLastAtomsToMath(model, 1); } return true; } const lFence = { ")": "(", "}": "{", "]": "[" }[c]; const { parent } = model.at(model.position); if (lFence && parent instanceof LeftRightAtom && parent.leftDelim === lFence) return true; if (/(^|[^a-zA-Z])(a|I) $/.test(context)) { return false; } if (/[$€£₤₺¥¤฿¢₡₧₨₹₩₱]/u.test(c)) { return true; } if (/(^|[^a-zA-Z'’])[a-zA-Z] $/.test(context)) { convertLastAtomsToMath(model, 1); return false; } if (/\D\.[^\d\s]$/.test(context)) { convertLastAtomsToMath(model, 1); const atom = model.at(model.position); atom.value = "\u22C5"; atom.style.variant = "normal"; atom.command = "\\cdot"; atom.verbatimLatex = void 0; model.contentDidChange({ data: "\\cdot", inputType: "insertText" }); return true; } if (/(^|\s)[a-zA-Z][^a-zA-Z]$/.test(context)) { convertLastAtomsToMath(model, 1); return true; } if (/\.\d$/.test(context)) { convertLastAtomsToMath(model, 1); return true; } if (/\([\d+\-.]$/.test(context)) { convertLastAtomsToMath(model, 1); return true; } if (/\([a-z][,;]$/.test(context)) { convertLastAtomsToMath(model, 2); return true; } if (/[\d+\-=><*|]$/.test(c)) { removeIsolatedSpace(model); return true; } } else { if (keystroke === "[Space]") { convertLastAtomsToText( model, void 0, (a) => /[a-z][:,;.]$/.test(a.value) ); return true; } if (/[a-zA-Z]{3,}$/.test(context) && !/(dxd|abc|xyz|uvw)$/.test(context)) { convertLastAtomsToText(model, void 0, (a) => /[a-zA-Z]/.test(a.value)); return true; } if (/(^|\W)(if)$/i.test(context)) { convertLastAtomsToText(model, 1); return true; } if (/(\u0393|\u0394|\u0398|\u039B|\u039E|\u03A0|\u03A3|\u03A5|\u03A6|\u03A8|\u03A9|[\u03B1-\u03C9]|\u03D1|\u03D5|\u03D6|\u03F1|\u03F5){3,}$/u.test( context ) && !/(αβγ)$/.test(context)) { convertLastAtomsToText( model, void 0, (a) => /(:|,|;|.|\u0393|\u0394|\u0398|\u039B|\u039E|\u03A0|\u03A3|\u03A5|\u03A6|\u03A8|\u03A9|[\u03B1-\u03C9]|\u03D1|\u03D5|\u03D6|\u03F1|\u03F5)/u.test( a.value ) ); return true; } if (c === "?") { return true; } if (c === "." && !/[\d-+]\.$/.test(context)) { return true; } } return false; } // src/editor-mathfield/keystroke-caption.ts function showKeystroke(mathfield, keystroke) { if (!mathfield.isSelectionEditable || !mathfield.keystrokeCaptionVisible) return; const vb = createKeystrokeCaption(); const bounds = mathfield.element.getBoundingClientRect(); vb.style.left = `${bounds.left}px`; vb.style.top = `${bounds.top - 64}px`; vb.innerHTML = window.MathfieldElement.createHTML( "" + (getKeybindingMarkup(keystroke) || keystroke) + "" + vb.innerHTML ); vb.style.visibility = "visible"; setTimeout(() => { if (vb.childNodes.length > 0) vb.childNodes[vb.childNodes.length - 1].remove(); if (vb.childNodes.length === 0) vb.style.visibility = "hidden"; }, 3e3); } function toggleKeystrokeCaption(mathfield) { mathfield.keystrokeCaptionVisible = !mathfield.keystrokeCaptionVisible; if (!mathfield.keystrokeCaptionVisible) { const panel = getSharedElement("mathlive-keystroke-caption-panel"); panel.style.visibility = "hidden"; } else { const panel = createKeystrokeCaption(); panel.innerHTML = ""; } return false; } function createKeystrokeCaption() { const panel = document.getElementById("mathlive-keystroke-caption-panel"); if (panel) return panel; injectStylesheet("keystroke-caption"); injectStylesheet("core"); return getSharedElement("mathlive-keystroke-caption-panel"); } function disposeKeystrokeCaption() { if (!document.getElementById("mathlive-keystroke-caption-panel")) return; releaseSharedElement("mathlive-keystroke-caption-panel"); releaseStylesheet("core"); releaseStylesheet("keystroke-caption"); } // src/editor-mathfield/keyboard-input.ts function onKeystroke(mathfield, evt) { var _a3, _b3, _c2; const { model } = mathfield; const keystroke = keyboardEventToString(evt); if (evt.isTrusted) { validateKeyboardLayout(evt); const activeLayout = getActiveKeyboardLayout(); if (mathfield.keyboardLayout !== activeLayout.id) { mathfield.keyboardLayout = activeLayout.id; mathfield._keybindings = void 0; } } clearTimeout(mathfield.inlineShortcutBufferFlushTimer); mathfield.inlineShortcutBufferFlushTimer = 0; showKeystroke(mathfield, keystroke); if (evt.isTrusted && evt.defaultPrevented) { mathfield.flushInlineShortcutBuffer(); return false; } let shortcut; let selector = ""; let stateIndex; const buffer = mathfield.inlineShortcutBuffer; if (mathfield.isSelectionEditable) { if (model.mode === "math") { if (keystroke === "[Backspace]") buffer.pop(); else if (!mightProducePrintableCharacter(evt)) { mathfield.flushInlineShortcutBuffer(); } else { const c = keyboardEventToChar(evt); const keystrokes = [ ...(_b3 = (_a3 = buffer[buffer.length - 1]) == null ? void 0 : _a3.keystrokes) != null ? _b3 : [], c ]; buffer.push({ state: model.getState(), keystrokes, leftSiblings: getLeftSiblings(mathfield) }); let i = 0; let candidate = ""; while (!shortcut && i < keystrokes.length) { stateIndex = buffer.length - (keystrokes.length - i); candidate = keystrokes.slice(i).join(""); shortcut = getInlineShortcut( buffer[stateIndex].leftSiblings, candidate, mathfield.options.inlineShortcuts ); if (!shortcut && /^[a-zA-Z][a-zA-Z0-9]+?([_\^][a-zA-Z0-9\*\+\-]+?)?$/.test(candidate)) shortcut = mathfield.options.onInlineShortcut(mathfield, candidate); i += 1; } mathfield.flushInlineShortcutBuffer({ defer: true }); } } if (mathfield.options.smartMode) { if (shortcut) { mathfield.switchMode("math"); } else if (smartMode(mathfield, keystroke, evt)) { mathfield.switchMode({ math: "text", text: "math" }[model.mode]); selector = ""; } } } if (!shortcut) { if (!selector) { selector = getCommandForKeybinding( mathfield.keybindings, model.mode, evt ); } if (!selector && (keystroke === "[Enter]" || keystroke === "[Return]")) { let result = false; if (model.contentWillChange({ inputType: "insertLineBreak" })) { if (mathfield.host) { result = !mathfield.host.dispatchEvent( new Event("change", { bubbles: true, composed: true }) ); } if (!result) { if (evt.preventDefault) { evt.preventDefault(); evt.stopPropagation(); } } model.contentDidChange({ inputType: "insertLineBreak" }); } return result; } if ((!selector || keystroke === "[Space]") && model.mode === "math") { if (keystroke === "[Space]") { mathfield.adoptStyle = "none"; mathfield.flushInlineShortcutBuffer(); if (mathfield.options.mathModeSpace) { ModeEditor.insert(model, mathfield.options.mathModeSpace, { format: "latex", mode: "math" }); mathfield.snapshot("insert-space"); selector = ""; mathfield.dirty = true; mathfield.scrollIntoView(); if (evt.preventDefault) { evt.preventDefault(); evt.stopPropagation(); } return false; } const nextSibling = model.at(model.position + 1); const previousSibling = model.at(model.position - 1); if ((nextSibling == null ? void 0 : nextSibling.mode) === "text" || (previousSibling == null ? void 0 : previousSibling.mode) === "text") { ModeEditor.insert(model, " ", { mode: "text" }); mathfield.snapshot("insert-space"); mathfield.dirty = true; mathfield.scrollIntoView(); return false; } } if (((_c2 = model.at(model.position)) == null ? void 0 : _c2.isDigit()) && window.MathfieldElement.decimalSeparator === "," && keyboardEventToChar(evt) === ",") selector = "insertDecimalSeparator"; } } if (!shortcut && !selector) { if (!model.mathfield.smartFence) { const { parent: parent2 } = model.at(model.position); if (parent2 instanceof LeftRightAtom && parent2.rightDelim === "?" && model.at(model.position).isLastSibling && /^[)}\]|]$/.test(keystroke)) { mathfield.snapshot(); parent2.isDirty = true; parent2.rightDelim = keystroke; model.position += 1; model.selectionDidChange(); model.contentDidChange({ data: keyboardEventToChar(evt), inputType: "insertText" }); mathfield.snapshot("insert-fence"); mathfield.dirty = true; mathfield.scrollIntoView(); if (evt.preventDefault) evt.preventDefault(); return false; } if (!model.selectionIsCollapsed) { const fence = keyboardEventToChar(evt); if (fence === "(" || fence === "{" || fence === "[") { const lDelim = { "(": "(", "{": "\\lbrace", "[": "\\lbrack" }[fence]; const rDelim = { "(": ")", "{": "\\rbrace", "[": "\\rbrack" }[fence]; const [start, end] = range(model.selection); mathfield.snapshot(); model.position = end; ModeEditor.insert(model, rDelim, { format: "latex" }); model.position = start; ModeEditor.insert(model, lDelim, { format: "latex" }); model.setSelection(start + 1, end + 1); model.contentDidChange({ data: fence, inputType: "insertText" }); mathfield.snapshot("insert-fence"); mathfield.dirty = true; mathfield.scrollIntoView(); if (evt.preventDefault) evt.preventDefault(); return false; } } } else if (insertSmartFence( model, keyboardEventToChar(evt), mathfield.effectiveStyle )) { mathfield.dirty = true; mathfield.scrollIntoView(); if (evt.preventDefault) evt.preventDefault(); return false; } return true; } const child = model.at(Math.max(model.position, model.anchor)); const { parent } = child; if (selector === "moveAfterParent" && (parent == null ? void 0 : parent.type) === "leftright" && child.isLastSibling && mathfield.options.smartFence && insertSmartFence(model, ".", mathfield.defaultStyle)) { selector = ""; requestUpdate(mathfield); } mathfield.keyboardDelegate.cancelComposition(); if (selector) mathfield.executeCommand(selector); else if (shortcut) { const style = mathfield.effectiveStyle; model.setState(buffer[stateIndex].state); const keystrokes = buffer[buffer.length - 1].keystrokes; for (const c of keystrokes) { ModeEditor.insert(model, c, { silenceNotifications: true, style }); } mathfield.snapshot(`insert-shortcut`); model.setState(buffer[stateIndex].state); model.deferNotifications( { content: true, selection: true, data: shortcut, type: "insertText" }, () => { ModeEditor.insert(model, shortcut, { format: "latex", style }); removeIsolatedSpace(mathfield.model); if (shortcut.endsWith(" ")) { mathfield.switchMode("text"); ModeEditor.insert(model, " ", { style, mode: "text" }); } mathfield.snapshot(); if (!model.selectionIsCollapsed) mathfield.flushInlineShortcutBuffer(); return true; } ); mathfield.dirty = true; model.announce("replacement"); } mathfield.scrollIntoView(); if (evt.preventDefault) evt.preventDefault(); return false; } function onInput(mathfield, text, options) { const { model } = mathfield; if (!mathfield.isSelectionEditable) { model.announce("plonk"); return; } options != null ? options : options = {}; if (options.focus) mathfield.focus(); if (options.feedback) window.MathfieldElement.playSound("keypress"); if (typeof options.mode === "string") { mathfield.switchMode(options.mode); mathfield.snapshot(); } let graphemes = splitGraphemes(text); const keyboard = window.mathVirtualKeyboard; if (keyboard == null ? void 0 : keyboard.isShifted) { graphemes = typeof graphemes === "string" ? graphemes.toUpperCase() : graphemes.map((c) => c.toUpperCase()); } if (options.simulateKeystroke) { let handled = true; for (const c of graphemes) { if (onKeystroke(mathfield, new KeyboardEvent("keypress", { key: c }))) handled = false; } if (handled) return; } const atom = model.at(model.position); const style = __spreadValues(__spreadValues({}, atom.computedStyle), mathfield.defaultStyle); if (!model.selectionIsCollapsed) { model.deleteAtoms(range(model.selection)); mathfield.snapshot("delete"); } if (model.mode === "latex") { model.deferNotifications( { content: true, selection: true, data: text, type: "insertText" }, () => { removeSuggestion(mathfield); for (const c of graphemes) ModeEditor.insert(model, c); mathfield.snapshot("insert-latex"); updateAutocomplete(mathfield); } ); } else if (model.mode === "text") { for (const c of graphemes) ModeEditor.insert(model, c, { style }); mathfield.snapshot("insert-text"); } else if (model.mode === "math") for (const c of graphemes) insertMathModeChar(mathfield, c, style, atom); mathfield.dirty = true; mathfield.scrollIntoView(); } function getLeftSiblings(mf) { const model = mf.model; const result = []; let atom = model.at(Math.min(model.position, model.anchor)); while (atom.type !== "first") { result.push(atom); atom = atom.leftSibling; } return result; } function insertMathModeChar(mathfield, c, style, atom) { const model = mathfield.model; let selector = { "^": "moveToSuperscript", "_": "moveToSubscript", " ": "moveAfterParent" }[c]; if (c === " " && mathfield.options.mathModeSpace) selector = ["insert", mathfield.options.mathModeSpace]; if (selector) { mathfield.executeCommand(selector); return; } if (/\d/.test(c) && mathfield.options.smartSuperscript && atom.parentBranch === "superscript" && atom.parent.type !== "mop" && atom.parent.type !== "operator" && atom.parent.type !== "extensible-symbol" && atom.hasNoSiblings) { clearSelection(model); ModeEditor.insert(model, c, { style }); mathfield.snapshot(); moveAfterParent(model); mathfield.snapshot(); return; } if (/[a-zA-Z0-9]/.test(c) && mathfield.adoptStyle !== "none") { const sibling = mathfield.adoptStyle === "left" ? atom : atom.parent ? atom.rightSibling : null; if ((sibling == null ? void 0 : sibling.type) === "mord" && /[a-zA-Z0-9]/.test(sibling.value)) { style = __spreadValues({}, style); if (sibling.style.variant) style.variant = sibling.style.variant; if (sibling.style.variantStyle) style.variantStyle = sibling.style.variantStyle; } } ModeEditor.insert(model, c, { style }); mathfield.snapshot(`insert-${model.at(model.position).type}`); } function clearSelection(model) { if (!model.selectionIsCollapsed) { model.deleteAtoms(range(model.selection)); model.mathfield.snapshot("delete"); } } function insertSmartFence(model, key, style) { if (!key) return false; if (model.mode !== "math") return false; const atom = model.at(model.position); const { parent } = atom; const fence = { "(": "(", ")": ")", "{": "\\lbrace", "}": "\\rbrace", "[": "\\lbrack", "]": "\\rbrack", "|": "|" }[key]; if (!fence) return false; const lDelim = LEFT_DELIM[fence]; const rDelim = RIGHT_DELIM[fence]; if (!model.selectionIsCollapsed) { model.mathfield.snapshot(); const [start, end] = range(model.selection); const body = model.extractAtoms([start, end]); const atom2 = parent.addChildrenAfter( [ new LeftRightAtom("left...right", body, { leftDelim: fence, rightDelim: rDelim }) ], model.at(start) ); model.setSelection( model.offsetOf(atom2.firstChild), model.offsetOf(atom2.lastChild) ); model.mathfield.snapshot("insert-fence"); model.contentDidChange({ data: fence, inputType: "insertText" }); return true; } if (fence === "|") { const delims = parent instanceof LeftRightAtom ? parent.leftDelim + parent.rightDelim : ""; if (delims === "\\lbrace\\rbrace" || delims === "\\{\\}" || delims === "\\lbrace?") { model.mathfield.snapshot(); ModeEditor.insert(model, "\\,\\middle\\vert\\,", { format: "latex", style }); model.mathfield.snapshot("insert-fence"); model.contentDidChange({ data: fence, inputType: "insertText" }); return true; } } if (rDelim) { if (parent instanceof LeftRightAtom && parent.firstChild === atom && // At first child (parent.leftDelim === "?" || parent.leftDelim === ".")) { parent.leftDelim = fence; parent.isDirty = true; model.mathfield.snapshot(); model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } if (!(parent instanceof LeftRightAtom)) { let sibling = atom; while (sibling) { if (sibling.type === "mclose" && sibling.value === rDelim) break; sibling = sibling.rightSibling; } if (sibling) { model.mathfield.snapshot(); const body = model.extractAtoms([ model.offsetOf(atom), model.offsetOf(sibling) ]); body.pop(); parent.addChildrenAfter( [ new LeftRightAtom("left...right", body, { leftDelim: fence, rightDelim: rDelim }) ], atom ); model.position = model.offsetOf(parent.firstChild) + 1; model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } } const lastSibling = model.offsetOf(atom.lastSibling); let i; for (i = model.position; i <= lastSibling; i++) { const atom2 = model.at(i); if (atom2 instanceof LeftRightAtom && (atom2.leftDelim === "?" || atom2.leftDelim === ".") && isValidOpen(fence, atom2.rightDelim)) break; } const match = model.at(i); if (i <= lastSibling && match instanceof LeftRightAtom) { match.leftDelim = fence; model.mathfield.snapshot(); let extractedAtoms = model.extractAtoms([model.position, i - 1]); extractedAtoms = extractedAtoms.filter((value) => value.type !== "first"); match.addChildren(extractedAtoms, match.parentBranch); model.position += 1; model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } if (parent instanceof LeftRightAtom && (parent.leftDelim === "?" || parent.leftDelim === ".") && isValidOpen(fence, parent.rightDelim)) { parent.isDirty = true; parent.leftDelim = fence; model.mathfield.snapshot(); const extractedAtoms = model.extractAtoms([ model.offsetOf(atom.firstSibling), model.position ]); for (const extractedAtom of extractedAtoms) parent.parent.addChildBefore(extractedAtom, parent); model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } if (!(parent instanceof LeftRightAtom && parent.leftDelim === "|")) { model.mathfield.snapshot(); ModeEditor.insert(model, `\\left${fence}\\right?`, { format: "latex", style }); if (atom.lastSibling.type !== "first") { const lastSiblingOffset = model.offsetOf(atom.lastSibling); const content = model.extractAtoms([model.position, lastSiblingOffset]); model.at(model.position).body = content; model.position -= 1; } model.mathfield.snapshot("insert-fence"); return true; } } if (lDelim) { let sibling = atom; while (sibling) { if (sibling.type === "mopen" && sibling.value === lDelim) { model.mathfield.snapshot(); const insertAfter = sibling.leftSibling; const body = model.extractAtoms([ model.offsetOf(sibling.leftSibling), model.offsetOf(atom) ]); body.shift(); const result = new LeftRightAtom("left...right", body, { leftDelim: lDelim, rightDelim: fence }); parent.addChildrenAfter([result], insertAfter); model.position = model.offsetOf(result); model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } sibling = sibling.leftSibling; } if (parent instanceof LeftRightAtom && atom.isLastSibling && isValidClose(parent.leftDelim, fence)) { model.mathfield.snapshot(); parent.isDirty = true; parent.rightDelim = fence; model.position += 1; model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } const firstSibling = model.offsetOf(atom.firstSibling); let i; for (i = model.position; i >= firstSibling; i--) { const atom2 = model.at(i); if (atom2 instanceof LeftRightAtom && (atom2.rightDelim === "?" || atom2.rightDelim === ".") && isValidClose(atom2.leftDelim, fence)) break; } const match = model.at(i); if (i >= firstSibling && match instanceof LeftRightAtom) { model.mathfield.snapshot(); match.rightDelim = fence; match.addChildren( model.extractAtoms([i, model.position]), match.parentBranch ); model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } if (parent instanceof LeftRightAtom && (parent.rightDelim === "?" || parent.rightDelim === ".") && isValidClose(parent.leftDelim, fence)) { model.mathfield.snapshot(); parent.isDirty = true; parent.rightDelim = fence; parent.parent.addChildren( model.extractAtoms([model.position, model.offsetOf(atom.lastSibling)]), parent.parentBranch ); model.position = model.offsetOf(parent); model.contentDidChange({ data: fence, inputType: "insertText" }); model.mathfield.snapshot("insert-fence"); return true; } const grandparent = parent.parent; if (grandparent instanceof LeftRightAtom && (grandparent.rightDelim === "?" || grandparent.rightDelim === ".") && model.at(model.position).isLastSibling) { model.position = model.offsetOf(grandparent); return insertSmartFence(model, fence, style); } return false; } return false; } function isValidClose(open, close) { if (!open) return true; if (["(", "\\lparen", "{", "\\{", "\\lbrace", "[", "\\lbrack"].includes(open)) { return [")", "\\rparen", "}", "\\}", "\\rbrace", "]", "\\rbrack"].includes( close ); } return RIGHT_DELIM[open] === close; } function isValidOpen(open, close) { if (!close) return true; if ([")", "\\rparen", "}", "\\}", "\\rbrace", "]", "\\rbrack"].includes(close)) { return ["(", "\\lparen", "{", "\\{", "\\lbrace", "[", "\\lbrack"].includes( open ); } return LEFT_DELIM[close] === open; } // src/editor-mathfield/commands.ts register2({ undo: (mathfield) => { mathfield.undo(); return true; }, redo: (mathfield) => { mathfield.redo(); return true; }, scrollIntoView: (mathfield) => { mathfield.scrollIntoView(); return true; }, scrollToStart: (mathfield) => { mathfield.field.scroll(0, 0); return true; }, scrollToEnd: (mathfield) => { const fieldBounds = mathfield.field.getBoundingClientRect(); mathfield.field.scroll(fieldBounds.left - window.scrollX, 0); return true; }, toggleKeystrokeCaption, toggleContextMenu: (mathfield) => { const result = mathfield.toggleContextMenu(); if (!result) mathfield.model.announce("plonk"); return result; }, plonk: (mathfield) => { mathfield.model.announce("plonk"); return true; }, switchMode: (mathfield, mode, prefix, suffix) => { mathfield.switchMode(mode, prefix, suffix); return true; }, insert: (mathfield, s, options) => mathfield.insert(s, options), typedText: (mathfield, text, options) => { onInput(mathfield, text, options); return true; }, insertDecimalSeparator: (mathfield) => { const model = mathfield.model; if (model.mode === "math" && window.MathfieldElement.decimalSeparator === ",") { const child = model.at(Math.max(model.position, model.anchor)); if (child.isDigit()) { mathfield.insert("{,}", { format: "latex" }); mathfield.snapshot("insert-mord"); return true; } } mathfield.insert("."); return true; }, // A 'commit' command is used to simulate pressing the return/enter key, // e.g. when using a virtual keyboard commit: (mathfield) => { var _a3; if (mathfield.model.contentWillChange({ inputType: "insertLineBreak" })) { (_a3 = mathfield.host) == null ? void 0 : _a3.dispatchEvent( new Event("change", { bubbles: true, composed: true }) ); mathfield.model.contentDidChange({ inputType: "insertLineBreak" }); } return true; }, insertPrompt: (mathfield, id, options) => { const promptIds = mathfield.getPrompts(); let prospectiveId = "prompt-" + Date.now().toString(36).slice(-2) + Math.floor(Math.random() * 1e5).toString(36); let i = 0; while (promptIds.includes(prospectiveId) && i < 100) { if (i === 99) { console.error("could not find a unique ID after 100 tries"); return false; } prospectiveId = "prompt-" + Date.now().toString(36).slice(-2) + Math.floor(Math.random() * 1e5).toString(36); i++; } mathfield.insert(`\\placeholder[${id != null ? id : prospectiveId}]{}`, options); return true; } }); register2( { copyToClipboard: (mathfield) => { mathfield.focus(); if (mathfield.model.selectionIsCollapsed) mathfield.select(); if ("queryCommandSupported" in document && document.queryCommandSupported("copy")) document.execCommand("copy"); else { mathfield.element.querySelector(".ML__keyboard-sink").dispatchEvent( new ClipboardEvent("copy", { bubbles: true, composed: true }) ); } return false; } }, { target: "mathfield" } ); register2( { cutToClipboard: (mathfield) => { mathfield.focus(); if ("queryCommandSupported" in document && document.queryCommandSupported("cut")) document.execCommand("cut"); else { mathfield.element.querySelector(".ML__keyboard-sink").dispatchEvent( new ClipboardEvent("cut", { bubbles: true, composed: true }) ); } return true; }, pasteFromClipboard: (mathfield) => { mathfield.focus(); if ("queryCommandSupported" in document && document.queryCommandSupported("paste")) { document.execCommand("paste"); return true; } navigator.clipboard.readText().then((text) => { if (text && mathfield.model.contentWillChange({ inputType: "insertFromPaste", data: text })) { mathfield.stopCoalescingUndo(); mathfield.stopRecording(); if (mathfield.insert(text, { mode: mathfield.model.mode })) { updateAutocomplete(mathfield); mathfield.startRecording(); mathfield.snapshot("paste"); mathfield.model.contentDidChange({ inputType: "insertFromPaste" }); requestUpdate(mathfield); } } else mathfield.model.announce("plonk"); mathfield.startRecording(); }); return true; } }, { target: "mathfield", canUndo: true, changeContent: true, changeSelection: true } ); // src/editor-mathfield/styling.ts function applyStyle2(mathfield, inStyle) { mathfield.flushInlineShortcutBuffer(); mathfield.stopCoalescingUndo(); const style = validateStyle(mathfield, inStyle); const { model } = mathfield; if (model.selectionIsCollapsed) { if (mathfield.defaultStyle.fontSeries && style.fontSeries === mathfield.defaultStyle.fontSeries) style.fontSeries = "auto"; if (style.fontShape && style.fontShape === mathfield.defaultStyle.fontShape) style.fontShape = "auto"; if (style.color && style.color === mathfield.defaultStyle.color) style.color = "none"; if (style.backgroundColor && style.backgroundColor === mathfield.defaultStyle.backgroundColor) style.backgroundColor = "none"; if (style.fontSize && style.fontSize === mathfield.defaultStyle.fontSize) style.fontSize = "auto"; mathfield.defaultStyle = __spreadValues(__spreadValues({}, mathfield.defaultStyle), style); } else { mathfield.model.deferNotifications( { content: true, type: "insertText" }, () => { model.selection.ranges.forEach( (range2) => applyStyle(model, range2, style, { operation: "toggle" }) ); mathfield.snapshot("style-change"); } ); } return true; } register2( { applyStyle: applyStyle2 }, { target: "mathfield", canUndo: true, changeContent: true } ); function validateStyle(mathfield, style) { var _a3, _b3, _c2, _d2, _e, _f, _g, _h, _i, _j; const result = {}; if (typeof style.color === "string") { const newColor = (_b3 = mathfield.colorMap((_a3 = style.color) != null ? _a3 : style.verbatimColor)) != null ? _b3 : "none"; if (newColor !== style.color) result.verbatimColor = (_c2 = style.verbatimColor) != null ? _c2 : style.color; result.color = newColor; } if (typeof style.backgroundColor === "string") { const newColor = (_e = mathfield.backgroundColorMap( (_d2 = style.backgroundColor) != null ? _d2 : style.verbatimBackgroundColor )) != null ? _e : "none"; if (newColor !== style.backgroundColor) { result.verbatimBackgroundColor = (_f = style.verbatimBackgroundColor) != null ? _f : style.backgroundColor; } result.backgroundColor = newColor; } if (typeof style.fontFamily === "string") result.fontFamily = style.fontFamily; if (typeof style.series === "string") result.fontSeries = style.series; if (typeof style.fontSeries === "string") result.fontSeries = style.fontSeries.toLowerCase(); if (result.fontSeries) { result.fontSeries = (_g = { bold: "b", medium: "m", normal: "m" }[result.fontSeries]) != null ? _g : result.fontSeries; } if (typeof style.shape === "string") result.fontShape = style.shape; if (typeof style.fontShape === "string") result.fontShape = style.fontShape.toLowerCase(); if (result.fontShape) { result.fontShape = (_h = { italic: "it", up: "n", upright: "n", normal: "n" }[result.fontShape]) != null ? _h : result.fontShape; } if (style.variant) result.variant = style.variant.toLowerCase(); if (style.variantStyle) result.variantStyle = style.variantStyle.toLowerCase(); const size = (_i = style.size) != null ? _i : style.fontSize; if (typeof size === "number") result.fontSize = Math.max(1, Math.min(10, size)); else if (typeof size === "string") { result.fontSize = (_j = { size1: 1, size2: 2, size3: 3, size4: 4, size5: 5, size6: 6, size7: 7, size8: 8, size9: 9, size10: 10 }[size.toLowerCase()]) != null ? _j : { tiny: 1, scriptsize: 2, footnotesize: 3, small: 4, normal: 5, normalsize: 5, large: 6, Large: 7, LARGE: 8, huge: 9, Huge: 10 }[size]; } return result; } // src/editor-model/commands-select.ts function selectGroup(model) { let [start, end] = range(model.selection); start = boundary(model, start, "backward"); end = boundary(model, end, "forward"); if (start === end) { const atom = model.at(start); if (atom.type === "leftright") return model.setSelection(model.offsetOf(atom.firstChild) - 1, end); if (atom.type === "first" && (atom.parent.type === "leftright" || atom.parent.type === "surd")) { return model.setSelection( start - 1, model.offsetOf(atom.parent.lastChild) + 1 ); } model.setSelection(start - 1, end); } else model.setSelection(start, end); return true; } function boundary(model, pos, direction) { var _a3, _b3, _c2; let atom = model.at(pos); if (!atom) return pos; const dir = direction === "forward" ? 1 : -1; if (atom.mode === "text") { while (atom) { if (atom.mode !== "text" || !LETTER_AND_DIGITS.test(atom.value)) break; pos += dir; atom = model.at(pos); } return direction === "backward" ? pos - 1 : pos; } if (atom.mode === "latex") { if (/[a-zA-Z\*]/.test(atom.value)) { if (direction === "backward") { while (atom && atom.mode === "latex" && atom.value !== "\\" && /[a-zA-Z]/.test(atom.value)) { pos += dir; atom = model.at(pos); } } else { while (atom && atom.mode === "latex" && /[a-zA-Z\*]/.test(atom.value)) { pos += dir; atom = model.at(pos); } } } else if (atom.value === "{") { if (direction === "forward") { while (atom && atom.mode === "latex" && atom.value !== "}") { pos += dir; atom = model.at(pos); } return pos; } return pos - 1; } else if (atom.value === "}") { if (direction === "backward") { while (atom && atom.mode === "latex" && atom.value !== "{") { pos += dir; atom = model.at(pos); } return pos - 1; } return pos; } return pos - 1; } if (atom.mode === "math") { if (atom.isDigit()) { while ((_a3 = model.at(pos + dir)) == null ? void 0 : _a3.isDigit()) pos += dir; return direction === "backward" ? pos - 1 : pos; } if (atom.style.variant || atom.style.variantStyle) { let x = (_b3 = model.at(pos)) == null ? void 0 : _b3.style; while (x && x.variant === atom.style.variant && x.variantStyle === atom.style.variantStyle) { x = (_c2 = model.at(pos + dir)) == null ? void 0 : _c2.style; pos += dir; } return direction === "backward" ? pos - 1 : pos; } return pos; } return pos; } register2( { selectGroup: (model) => { const result = selectGroup(model); if (!result) model.announce("plonk"); return result; }, selectAll: (model) => model.setSelection(0, model.lastOffset), extendSelectionForward: (model) => move(model, "forward", { extend: true }), extendSelectionBackward: (model) => move(model, "backward", { extend: true }), extendToNextWord: (model) => skip(model, "forward", { extend: true }), extendToPreviousWord: (model) => skip(model, "backward", { extend: true }), extendSelectionUpward: (model) => move(model, "upward", { extend: true }), extendSelectionDownward: (model) => move(model, "downward", { extend: true }), /** * Extend the selection until the next boundary is reached. A boundary * is defined by an atom of a different type (mbin, mord, etc...) * than the current focus. For example, in "1234+x=y", if the focus is between * "1" and "2", invoking `extendToNextBoundary_` would extend the selection * to "234". */ extendToNextBoundary: (model) => skip(model, "forward", { extend: true }), /** * Extend the selection until the previous boundary is reached. A boundary * is defined by an atom of a different type (mbin, mord, etc...) * than the current focus. For example, in "1+23456", if the focus is between * "5" and "6", invoking `extendToPreviousBoundary` would extend the selection * to "2345". */ extendToPreviousBoundary: (model) => skip(model, "backward", { extend: true }), extendToGroupStart: (model) => { const result = model.setSelection( model.anchor, model.offsetOf(model.at(model.position).firstSibling) ); if (!result) model.announce("plonk"); return result; }, extendToGroupEnd: (model) => { const result = model.setSelection( model.anchor, model.offsetOf(model.at(model.position).lastSibling) ); if (!result) model.announce("plonk"); return result; }, extendToMathFieldStart: (model) => { const result = model.setSelection(model.anchor, 0); if (!result) model.announce("plonk"); return result; }, extendToMathFieldEnd: (model) => { const result = model.setSelection(model.anchor, model.lastOffset); if (!result) model.announce("plonk"); return result; } }, { target: "model", changeSelection: true } ); // src/editor-mathfield/pointer-input.ts var gLastTap = null; var gTapCount = 0; var PointerTracker = class _PointerTracker { static start(element, evt, onMove, onCancel) { var _a3; _PointerTracker.element = element; (_a3 = _PointerTracker.controller) == null ? void 0 : _a3.abort(); _PointerTracker.controller = new AbortController(); const options = { signal: _PointerTracker.controller.signal }; if ("PointerEvent" in window) { element.addEventListener("pointermove", onMove, options); element.addEventListener("pointerup", onCancel, options); element.addEventListener("pointercancel", onCancel, options); if (isPointerEvent(evt)) { _PointerTracker.pointerId = evt.pointerId; element.setPointerCapture(evt.pointerId); } } else { window.addEventListener("mousemove", onMove, options); window.addEventListener("blur", onCancel, options); window.addEventListener("mouseup", onCancel, options); } } static stop() { var _a3; (_a3 = _PointerTracker.controller) == null ? void 0 : _a3.abort(); _PointerTracker.controller = void 0; if (typeof _PointerTracker.pointerId === "number") { _PointerTracker.element.releasePointerCapture(_PointerTracker.pointerId); _PointerTracker.pointerId = void 0; } } }; function isPointerEvent(evt) { return evt !== null && globalThis.PointerEvent !== void 0 && evt instanceof PointerEvent; } function onPointerDown(mathfield, evt) { var _a3; if (evt.buttons > 1) return; mathfield.atomBoundsCache = /* @__PURE__ */ new Map(); const that = mathfield; let anchor; let trackingPointer = false; let trackingWords = false; let dirty = "none"; let scrollLeft = false; let scrollRight = false; const anchorX = evt.clientX; const anchorY = evt.clientY; const anchorTime = Date.now(); const field = that.field; const scrollInterval = setInterval(() => { if (scrollLeft) field.scroll({ top: 0, left: field.scrollLeft - 16 }); else if (scrollRight) field.scroll({ top: 0, left: field.scrollLeft + 16 }); }, 32); function endPointerTracking() { PointerTracker.stop(); trackingPointer = false; clearInterval(scrollInterval); mathfield.element.classList.remove("tracking"); if (evt) evt.preventDefault(); } function onPointerMove(evt2) { if (!that.hasFocus()) { endPointerTracking(); return; } const x = evt2.clientX; const y = evt2.clientY; const hysteresis = isPointerEvent(evt2) && evt2.pointerType === "touch" ? 20 : 5; if (Date.now() < anchorTime + 500 && Math.abs(anchorX - x) < hysteresis && Math.abs(anchorY - y) < hysteresis) { evt2.preventDefault(); evt2.stopPropagation(); return; } const fieldBounds = field.getBoundingClientRect(); scrollRight = x > fieldBounds.right; scrollLeft = x < fieldBounds.left; let actualAnchor = anchor; if (isPointerEvent(evt2)) { if (!evt2.isPrimary) { actualAnchor = offsetFromPoint(that, evt2.clientX, evt2.clientY, { bias: 0 }); } } const focus = offsetFromPoint(that, x, y, { bias: x <= anchorX ? x === anchorX ? 0 : -1 : 1 }); if (actualAnchor >= 0 && focus >= 0) { that.model.extendSelectionTo(actualAnchor, focus); requestUpdate(mathfield); } if (trackingWords) selectGroup(that.model); } if (gLastTap && Math.abs(gLastTap.x - anchorX) < 5 && Math.abs(gLastTap.y - anchorY) < 5 && Date.now() < gLastTap.time + 500) { gTapCount += 1; gLastTap.time = anchorTime; } else { gLastTap = { x: anchorX, y: anchorY, time: anchorTime }; gTapCount = 1; } const bounds = field.getBoundingClientRect(); if (anchorX >= bounds.left && anchorX <= bounds.right && anchorY >= bounds.top && anchorY <= bounds.bottom) { mathfield.flushInlineShortcutBuffer(); mathfield.adoptStyle = "left"; anchor = offsetFromPoint(mathfield, anchorX, anchorY, { bias: 0 }); if (anchor >= 0) { mathfield.element.classList.add("tracking"); if (evt.shiftKey) { const wasCollapsed = mathfield.model.selectionIsCollapsed; mathfield.model.extendSelectionTo(mathfield.model.anchor, anchor); if (acceptCommandSuggestion(mathfield.model) || wasCollapsed) dirty = "all"; else dirty = "selection"; } else if (mathfield.model.at(anchor).type === "placeholder") { mathfield.model.setSelection(anchor - 1, anchor); dirty = "selection"; } else if (((_a3 = mathfield.model.at(anchor).rightSibling) == null ? void 0 : _a3.type) === "placeholder") { mathfield.model.setSelection(anchor, anchor + 1); dirty = "selection"; } else { mathfield.model.position = anchor; if (acceptCommandSuggestion(mathfield.model)) dirty = "all"; else dirty = "selection"; } mathfield.defaultStyle = {}; if (evt.detail === 3 || gTapCount > 2) { endPointerTracking(); if (evt.detail === 3 || gTapCount === 3) { mathfield.model.selection = { ranges: [[0, mathfield.model.lastOffset]] }; dirty = "all"; } } else if (!trackingPointer) { trackingPointer = true; PointerTracker.start(field, evt, onPointerMove, endPointerTracking); if (evt.detail === 2 || gTapCount === 2) { trackingWords = true; selectGroup(mathfield.model); dirty = "all"; } } } if (!mathfield.hasFocus()) { dirty = "none"; mathfield.focus({ preventScroll: true }); } } else gLastTap = null; mathfield.stopCoalescingUndo(); if (dirty !== "none") { if (mathfield.model.selectionIsCollapsed) dirty = "all"; requestUpdate(mathfield); } evt.preventDefault(); } function distance(x, y, r) { if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return 0; const dx = x - (r.left + r.right) / 2; const dy = y - (r.top + r.bottom) / 2; return dx * dx + dy * dy; } function nearestAtomFromPointRecursive(mathfield, cache, atom, x, y) { if (!atom.id) return [Infinity, null]; if (cache.has(atom.id)) return cache.get(atom.id); const bounds = getAtomBounds(mathfield, atom); if (!bounds) return [Infinity, null]; let result = [ Infinity, null ]; if (atom.hasChildren && !atom.captureSelection && x >= bounds.left && x <= bounds.right) { for (const child of atom.children) { const r = nearestAtomFromPointRecursive(mathfield, cache, child, x, y); if (r[0] <= result[0]) result = r; } } if (!result[1]) result = [distance(x, y, bounds), atom]; cache.set(atom.id, result); return result; } function nearestAtomFromPoint(mathfield, x, y) { const [, atom] = nearestAtomFromPointRecursive( mathfield, /* @__PURE__ */ new Map(), mathfield.model.root, x, y ); return atom; } function offsetFromPoint(mathfield, x, y, options) { var _a3; const bounds = mathfield.field.querySelector(".ML__latex").getBoundingClientRect(); if (!bounds) return 0; if (x > bounds.right || y > bounds.bottom + 8) return mathfield.model.lastOffset; if (x < bounds.left || y < bounds.top - 8) return 0; options = options != null ? options : {}; options.bias = (_a3 = options.bias) != null ? _a3 : 0; let atom = nearestAtomFromPoint(mathfield, x, y); const parents = []; let parent = atom; while (parent) { parents.unshift(parent); parent = parent.parent; } for (const x2 of parents) { if (x2.captureSelection) { atom = x2; break; } } let result = mathfield.model.offsetOf(atom); if (result < 0) return -1; if (atom.leftSibling) { if (options.bias === 0 && atom.type !== "placeholder") { const bounds2 = getAtomBounds(mathfield, atom); if (bounds2 && x < (bounds2.left + bounds2.right) / 2) result = mathfield.model.offsetOf(atom.leftSibling); } else if (options.bias < 0) result = mathfield.model.offsetOf(atom.leftSibling); } return result; } // src/editor-mathfield/mode-editor-math.ts var MathModeEditor = class extends ModeEditor { constructor() { super("math"); } onPaste(mathfield, data) { if (!data) return false; if (!mathfield.model.contentWillChange({ data: typeof data === "string" ? data : null, dataTransfer: typeof data === "string" ? null : data, inputType: "insertFromPaste" })) return false; let text = ""; let format = "auto"; let json = typeof data !== "string" ? data.getData("application/json+mathlive") : ""; if (json) { try { const atomJson = JSON.parse(json); if (atomJson && Array.isArray(atomJson)) { mathfield.snapshot(); const atoms = fromJson(atomJson); const { model } = mathfield; if (!model.selectionIsCollapsed) model.deleteAtoms(range(model.selection)); const cursor = model.at(model.position); if (cursor.parent instanceof ArrayAtom) { console.assert(cursor.parentBranch !== void 0); const columns = []; let buffer = []; if (atoms[0].type === "first") atoms.shift(); if (atoms[atoms.length - 1].type === "first") atoms.pop(); for (const atom of atoms) { if (atom.type === "first" && buffer.length > 0) { columns.push(buffer); buffer = [atom]; } else buffer.push(atom); } if (buffer.length > 0) columns.push(buffer); let currentRow = Number(cursor.parentBranch[0]); let currentColumn = Number(cursor.parentBranch[1]); const maxColumns = cursor.parent.maxColumns; while (cursor.parent.colCount - currentColumn < columns.length && cursor.parent.colCount < maxColumns) cursor.parent.addColumn(); cursor.parent.addChildrenAfter(columns[0], cursor); for (let i = 1; i < columns.length; i++) { currentColumn++; if (currentColumn >= maxColumns) { currentColumn = 0; cursor.parent.addRowAfter(currentRow); currentRow++; } cursor.parent.setCell(currentRow, currentColumn, columns[i]); } } else { cursor.parent.addChildrenAfter( atoms.filter((a) => a.type !== "first"), cursor ); } model.position = model.offsetOf(atoms[atoms.length - 1]); model.contentDidChange({ inputType: "insertFromPaste" }); requestUpdate(mathfield); return true; } } catch (e) { } } json = typeof data !== "string" ? data.getData("application/json") : ""; if (json && window.MathfieldElement.computeEngine) { try { const expr = JSON.parse(json); if (typeof expr === "object" && "latex" in expr && expr.latex) text = expr.latex; if (!text) { const box = window.MathfieldElement.computeEngine.box(expr); if (box && !box.has("Error")) text = box.latex; } if (!text) format = "latex"; } catch (e) { } } if (!text && typeof data !== "string") { text = data.getData("application/x-latex"); if (text) format = "latex"; } if (!text) text = typeof data === "string" ? data : data.getData("text/plain"); if (text) { let wasLatex; [wasLatex, text] = trimModeShiftCommand(text); if (format === "auto" && wasLatex) format = "latex"; mathfield.stopCoalescingUndo(); mathfield.stopRecording(); if (this.insert(mathfield.model, text, { format })) { mathfield.startRecording(); mathfield.snapshot("paste"); requestUpdate(mathfield); } mathfield.startRecording(); return true; } return false; } insert(model, input, options) { var _a3, _b3; const data = typeof input === "string" ? input : (_b3 = (_a3 = window.MathfieldElement.computeEngine) == null ? void 0 : _a3.box(input).latex) != null ? _b3 : ""; if (!options.silenceNotifications && !model.contentWillChange({ data, inputType: "insertText" })) return false; if (!options.insertionMode) options.insertionMode = "replaceSelection"; if (!options.selectionMode) options.selectionMode = "placeholder"; if (!options.format) options.format = "auto"; const { silenceNotifications } = model; if (options.silenceNotifications) model.silenceNotifications = true; const contentWasChanging = model.silenceNotifications; model.silenceNotifications = true; const args = { "?": "\\placeholder{}", "@": "\\placeholder{}" }; args[0] = options.insertionMode === "replaceAll" ? "" : model.getValue(model.selection, "latex-unstyled"); if (options.insertionMode === "replaceSelection" && !model.selectionIsCollapsed) model.deleteAtoms(range(model.selection)); else if (options.insertionMode === "replaceAll") { model.root.setChildren([], "body"); model.position = 0; } else if (options.insertionMode === "insertBefore") model.collapseSelection("backward"); else if (options.insertionMode === "insertAfter") model.collapseSelection("forward"); if (!model.at(model.position).isLastSibling && model.at(model.position + 1).type === "placeholder") { model.deleteAtoms([model.position, model.position + 1]); } else if (model.at(model.position).type === "placeholder") { model.deleteAtoms([model.position - 1, model.position]); } let implicitArgumentOffset = -1; if (args[0]) { args["@"] = args[0]; } else if (typeof input === "string" && /(^|[^\\])#@/.test(input)) { implicitArgumentOffset = getImplicitArgOffset(model); if (implicitArgumentOffset >= 0) { args["@"] = model.getValue( implicitArgumentOffset, model.position, "latex" ); } } if (!args[0]) args[0] = args["?"]; let usedArg = false; const argFunction = (arg) => { usedArg = true; return args[arg]; }; let [format, newAtoms] = convertStringToAtoms( model, input, argFunction, options ); if (!newAtoms) return false; const insertingFraction = newAtoms.length === 1 && newAtoms[0].type === "genfrac"; if (insertingFraction && implicitArgumentOffset >= 0 && typeof model.mathfield.options.isImplicitFunction === "function" && model.mathfield.options.isImplicitFunction( model.at(model.position).command )) { args["@"] = args["?"]; usedArg = false; [format, newAtoms] = convertStringToAtoms( model, input, argFunction, options ); } else if (implicitArgumentOffset >= 0) { model.deleteAtoms([implicitArgumentOffset, model.position]); } const { parent } = model.at(model.position); const hadEmptyBody = parent.hasEmptyBranch("body"); if (insertingFraction && format !== "latex" && model.mathfield.options.removeExtraneousParentheses && parent instanceof LeftRightAtom && parent.leftDelim === "(" && hadEmptyBody) { const newParent = parent.parent; const branch = parent.parentBranch; newParent.removeChild(parent); newParent.setChildren(newAtoms, branch); } const cursor = model.at(model.position); cursor.parent.addChildrenAfter(newAtoms, cursor); if (format === "latex" && typeof input === "string") { if ((parent == null ? void 0 : parent.type) === "root" && hadEmptyBody && !usedArg) parent.verbatimLatex = input; } model.silenceNotifications = contentWasChanging; const lastNewAtom = newAtoms[newAtoms.length - 1]; if (options.selectionMode === "placeholder") { const placeholder = newAtoms.flatMap((x) => [x, ...x.children]).find((x) => x.type === "placeholder"); if (placeholder) { const placeholderOffset = model.offsetOf(placeholder); model.setSelection(placeholderOffset - 1, placeholderOffset); model.announce("move"); } else if (lastNewAtom) { model.position = model.offsetOf(lastNewAtom); } } else if (options.selectionMode === "before") { } else if (options.selectionMode === "after") { if (lastNewAtom) model.position = model.offsetOf(lastNewAtom); } else if (options.selectionMode === "item") model.setSelection(model.anchor, model.offsetOf(lastNewAtom)); model.contentDidChange({ data, inputType: "insertText" }); model.silenceNotifications = silenceNotifications; return true; } }; function convertStringToAtoms(model, s, args, options) { var _a3; let format = void 0; let result = []; if (typeof s !== "string" || options.format === "math-json") { const ce = window.MathfieldElement.computeEngine; if (!ce) return ["math-json", []]; [format, s] = ["latex", ce.box(s).latex]; result = parseLatex(s, { context: model.mathfield.context }); } else if (typeof s === "string" && options.format === "ascii-math") { [format, s] = parseMathString(s, { format: "ascii-math", inlineShortcuts: model.mathfield.options.inlineShortcuts }); result = parseLatex(s, { context: model.mathfield.context }); if (format !== "latex" && model.mathfield.options.removeExtraneousParentheses) simplifyParen(result); } else if (options.format === "auto" || ((_a3 = options.format) == null ? void 0 : _a3.startsWith("latex"))) { if (options.format === "auto") { [format, s] = parseMathString(s, { format: "auto", inlineShortcuts: model.mathfield.options.inlineShortcuts }); } if (options.format === "latex") [, s] = trimModeShiftCommand(s); result = parseLatex(s, { context: model.mathfield.context, args }); if (options.format !== "latex" && model.mathfield.options.removeExtraneousParentheses) simplifyParen(result); } applyStyleToUnstyledAtoms(result, options.style); return [format != null ? format : "latex", result]; } function removeParen(atoms) { if (!atoms) return null; console.assert(atoms[0].type === "first"); if (atoms.length > 1) return null; const atom = atoms[0]; if (atom instanceof LeftRightAtom && atom.leftDelim === "(" && atom.rightDelim === ")") return atom.removeBranch("body"); return null; } function simplifyParen(atoms) { if (!atoms) return; for (let i = 0; atoms[i]; i++) { const atom = atoms[i]; if (atom instanceof LeftRightAtom && atom.leftDelim === "(") { let genFracCount = 0; let genFracIndex = 0; let nonGenFracCount = 0; for (let j = 0; atom.body[j]; j++) { if (atom.body[j].type === "genfrac") { genFracCount++; genFracIndex = j; } nonGenFracCount++; } if (nonGenFracCount === 0 && genFracCount === 1) { atoms[i] = atom.body[genFracIndex]; } } } for (const atom of atoms) { for (const branch of atom.branches) { if (!atom.hasEmptyBranch(branch)) { simplifyParen(atom.branch(branch)); const newChildren = removeParen(atom.branch(branch)); if (newChildren) atom.setChildren(newChildren, branch); } } if (atom instanceof ArrayAtom) for (const x of atom.cells) simplifyParen(x); } } function getImplicitArgOffset(model) { let atom = model.at(model.position); if (atom.mode === "text") { while (!atom.isFirstSibling && atom.mode === "text") atom = atom.leftSibling; return model.offsetOf(atom); } const atomAtCursor = atom; let afterDelim = false; if (atom.type === "mclose") { const delim = LEFT_DELIM[atom.value]; while (!atom.isFirstSibling && !(atom.type === "mopen" && atom.value === delim)) atom = atom.leftSibling; if (!atom.isFirstSibling) atom = atom.leftSibling; afterDelim = true; } else if (atom.type === "leftright") { atom = atom.leftSibling; afterDelim = true; } if (afterDelim) { while (!atom.isFirstSibling && (atom.isFunction || isImplicitArg(atom))) atom = atom.leftSibling; } else { const delimiterStack = []; while (!atom.isFirstSibling && (isImplicitArg(atom) || delimiterStack.length > 0)) { if (atom.type === "mclose") delimiterStack.unshift(atom.value); if (atom.type === "mopen" && delimiterStack.length > 0 && atom.value === LEFT_DELIM[delimiterStack[0]]) delimiterStack.shift(); atom = atom.leftSibling; } } if (atomAtCursor === atom) return -1; return model.offsetOf(atom); } function isImplicitArg(atom) { if (atom.isDigit()) return true; if (atom.type && /^(mord|surd|subsup|leftright|mop|mclose)$/.test(atom.type)) { if (atom.isExtensibleSymbol) return false; return true; } return false; } new MathModeEditor(); // src/editor-mathfield/mode-editor-text.ts var TextModeEditor = class extends ModeEditor { constructor() { super("text"); } onPaste(mathfield, data) { if (!data) return false; const text = typeof data === "string" ? data : data.getData("text/plain"); if (text && mathfield.model.contentWillChange({ inputType: "insertFromPaste", data: text })) { mathfield.stopCoalescingUndo(); mathfield.stopRecording(); if (this.insert(mathfield.model, text)) { mathfield.model.contentDidChange({ inputType: "insertFromPaste" }); mathfield.startRecording(); mathfield.snapshot("paste"); requestUpdate(mathfield); } mathfield.startRecording(); return true; } return false; } insert(model, text, options = {}) { if (!model.contentWillChange({ data: text, inputType: "insertText" })) return false; if (!options.insertionMode) options.insertionMode = "replaceSelection"; if (!options.selectionMode) options.selectionMode = "placeholder"; if (!options.format) options.format = "auto"; const { silenceNotifications } = model; if (options.silenceNotifications) model.silenceNotifications = true; const contentWasChanging = model.silenceNotifications; model.silenceNotifications = true; if (options.insertionMode === "replaceSelection" && !model.selectionIsCollapsed) model.deleteAtoms(range(model.selection)); else if (options.insertionMode === "replaceAll") { model.root.setChildren([], "body"); model.position = 0; } else if (options.insertionMode === "insertBefore") model.collapseSelection("backward"); else if (options.insertionMode === "insertAfter") model.collapseSelection("forward"); const newAtoms = convertStringToAtoms2(text, model.mathfield.context); applyStyleToUnstyledAtoms(newAtoms, options.style); if (!newAtoms) return false; const cursor = model.at(model.position); const lastNewAtom = cursor.parent.addChildrenAfter(newAtoms, cursor); model.silenceNotifications = contentWasChanging; if (options.selectionMode === "before") { } else if (options.selectionMode === "item") model.setSelection(model.anchor, model.offsetOf(lastNewAtom)); else if (lastNewAtom) model.position = model.offsetOf(lastNewAtom); model.contentDidChange({ data: text, inputType: "insertText" }); model.silenceNotifications = silenceNotifications; return true; } }; function convertStringToAtoms2(s, context) { s = s.replace(/\\/g, "\\textbackslash "); s = s.replace(/#/g, "\\#"); s = s.replace(/\$/g, "\\$"); s = s.replace(/%/g, "\\%"); s = s.replace(/&/g, "\\&"); s = s.replace(/_/g, "\\_"); s = s.replace(/{/g, "\\textbraceleft "); s = s.replace(/}/g, "\\textbraceright "); s = s.replace(/lbrace/g, "\\textbraceleft "); s = s.replace(/rbrace/g, "\\textbraceright "); s = s.replace(/\^/g, "\\textasciicircum "); s = s.replace(/~/g, "\\textasciitilde "); s = s.replace(/£/g, "\\textsterling "); return parseLatex(s, { context, parseMode: "text" }); } new TextModeEditor(); // src/virtual-keyboard/mathfield-proxy.ts function makeProxy(mf) { return { value: mf.model.getValue(), selectionIsCollapsed: mf.model.selectionIsCollapsed, canUndo: mf.canUndo(), canRedo: mf.canRedo(), style: mf.selectionStyle, mode: mf.model.mode }; } // src/editor/environment-popover.ts var padding = 4; var radius = 20; var paddedWidth = 2 * (radius + padding); var newPlus = (x, y) => ` `; var newMinus = (x, y) => ` `; var newArrow = (x, y, theta) => ` `; var controllerSvg = ` ${newArrow(2 * (padding + paddedWidth), 2 * padding + 3 * paddedWidth, 0)} ${newArrow(2 * (padding + paddedWidth), 2 * padding + paddedWidth, 180)} ${newArrow(2 * padding + 3 * paddedWidth, 2 * (padding + paddedWidth), -90)} ${newArrow(2 * padding + paddedWidth, 2 * (padding + paddedWidth), 90)} ${newPlus(2 * padding + paddedWidth, padding)} ${newMinus(2 * padding + 2 * paddedWidth, padding)} ${newPlus(2 * padding + 3 * paddedWidth, padding)} ${newPlus(padding, 2 * padding + paddedWidth)} ${newMinus(padding, 2 * padding + 2 * paddedWidth)} ${newPlus(padding, 2 * padding + 3 * paddedWidth)} `; var matrix = (className) => ` `; var pmatrix = (className) => ` `; var Bmatrix = (className) => ` `; var bmatrix = (className) => ` `; var vmatrix = (className) => ` `; var Vmatrix = (className) => ` `; var cases2 = (className) => ` `; var rcases = (className) => ` `; var matrixButtons = { matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix }; var casesButtons = { cases: cases2, rcases, Bmatrix }; function showEnvironmentPopover(mf) { var _a3, _d2; const array = (_a3 = mf.model.parentEnvironment) == null ? void 0 : _a3.array; if (!array) return; let columnCount = 0; array.forEach((column) => { if (!columnCount || column.length > columnCount) columnCount = column.length; }); let panel = document.getElementById("mathlive-environment-popover"); if (!panel) { panel = getSharedElement("mathlive-environment-popover"); injectStylesheet("environment-popover"); injectStylesheet("core"); panel.setAttribute("aria-hidden", "true"); } let flexbox; const possiblyExistentFlexbox = panel.querySelector( ".MLEP__environment-controls" ); if (possiblyExistentFlexbox) flexbox = possiblyExistentFlexbox; else { flexbox = document.createElement("div"); panel.innerHTML = ""; panel.appendChild(flexbox); } flexbox.className = "MLEP__environment-controls"; flexbox.style.display = "flex"; flexbox.style.width = "100%"; flexbox.style.height = "100%"; flexbox.style.boxSizing = "border-box"; flexbox.innerHTML = controllerSvg; let delimiterOptions = []; let activeDelimeter = ""; const environment = mf.model.parentEnvironment.environmentName; if (isMatrixEnvironment(environment)) { const normalizedEnvironment = normalizeMatrixName(environment); activeDelimeter = matrixButtons[normalizedEnvironment]("active"); const _b3 = matrixButtons, { [normalizedEnvironment]: _ } = _b3, filteredDelimeters = __objRest(_b3, [__restKey(normalizedEnvironment)]); delimiterOptions = Object.values(filteredDelimeters).map( (f) => f("inactive") ); } else if (isCasesEnvironment(environment)) { const normalizedEnvironment = normalizeCasesName(environment); activeDelimeter = casesButtons[normalizedEnvironment]("active"); const _c2 = casesButtons, { [normalizedEnvironment]: _ } = _c2, filteredDelimeters = __objRest(_c2, [__restKey(normalizedEnvironment)]); delimiterOptions = Object.values(filteredDelimeters).map( (f) => f("inactive") ); } else if (isAlignEnvironment(environment)) { activeDelimeter = matrixButtons["matrix"]("active"); delimiterOptions = Object.values(casesButtons).map( (f) => f("inactive") ); } const delimiterControls = document.createElement("div"); delimiterControls.className = "MLEP__environment-delimiter-controls"; delimiterControls.style.display = "flex"; delimiterControls.style.flexDirection = "column"; delimiterControls.innerHTML = `
    ${activeDelimeter} ${delimiterOptions.join("")}
    `; if (activeDelimeter) flexbox.appendChild(delimiterControls); const arrayControls = flexbox.querySelectorAll( "[data-command]" ); arrayControls.forEach((control) => { const commandString = control.dataset.command; let command = commandString; try { command = JSON.parse(commandString); } catch (e) { } control.addEventListener("mousedown", (ev) => ev.preventDefault()); if (command) control.addEventListener("click", () => mf.executeCommand(command)); }); const position = (_d2 = mf.field) == null ? void 0 : _d2.getBoundingClientRect(); if (position) { panel.style.top = `${window.scrollY + (position.top - panel.clientHeight - 15)}px`; panel.style.left = `${position.left + 20}px`; panel.classList.add("is-visible"); } } function hideEnvironmentPopover() { const panel = document.getElementById("mathlive-environment-popover"); panel == null ? void 0 : panel.classList.remove("is-visible"); } function disposeEnvironmentPopover() { if (!document.getElementById("mathlive-environment-popover")) return; releaseSharedElement("mathlive-environment-popover"); releaseStylesheet("environment-popover"); releaseStylesheet("core"); } function updateEnvironmentPopover(mf) { if (!mf.hasFocus()) return; let visible = false; if (mf.model.mode === "math") { const env = mf.model.parentEnvironment; if (!!(env == null ? void 0 : env.array) && isTabularEnvironment(env.environmentName)) { const policy = mf.options.environmentPopoverPolicy; visible = policy === "auto" || policy === "on"; } } if (visible) showEnvironmentPopover(mf); else hideEnvironmentPopover(); } function normalizeMatrixName(environment) { return environment.replace("*", ""); } function normalizeCasesName(environment) { if (environment === "dcases") return "cases"; return environment; } // src/ui/i18n/utils.ts function getComputedDir(element) { const dir = getComputedStyle(element).direction; return dir === "ltr" || dir === "rtl" ? dir : "ltr"; } // src/ui/geometry/utils.ts function getEdge(bounds, position, direction) { if (position === "left" || position === "leading" && direction === "ltr" || position === "trailing" && direction === "rtl") return bounds.left; return bounds.right; } function getEffectivePos(pos, length, placement, dir) { if (placement === "middle") return pos - length / 2; if (placement === "start" && dir === "rtl" || placement === "end" && dir === "ltr" || placement === "top" || placement === "right") return Math.max(0, pos - length); return pos; } function getOppositeEffectivePos(pos, length, placement, dir) { if (placement === "middle") return pos - length / 2; if (placement === "start" && dir === "ltr" || placement === "end" && dir === "rtl" || placement === "top" || placement === "right") return pos; return pos - length; } function fitInViewport(element, options) { var _a3, _b3, _c2; const dir = (_a3 = getComputedDir(element)) != null ? _a3 : "ltr"; element.style.position = "fixed"; element.style.left = ""; element.style.top = ""; element.style.right = ""; element.style.bottom = ""; element.style.height = ""; element.style.width = ""; const elementBounds = element.getBoundingClientRect(); const maxHeight = Number.isFinite(options.maxHeight) ? Math.min(options.maxHeight, window.innerHeight) : window.innerHeight; let height = Math.min(maxHeight, (_b3 = options.height) != null ? _b3 : elementBounds.height); let top = getEffectivePos( options.location.y, height, options.verticalPos, dir ); if (top + height > window.innerHeight - 8) { if (options.alternateLocation) { top = getEffectivePos( options.alternateLocation.y, height, options.verticalPos, dir ); if (top + height > window.innerHeight - 8) top = void 0; } else top = void 0; } if (!Number.isFinite(top)) { top = Math.max(8, window.innerHeight - 8 - height); if (8 + height > window.innerHeight - 8) { element.style.bottom = "8px"; } } height = Math.min(top + height, window.innerHeight - 8) - top; const maxWidth = Number.isFinite(options.maxWidth) ? Math.min(options.maxWidth, window.innerWidth) : window.innerWidth; let width = Math.min(maxWidth, (_c2 = options.width) != null ? _c2 : elementBounds.width); let left = getEffectivePos( options.location.x, width, options.horizontalPos, dir ); if (left + width > window.innerWidth - 8) { if (options.alternateLocation) { left = getOppositeEffectivePos( options.alternateLocation.x, width, options.verticalPos, dir ); if (left + width > window.innerWidth - 8) left = void 0; } else left = void 0; } if (!Number.isFinite(left)) { left = Math.max(8, window.innerWidth - 8 - width); if (8 + width > window.innerWidth - 8) { element.style.right = "8px"; } } width = Math.min(left + width, window.innerWidth - 8) - left; if (dir === "rtl") { element.style.right = `${Math.ceil( window.innerWidth - left - width ).toString()}px`; } else element.style.left = `${Math.ceil(left).toString()}px`; element.style.top = `${Math.ceil(top).toString()}px`; if (height !== elementBounds.height) element.style.height = `${Math.ceil(height).toString()}px`; if (width !== elementBounds.width) element.style.width = `${Math.ceil(width).toString()}px`; } function distance2(p1, p2) { return Math.hypot(p2.x - p1.x, p2.y - p1.y); } // src/public/ui-menu-types.ts function isSubmenu(item) { return "submenu" in item; } function isCommand(item) { return "type" in item && item.type === "command" || "onMenuSelect" in item || "id" in item; } function isDivider(item) { return "type" in item && item.type === "divider"; } function isHeading(item) { return "type" in item && item.type === "heading"; } // src/ui/icons/icons.ts var ICON_CATALOG = {}; function icon(name) { let icon2 = ICON_CATALOG[name]; if (!icon2) { let markup; switch (name) { case "checkmark": markup = ``; break; case "trailing-chevron": markup = ``; break; case "mixedmark": markup = ''; } if (markup) { const template = document.createElement("template"); template.innerHTML = markup; ICON_CATALOG[name] = template; icon2 = template; } } if (icon2) { if ("content" in icon2) return icon2.content.cloneNode(true); const element = document.createElement("svg"); element.innerHTML = icon2.innerHTML; return element; } return void 0; } // src/ui/menu/menu-item.ts var BLINK_SPEED = 80; var _MenuItemState = class { constructor(declaration, parentMenu) { /** The DOM element the menu item is rendered as */ this._element = null; var _a3; this.parentMenu = parentMenu; this._declaration = declaration; if (isSubmenu(declaration)) { this.type = "submenu"; this.submenu = new _MenuListState(declaration.submenu, { parentMenu, submenuClass: declaration.submenuClass, columnCount: declaration.columnCount }); } else this.type = (_a3 = declaration.type) != null ? _a3 : "command"; this.hasCheck = isCommand(declaration) && declaration.checked !== void 0; } get rootMenu() { return this.parentMenu.rootMenu; } get abortController() { if (!this._abortController) this._abortController = new AbortController(); return this._abortController; } dispose() { var _a3, _b3; (_a3 = this._abortController) == null ? void 0 : _a3.abort(); this._abortController = void 0; (_b3 = this._element) == null ? void 0 : _b3.remove(); this._element = null; if (this.submenu) this.submenu.dispose(); this.submenu = void 0; } get menuItem() { return this._declaration; } get label() { var _a3; return (_a3 = this._label) != null ? _a3 : ""; } set label(value) { if (value === void 0) value = ""; if (value === this._label) return; this._label = value; this.dirty = true; } get visible() { return this._visible; } set visible(value) { if (value === this._visible) return; this._visible = value; this.dirty = true; } get enabled() { return this._enabled; } set enabled(value) { this._enabled = value; if (this.element) { if (value) this.element.removeAttribute("aria-disabled"); else this.element.setAttribute("aria-disabled", "true"); } this.dirty = true; } get checked() { return this._checked; } set checked(value) { this._checked = value; this.dirty = true; } get tooltip() { return this._tooltip; } set tooltip(value) { if (value === this._tooltip) return; this._tooltip = value; this.dirty = true; } get ariaLabel() { return this._ariaLabel; } set ariaLabel(value) { if (value === this._ariaLabel) return; this._ariaLabel = value; this.dirty = true; } get active() { var _a3, _b3; return (_b3 = (_a3 = this.element) == null ? void 0 : _a3.classList.contains("active")) != null ? _b3 : false; } set active(value) { if (!this.element) return; this.element.classList.toggle("active", value); } updateState(modifiers) { var _a3, _b3, _c2; const declaration = this._declaration; if (isDivider(declaration)) { this.enabled = false; this.checked = false; return; } if (isHeading(declaration)) { this.enabled = false; this.checked = false; this.visible = true; } if (isCommand(declaration)) { this.checked = isCommand(declaration) && ((_a3 = dynamicValue(declaration.checked, modifiers)) != null ? _a3 : false); } if (isCommand(declaration) || isSubmenu(declaration)) { this.enabled = (_b3 = dynamicValue(declaration.enabled, modifiers)) != null ? _b3 : true; this.visible = (_c2 = dynamicValue(declaration.visible, modifiers)) != null ? _c2 : true; if (this.visible && this.enabled && this.submenu) { this.submenu.updateState(modifiers); if (!this.submenu.visible) this.visible = false; } } if (isCommand(declaration) || isHeading(declaration) || isSubmenu(declaration)) { this.label = dynamicValue(declaration.label, modifiers); this.tooltip = dynamicValue(declaration.tooltip, modifiers); this.ariaLabel = dynamicValue(declaration.ariaLabel, modifiers); } if (this._element) this.updateElement(); } set dirty(value) { console.assert(value === true); if (value && this.parentMenu) this.parentMenu.dirty = true; } updateElement() { if (!this.visible || !this.element) return; const li = this.element; li.textContent = ""; if (!this.enabled) li.setAttribute("aria-disabled", "true"); else li.removeAttribute("aria-disabled"); if (this.checked === true) { li.setAttribute("aria-checked", "true"); li.append(icon("checkmark")); } else if (this.checked === "mixed") { li.setAttribute("aria-checked", "mixed"); li.append(icon("mixedmark")); } else li.removeAttribute("aria-checked"); if (this.ariaLabel) li.setAttribute("aria-label", this.ariaLabel); const span = document.createElement("span"); span.className = this.parentMenu.hasCheck ? "label indent" : "label"; if (this.type === "heading") span.classList.add("heading"); span.innerHTML = this.label; li.append(span); if (this._tooltip) { li.setAttribute("data-tooltip", this._tooltip); } if (isCommand(this._declaration) && this._declaration.keyboardShortcut) { const kbd = document.createElement("kbd"); kbd.innerHTML = getKeybindingMarkup(this._declaration.keyboardShortcut); li.append(kbd); } if (this.type === "submenu") li.append(icon("trailing-chevron")); } get element() { if (this._element) return this._element; if (isDivider(this._declaration)) { const li2 = document.createElement("li"); li2.setAttribute("part", "menu-divider"); li2.setAttribute("role", "divider"); this._element = li2; return li2; } const li = document.createElement("li"); this._element = li; if ((isCommand(this._declaration) || isHeading(this._declaration) || isSubmenu(this._declaration)) && this._declaration.class) li.className = this._declaration.class; li.setAttribute("part", "menu-item"); li.setAttribute("tabindex", "-1"); if (this.hasCheck) li.setAttribute("role", "menuitemcheckbox"); else li.setAttribute("role", "menuitem"); if (this.type === "submenu") { li.setAttribute("aria-haspopup", "true"); li.setAttribute("aria-expanded", "false"); } const signal = this.abortController.signal; li.addEventListener("pointerenter", this, { signal }); li.addEventListener("pointerleave", this, { signal }); li.addEventListener("pointerup", this, { signal }); li.addEventListener("click", this, { signal }); return this._element; } /** Dispatch a `menu-select` event, and call the * `onMenuSelect()` hook if defined. */ dispatchSelect() { if (!isCommand(this._declaration)) return; const ev = new CustomEvent("menu-select", { cancelable: true, bubbles: true, detail: { modifiers: this.rootMenu.modifiers, id: this._declaration.id, data: this._declaration.data } }); const notCanceled = this.parentMenu.dispatchEvent(ev); if (notCanceled && typeof this._declaration.onMenuSelect === "function") { this._declaration.onMenuSelect({ modifiers: this.rootMenu.modifiers, id: this._declaration.id, data: this._declaration.data }); } } handleEvent(event) { var _a3; if (!this.visible || !this.enabled) return; if (event.type === "click") { if (this.rootMenu.state === "modal") this.select(); event.stopPropagation(); event.preventDefault(); return; } if (event.type === "pointerenter") { const ev = event; this.rootMenu.cancelDelayedOperation(); if (this.parentMenu.isSubmenuOpen && ((_a3 = this.parentMenu.activeMenuItem) == null ? void 0 : _a3.movingTowardSubmenu(ev))) { this.rootMenu.scheduleOperation(() => { this.parentMenu.activeMenuItem = this; this.openSubmenu(); }); } else { this.parentMenu.activeMenuItem = this; this.openSubmenu({ withDelay: true }); } return; } if (event.type === "pointerleave") { if (this.rootMenu.activeSubmenu === this.parentMenu) this.parentMenu.activeMenuItem = null; return; } if (event.type === "pointerup") { if (this.rootMenu.state !== "modal") this.select(); event.stopPropagation(); event.preventDefault(); return; } } /** * Called when a menu item is selected: * - either dismiss the menu and execute the command * - or display the submenu */ select() { this.rootMenu.cancelDelayedOperation(); if (this.type === "submenu") { this.openSubmenu(); return; } this.active = false; setTimeout(() => { this.active = true; setTimeout(() => { this.rootMenu.hide(); this.dispatchSelect(); }, BLINK_SPEED); }, BLINK_SPEED); } /** * Open the submenu of this menu item, with a delay if options.delay * This delay improves targeting of submenus with the mouse. */ openSubmenu(options) { var _a3; if (this.type !== "submenu" || !this.element) return; if ((_a3 = options == null ? void 0 : options.withDelay) != null ? _a3 : false) { this.rootMenu.scheduleOperation(() => this.openSubmenu()); return; } const bounds = this.element.getBoundingClientRect(); const dir = getComputedDir(this.element); this.submenu.show({ container: this.rootMenu.element.parentNode, location: { x: getEdge(bounds, "trailing", dir), y: bounds.top - 4 }, alternateLocation: { x: getEdge(bounds, "leading", dir), y: bounds.top - 4 } }); } movingTowardSubmenu(ev) { if (!this.element) return false; if (this.type !== "submenu") return false; const lastEv = this.rootMenu.lastMoveEvent; if (!lastEv) return false; const deltaT = ev.timeStamp - lastEv.timeStamp; if (deltaT > 500) return false; const deltaX = ev.clientX - lastEv.clientX; const s = speed(deltaX, lastEv.clientY - ev.clientY, deltaT); if (s <= 0.2) return false; let position = "right"; if (this.submenu.element) { const submenuBounds = this.submenu.element.getBoundingClientRect(); const bounds = this.element.getBoundingClientRect(); if (submenuBounds.left < bounds.left + bounds.width / 2) position = "left"; } return position === "right" ? deltaX > 0 : deltaX < 0; } }; function speed(dx, dy, dt) { return Math.hypot(dx, dy) / dt; } function dynamicValue(value, modifiers) { if (value === void 0 || typeof value !== "function") return value; modifiers != null ? modifiers : modifiers = { alt: false, control: false, shift: false, meta: false }; return value(modifiers); } // src/ui/menu/menu-list.ts var _MenuListState = class __MenuListState { constructor(items, options) { this._element = null; this._activeMenuItem = null; this._dirty = true; var _a3, _b3; this.parentMenu = (_a3 = options == null ? void 0 : options.parentMenu) != null ? _a3 : null; this._submenuClass = options == null ? void 0 : options.submenuClass; this.columnCount = (_b3 = options == null ? void 0 : options.columnCount) != null ? _b3 : 1; this.isSubmenuOpen = false; this.menuItems = items; } get children() { return this._menuItems; } /** Setting the menu items will reset this item and * redefine a set of _MenuItem objects */ set menuItems(items) { const parent = this.parentMenu; this.dispose(); this.parentMenu = parent; items = [...items]; this._menuItems = items.map( (x) => x["onCreate"] ? x["onCreate"](x, this) : new _MenuItemState(x, this) ); this.hasCheck = void 0; this.dirty = true; } dispose() { var _a3; this.hide(); if (this._element) this._element.remove(); if (this._abortController) this._abortController.abort(); (_a3 = this._menuItems) == null ? void 0 : _a3.forEach((x) => x.dispose()); this._menuItems = []; this._activeMenuItem = null; this.parentMenu = null; } handleEvent(event) { if (event.type === "wheel" && this._element) { const ev = event; this._element.scrollBy(0, ev.deltaY); event.stopPropagation(); } } dispatchEvent(ev) { return this.rootMenu.dispatchEvent(ev); } get rootMenu() { return this.parentMenu.rootMenu; } /** * Update the 'model' of this menu (i.e. list of menu items) */ updateState(modifiers) { var _a3, _b3, _c2; this._menuItems.forEach((x) => x.updateState(modifiers)); const previousHasCheck = this.hasCheck; this.hasCheck = this._menuItems.some((x) => x.visible && x.hasCheck); if (this.hasCheck !== previousHasCheck) { this._menuItems.forEach((x) => x.updateState(modifiers)); } let heading = void 0; let itemInHeadingCount = 0; for (const item of this._menuItems) { if (item.type === "heading") { if (heading && itemInHeadingCount === 0) heading.visible = false; heading = item; itemInHeadingCount = 0; } else if (item.type === "divider" && heading) { heading.visible = itemInHeadingCount > 0; heading = void 0; itemInHeadingCount = 0; } else if (heading && item.visible) itemInHeadingCount += 1; } if (heading) heading.visible = itemInHeadingCount > 0; let wasDivider = true; for (const item of this._menuItems) { if (item.type === "divider") { item.visible = !wasDivider; wasDivider = true; } else if (item.visible) wasDivider = false; } if (!((_a3 = this.activeMenuItem) == null ? void 0 : _a3.visible)) this.activeMenuItem = null; if (!((_b3 = this.activeMenuItem) == null ? void 0 : _b3.enabled) && ((_c2 = this.activeMenuItem) == null ? void 0 : _c2.type) === "submenu") this._activeMenuItem.submenu.hide(); this._dirty = false; } get enabled() { this.updateIfDirty(); return this._menuItems.some( (x) => x.type !== "divider" && x.visible && x.enabled ); } get visible() { this.updateIfDirty(); return this._menuItems.some((x) => x.type !== "divider" && x.visible); } set dirty(value) { console.assert(value === true); if (this._dirty === value) return; if (value && this.parentMenu) { this._dirty = true; this.parentMenu.dirty = true; } } updateIfDirty() { if (this._dirty) this.updateState(this.rootMenu.modifiers); } /** If the element has been created, update its content to reflect * the current state of the menu items */ updateElement() { var _a3; if (!this._element) return; this._element.textContent = ""; for (const { element, visible } of this._menuItems) if (element && visible) this._element.append(element); (_a3 = this._element.querySelector("li:first-of-type")) == null ? void 0 : _a3.setAttribute("tabindex", "0"); } /** * Construct (or return a cached version) of an element representing * the items in this menu (model -> view) */ get element() { if (this._element) return this._element; const menu = document.createElement("menu"); menu.setAttribute("role", "menu"); menu.setAttribute("tabindex", "-1"); menu.setAttribute("aria-orientation", "vertical"); menu.setAttribute("part", "ui-menu-container"); if (this._submenuClass) menu.classList.add(this._submenuClass); menu.classList.add("ui-menu-container"); if (!this._abortController) this._abortController = new AbortController(); const signal = this._abortController.signal; menu.addEventListener("focus", this, { signal }); menu.addEventListener("wheel", this, { passive: true, signal }); this._element = menu; this.updateElement(); return menu; } /** * The active menu is displayed on a colored background. */ get activeMenuItem() { return this._activeMenuItem; } /** * Set to null to have no active item. * Note that setting the active menu item doesn't automatically * open the submenu (e.g. when keyboard navigating). * Call `item.submenu.openSubmenu()` to open the submenu. */ set activeMenuItem(value) { var _a3, _b3, _c2, _d2; this.rootMenu.cancelDelayedOperation(); if (value !== this._activeMenuItem) { if (this.activeMenuItem) { const item = this.activeMenuItem; item.active = false; (_a3 = item.submenu) == null ? void 0 : _a3.hide(); } if (!((_b3 = value == null ? void 0 : value.visible) != null ? _b3 : true)) { this._activeMenuItem = null; return; } this._activeMenuItem = value; if (value) value.active = true; } if (value) (_c2 = value.element) == null ? void 0 : _c2.focus({ preventScroll: true }); else (_d2 = this._element) == null ? void 0 : _d2.focus({ preventScroll: true }); } /** First activable menu item */ get firstMenuItem() { this.updateIfDirty(); let result = 0; let found = false; const menuItems = this._menuItems; while (!found && result <= menuItems.length - 1) { const item = menuItems[result]; found = item.type !== "divider" && item.visible && item.enabled; result += 1; } return found ? menuItems[result - 1] : null; } /** Last activable menu item */ get lastMenuItem() { this.updateIfDirty(); const menuItems = this._menuItems; let result = menuItems.length - 1; let found = false; while (!found && result >= 0) { const item = menuItems[result]; found = item.type !== "divider" && item.visible && item.enabled; result -= 1; } return found ? menuItems[result + 1] : null; } nextMenuItem(stride) { if (stride === 0) return this._activeMenuItem; if (!this._activeMenuItem) return stride > 0 ? this.firstMenuItem : this.lastMenuItem; if (!this.firstMenuItem || !this.lastMenuItem || !this._activeMenuItem) return null; this.updateIfDirty(); const first = this._menuItems.indexOf(this.firstMenuItem); const last = this._menuItems.indexOf(this.lastMenuItem); let index = this._menuItems.indexOf(this._activeMenuItem); let count = 1; while (index >= first && index <= last) { index += stride > 0 ? 1 : -1; const item = this._menuItems[index]; if (!item) break; if (item.visible && item.enabled) { if (count === Math.abs(stride)) return this._menuItems[index]; count += 1; } } return stride > 0 ? this.lastMenuItem : this.firstMenuItem; } getMenuItemColumn(menu) { this.updateIfDirty(); const visibleItems = this._menuItems.filter((x) => x.visible && x.enabled); const index = visibleItems.indexOf(menu); if (index < 0) return -1; return index % this.columnCount; } static get collator() { if (__MenuListState._collator) return __MenuListState._collator; __MenuListState._collator = new Intl.Collator(void 0, { usage: "search", sensitivity: "base" }); return __MenuListState._collator; } findMenuItem(text) { var _a3; this.updateIfDirty(); const candidates = this._menuItems.filter( (x) => x.type !== "divider" && x.visible && x.enabled ); if (candidates.length === 0) return null; const last = Math.max(...candidates.map((x) => x.label.length)) - text.length; if (last < 0) return null; let result = null; let i = 0; while (i < last && !result) { result = (_a3 = candidates.find( (x) => __MenuListState.collator.compare( text, x.label.substring(i, text.length) ) === 0 )) != null ? _a3 : null; i++; } return result; } /** * @param location: in viewport coordinates * @param alternateLocation: in viewport coordinates * @param container: where the menu should be attached * @return false if no menu to show */ show(options) { if (!this.visible || !options.container) return false; this.updateElement(); options.container.appendChild(this.element); if (supportPopover()) { this.element.popover = "manual"; this.element.showPopover(); } if (options.location) { fitInViewport(this.element, { location: options.location, alternateLocation: options.alternateLocation, verticalPos: "bottom", horizontalPos: "start" }); } this.element.focus({ preventScroll: true }); if (this.parentMenu) this.parentMenu.openSubmenu = this; return true; } hide() { var _a3, _b3, _c2, _d2, _e; this.openSubmenu = null; this.activeMenuItem = null; if (this.parentMenu) this.parentMenu.openSubmenu = null; if (supportPopover() && ((_a3 = this._element) == null ? void 0 : _a3.popover)) this.element.hidePopover(); (_c2 = (_b3 = this.parentMenu) == null ? void 0 : _b3.element) == null ? void 0 : _c2.focus(); (_e = (_d2 = this._element) == null ? void 0 : _d2.parentNode) == null ? void 0 : _e.removeChild(this._element); } /** * This method is called to record that one of our submenus has opened. * To open a submenu call openSubmenu() on the item with the submenu * or show() on the submenu. */ set openSubmenu(submenu) { var _a3, _b3, _c2, _d2; const expanded = submenu !== null; if (((_a3 = this.activeMenuItem) == null ? void 0 : _a3.type) === "submenu") { (_b3 = this.activeMenuItem.element) == null ? void 0 : _b3.setAttribute( "aria-expanded", expanded.toString() ); } (_d2 = (_c2 = this.activeMenuItem) == null ? void 0 : _c2.element) == null ? void 0 : _d2.classList.toggle("is-submenu-open", expanded); this.isSubmenuOpen = expanded; } }; // src/ui/menu/menu.ts var _Menu = class _Menu extends _MenuListState { /** * The host is the element that the events will be dispatched from * */ constructor(menuItems, options) { var _a3; super(menuItems); /** * - 'closed': the menu is not visible * - 'open': the menu is visible as long as the mouse button is pressed * - 'modal': the menu is visible until dismissed, even with * the mouse button released */ this.state = "closed"; this.typingBufferResetTimer = 0; this.hysteresisTimer = 0; this._updating = false; this._host = (_a3 = options == null ? void 0 : options.host) != null ? _a3 : null; this.isDynamic = menuItems.some(isDynamic); this._modifiers = { shift: false, control: false, alt: false, meta: false }; this.typingBuffer = ""; this.state = "closed"; } get modifiers() { return this._modifiers; } set modifiers(value) { if (equalKeyboardModifiers(this._modifiers, value)) return; this._modifiers = value; this.dirty = true; } /** * The currently active menu: could be the root menu or a submenu */ get activeSubmenu() { let result = this; while (result.isSubmenuOpen) result = result.activeMenuItem.submenu; return result; } set dirty(value) { if (this._updating) return; console.assert(value === true); if (this._dirty === value) return; this._dirty = true; if (value) { setTimeout(() => { this.updateState(this.modifiers); this.updateElement(); }); } } updateState(modifiers) { this._updating = true; this.modifiers = modifiers != null ? modifiers : this.modifiers; super.updateState(this.modifiers); this._updating = false; } handleKeyupEvent(ev) { if (this.isDynamic) this.modifiers = keyboardModifiersFromEvent(ev); ev.stopImmediatePropagation(); } handleKeydownEvent(ev) { var _a3, _b3, _c2; if (ev.key === "Tab" || ev.key === "Escape") { this.hide(); return; } if (this.isDynamic) this.modifiers = keyboardModifiersFromEvent(ev); let handled = true; const menu = this.activeSubmenu; const menuItem = menu.activeMenuItem; switch (ev.key) { case " ": case "Space": case "Return": case "Enter": menuItem == null ? void 0 : menuItem.select(keyboardModifiersFromEvent(ev)); break; case "ArrowRight": if ((menuItem == null ? void 0 : menuItem.type) === "submenu") { menuItem.select(keyboardModifiersFromEvent(ev)); this.activeSubmenu.activeMenuItem = this.activeSubmenu.firstMenuItem; } else if (!menuItem) menu.activeMenuItem = menu.firstMenuItem; else { const col = (_a3 = menu.getMenuItemColumn(menuItem)) != null ? _a3 : -1; if (col >= 0 && col < ((_b3 = menu.columnCount) != null ? _b3 : 1) - 1) { const next = menu.nextMenuItem(1); if (next) menu.activeMenuItem = next; } } break; case "ArrowLeft": if (menu === this.rootMenu) { if (!menuItem) menu.activeMenuItem = menu.firstMenuItem; } else { const col = menuItem ? (_c2 = menu.getMenuItemColumn(menuItem)) != null ? _c2 : -1 : -1; if (col <= 0 || !menuItem) { menu.hide(); const activeMenu = menu.parentMenu.activeMenuItem; if (activeMenu) { const { element } = activeMenu; element == null ? void 0 : element.focus(); element == null ? void 0 : element.classList.remove("is-submenu-open"); } } else { const next = menu.nextMenuItem(-1); if (next) menu.activeMenuItem = next; } } break; case "ArrowDown": menu.activeMenuItem = menu.nextMenuItem(menu.columnCount); break; case "ArrowUp": menu.activeMenuItem = menu.nextMenuItem(-menu.columnCount); break; case "Home": case "PageUp": menu.activeMenuItem = menu.firstMenuItem; break; case "End": case "PageDown": menu.activeMenuItem = menu.lastMenuItem; break; case "Backspace": if (this.typingBuffer) { this.typingBuffer = this.typingBuffer.slice(0, -1); if (this.typingBuffer) { clearTimeout(this.typingBufferResetTimer); const newItem = menu.findMenuItem(this.typingBuffer); if (newItem) menu.activeMenuItem = newItem; this.typingBufferResetTimer = setTimeout(() => { this.typingBuffer = ""; }, 500); } } break; default: if (mightProducePrintableCharacter(ev)) { if (isFinite(this.typingBufferResetTimer)) clearTimeout(this.typingBufferResetTimer); this.typingBuffer += ev.key; const newItem = menu.findMenuItem(this.typingBuffer); if (newItem) menu.activeMenuItem = newItem; this.typingBufferResetTimer = setTimeout(() => { this.typingBuffer = ""; }, 500); } else handled = false; } if (handled) { ev.preventDefault(); ev.stopPropagation(); } } handleEvent(event) { if (event.type === "keydown") this.handleKeydownEvent(event); else if (event.type === "keyup") this.handleKeyupEvent(event); else if (event.type === "pointermove") this.lastMoveEvent = event; else if (event.type === "pointerup" && event.target === this.scrim) { if (Number.isFinite(this.rootMenu._openTimestamp) && Date.now() - this.rootMenu._openTimestamp < 120) { this.state = "modal"; } else if (this.state === "modal") { this.hide(); } } else if (event.type === "contextmenu") { event.preventDefault(); event.stopPropagation(); return; } super.handleEvent(event); } /** Return true if the event is **not** canceled */ dispatchEvent(ev) { if (!this._host) return true; return this._host.dispatchEvent(ev); } get scrim() { return Scrim.element; } connectScrim(target) { const scrim = this.scrim; scrim.addEventListener("pointerup", this); scrim.addEventListener("contextmenu", this); scrim.addEventListener("keydown", this); scrim.addEventListener("keyup", this); scrim.addEventListener("pointermove", this); Scrim.open({ root: target, onDismiss: () => this.hide() }); } disconnectScrim() { const scrim = this.scrim; scrim.removeEventListener("pointerup", this); scrim.removeEventListener("contextmenu", this); scrim.removeEventListener("keydown", this); scrim.removeEventListener("keyup", this); scrim.removeEventListener("pointermove", this); if (Scrim.state === "open") Scrim.scrim.close(); } get rootMenu() { return this; } /** Locations are in viewport coordinate. */ show(options) { this._onDismiss = options == null ? void 0 : options.onDismiss; if (options == null ? void 0 : options.modifiers) this.modifiers = options.modifiers; this.updateState(); this.connectScrim(options == null ? void 0 : options.target); if (!super.show(__spreadProps(__spreadValues({}, options), { container: this.scrim }))) { this.disconnectScrim(); return false; } this._openTimestamp = Date.now(); this.state = "open"; return true; } hide() { this.cancelDelayedOperation(); if (this.state !== void 0) { if (this.state !== "closed") { this.activeMenuItem = null; Scrim.element.parentElement.focus(); super.hide(); this.state = "closed"; this.disconnectScrim(); } if (this._onDismiss) { this._onDismiss(); this._onDismiss = void 0; } } } scheduleOperation(fn) { this.cancelDelayedOperation(); const delay = _Menu.SUBMENU_DELAY; if (delay <= 0) { fn(); return; } this.hysteresisTimer = setTimeout(() => { this.hysteresisTimer = 0; fn(); }, delay); } cancelDelayedOperation() { if (this.hysteresisTimer) { clearTimeout(this.hysteresisTimer); this.hysteresisTimer = 0; } } }; /** * Delay (in milliseconds) before displaying a submenu. * * Prevents distracting flashing of submenus when moving quickly * through the options in a menu. */ _Menu.SUBMENU_DELAY = 120; var Menu = _Menu; function isDynamic(item) { if (isDivider(item)) return false; if (typeof item.label === "function" || typeof item.ariaLabel === "function" || typeof item.tooltip === "function") return true; if ((isCommand(item) || isSubmenu(item)) && (typeof item.enabled === "function" || typeof item.visible === "function")) return true; if (isCommand(item) && typeof item.checked === "function") return true; if (isSubmenu(item)) return item.submenu.some(isDynamic); return false; } // src/ui/events/longpress.ts var LongPress = class { // Maximum distance between the start and end of the gesture, in pixels }; LongPress.DELAY = 300; // Amount of time before showing the context menu, in ms LongPress.MAX_DISTANCE = 10; function onLongPress(triggerEvent) { return new Promise((resolve, _reject) => { const startPoint = eventLocation(triggerEvent); if (!startPoint) resolve(false); let lastPoint = startPoint; const timer = setTimeout(() => { controller.abort(); resolve(distance2(lastPoint, startPoint) < LongPress.MAX_DISTANCE); }, LongPress.DELAY); const controller = new AbortController(); const signal = controller.signal; for (const eventType of ["pointermove", "pointerup", "pointercancel"]) { window.addEventListener( eventType, (evt) => { if (evt.type === "pointerup" || evt.type === "pointercancel") { clearTimeout(timer); controller.abort(); resolve(false); } else if (evt.type === "pointermove") { const location = eventLocation(evt); if (location) lastPoint = location; } }, { passive: true, signal } ); } }); } // src/ui/menu/context-menu.ts async function onContextMenu(event, target, menu) { if (event.type === "contextmenu") { const evt = event; if (menu.show({ target, location: eventLocation(evt), modifiers: keyboardModifiersFromEvent(evt) })) { event.preventDefault(); event.stopPropagation(); return true; } } if (event.type === "keydown") { const evt = event; if (evt.code === "ContextMenu" || evt.code === "F10" && evt.shiftKey) { const bounds = target == null ? void 0 : target.getBoundingClientRect(); if (bounds && menu.show({ target, location: { x: Math.ceil(bounds.left + bounds.width / 2), y: Math.ceil(bounds.top + bounds.height / 2) }, modifiers: keyboardModifiersFromEvent(evt) })) { event.preventDefault(); event.stopPropagation(); return true; } } } if (event.type === "pointerdown" && event.pointerType !== "mouse" && event.button === 0) { let eventTarget = event.target; while (eventTarget && target !== eventTarget) eventTarget = eventTarget.parentNode; if (!eventTarget) return false; if (!menu.visible) return false; const location = eventLocation(event); if (await onLongPress(event)) { if (menu.state !== "closed") return false; menu.show({ target, location }); return true; } } return false; } // src/latex-commands/accents.ts var ACCENTS = { acute: 714, grave: 715, dot: 729, ddot: 168, mathring: 730, tilde: 126, bar: 713, breve: 728, check: 711, hat: 94, vec: 8407 }; defineFunction(Object.keys(ACCENTS), "{body:auto}", { createAtom: (options) => new AccentAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), accentChar: ACCENTS[options.command.slice(1)] })) }); defineFunction(["widehat", "widecheck", "widetilde"], "{body:auto}", { createAtom: (options) => { const baseString = parseArgAsString(argAtoms(options.args[0])); return new AccentAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), svgAccent: options.command.slice(1) + (baseString.length > 5 ? "4" : ["1", "1", "2", "2", "3", "3"][baseString.length]) })); } }); defineFunction(["overarc", "overparen", "wideparen"], "{body:auto}", { createAtom: (options) => { return new AccentAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), svgAccent: "overarc" })); } }); defineFunction(["underarc", "underparen"], "{body:auto}", { createAtom: (options) => { return new OverunderAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), svgBelow: "underarc" })); } }); defineFunction("utilde", "{body:auto}", { createAtom: (options) => { const body = argAtoms(options.args[0]); const baseString = parseArgAsString(body); const accent = "widetilde" + (baseString.length > 5 ? "4" : ["1", "1", "2", "2", "3", "3"][baseString.length]); return new OverunderAtom(__spreadProps(__spreadValues({}, options), { body, svgBelow: accent, boxType: atomsBoxType(body) })); } }); defineFunction("^", "{:string}", { createAtom: (options) => { var _a3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: options.args[0] ? (_a3 = { a: "\xE2", e: "\xEA", i: "\xEE", o: "\xF4", u: "\xFB", A: "\xC2", E: "\xCA", I: "\xCE", O: "\xD4", U: "\xDB" }[options.args[0]]) != null ? _a3 : "^" : "^" })); } }); defineFunction("`", "{:string}", { createAtom: (options) => { var _a3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: options.args[0] ? (_a3 = { a: "\xE0", e: "\xE8", i: "\xEC", o: "\xF2", u: "\xF9", A: "\xC0", E: "\xC8", I: "\xCC", O: "\xD2", U: "\xD9" }[options.args[0]]) != null ? _a3 : "`" : "`" })); } }); defineFunction("'", "{:string}", { createAtom: (options) => { var _a3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: options.args[0] ? (_a3 = { a: "\xE1", e: "\xE9", i: "\xED", o: "\xF3", u: "\xFA", A: "\xC1", E: "\xC9", I: "\xCD", O: "\xD3", U: "\xDA" }[options.args[0]]) != null ? _a3 : "'" : "'" })); } }); defineFunction('"', "{:string}", { createAtom: (options) => { var _a3, _b3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: ((_a3 = options.args) == null ? void 0 : _a3[0]) ? (_b3 = { a: "\xE4", e: "\xEB", i: "\xEF", o: "\xF6", u: "\xFC", A: "\xC4", E: "\xCB", I: "\xCB", O: "\xD6", U: "\xDC" }[options.args[0]]) != null ? _b3 : '"' + options.args[0] : '"' })); } }); defineFunction(".", "{:string}", { createAtom: (options) => { var _a3, _b3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: ((_a3 = options.args) == null ? void 0 : _a3[0]) ? (_b3 = { // a with single dot above a: "\u0227", e: "\u0117", // i with single dot above (combining character) i: "\u0307i", o: "\u022F", // U with single dot above (combining character) u: "\u0307u", A: "\u0226", E: "\u0116", I: "\u0130", O: "\u022E", // U with single dot above (combining character) U: "\u0307U" }[options.args[0]]) != null ? _b3 : "." + options.args[0] : "." })); } }); defineFunction("=", "{:string}", { createAtom: (options) => { var _a3, _b3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: ((_a3 = options.args) == null ? void 0 : _a3[0]) ? (_b3 = { // a with macron a: "\u0101", e: "\u0113", i: "\u012B", o: "\u014D", u: "\u016B", A: "\u0100", E: "\u0112", I: "\u012A", O: "\u014C", U: "\u016A" }[options.args[0]]) != null ? _b3 : "=" + options.args[0] : "=" // fallback })); } }); defineFunction("~", "{:string}", { createAtom: (options) => { var _a3; return new Atom(__spreadProps(__spreadValues({ type: "mord" }, options), { isFunction: false, limits: "adjacent", value: options.args[0] ? (_a3 = { n: "\xF1", N: "\xD1", a: "\xE3", o: "\xF5", A: "\xC3", O: "\xD5" }[options.args[0]]) != null ? _a3 : "\xB4" : "\xB4" })); } }); defineFunction("c", "{:string}", { createAtom: (options) => { var _a3; return new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", isFunction: false, limits: "adjacent", value: options.args[0] ? (_a3 = { c: "\xE7", C: "\xC7" }[options.args[0]]) != null ? _a3 : "" : "" })); } }); // src/latex-commands/enclose.ts defineFunction("enclose", "{notation:string}[style:string]{body:auto}", { createAtom: (atomOptions) => { var _a3, _b3; const args = atomOptions.args; const options = { strokeColor: "currentColor", strokeWidth: "", strokeStyle: "solid", backgroundcolor: "transparent", padding: "auto", shadow: "none", svgStrokeStyle: void 0, borderStyle: void 0, style: (_a3 = atomOptions.style) != null ? _a3 : {} }; if (args[1]) { const styles = args[1].split(/,(?![^(]*\)(?:(?:[^(]*\)){2})*[^"]*$)/); for (const s of styles) { const shorthand = s.match(/\s*(\S+)\s+(\S+)\s+(.*)/); if (shorthand) { options.strokeWidth = shorthand[1]; options.strokeStyle = shorthand[2]; options.strokeColor = shorthand[3]; } else { const attribute = s.match(/\s*([a-z]*)\s*=\s*"(.*)"/); if (attribute) { if (attribute[1] === "mathbackground") options.backgroundcolor = attribute[2]; else if (attribute[1] === "mathcolor") options.strokeColor = attribute[2]; else if (attribute[1] === "padding") options.padding = attribute[2]; else if (attribute[1] === "shadow") options.shadow = attribute[2]; } } } if (options.strokeStyle === "dashed") options.svgStrokeStyle = "5,5"; else if (options.strokeStyle === "dotted") options.svgStrokeStyle = "1,5"; } options.borderStyle = `${options.strokeWidth} ${options.strokeStyle} ${options.strokeColor}`; const notation = {}; ((_b3 = args[0]) != null ? _b3 : "").split(/[, ]/).filter((v) => v.length > 0).forEach((x) => { notation[x.toLowerCase()] = true; }); return new EncloseAtom( atomOptions.command, argAtoms(args[2]), notation, options ); } }); defineFunction("cancel", "{body:auto}", { createAtom: (options) => { var _a3; return new EncloseAtom( options.command, argAtoms(options.args[0]), { updiagonalstrike: true }, { strokeColor: "currentColor", strokeWidth: "", strokeStyle: "solid", borderStyle: "1px solid currentColor", backgroundcolor: "transparent", padding: "auto", shadow: "none", style: (_a3 = options.style) != null ? _a3 : {} } ); } }); defineFunction("bcancel", "{body:auto}", { createAtom: (options) => { var _a3; return new EncloseAtom( options.command, argAtoms(options.args[0]), { downdiagonalstrike: true }, { strokeColor: "currentColor", strokeWidth: "", strokeStyle: "solid", borderStyle: "1px solid currentColor", backgroundcolor: "transparent", padding: "auto", shadow: "none", style: (_a3 = options.style) != null ? _a3 : {} } ); } }); defineFunction("xcancel", "{body:auto}", { createAtom: (options) => { var _a3; return new EncloseAtom( options.command, argAtoms(options.args[0]), { updiagonalstrike: true, downdiagonalstrike: true }, { strokeColor: "currentColor", strokeWidth: "", strokeStyle: "solid", borderStyle: "1px solid currentColor", backgroundcolor: "transparent", padding: "auto", shadow: "none", style: (_a3 = options.style) != null ? _a3 : {} } ); } }); // src/latex-commands/extensible-symbols.ts defineFunction( [ "overrightarrow", "overleftarrow", "Overrightarrow", "overleftharpoon", "overrightharpoon", "overleftrightarrow", "overlinesegment", "overgroup" ], "{:auto}", { createAtom: (options) => { var _a3; return new OverunderAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms((_a3 = options.args) == null ? void 0 : _a3[0]), skipBoundary: false, supsubPlacement: "over-under", paddedBody: true, boxType: "rel", // Set the "svgAbove" to the name of a SVG object (which is the same // as the command name) svgAbove: options.command.slice(1) })); } } ); defineFunction("overbrace", "{:auto}", { createAtom: (options) => new OverunderAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), skipBoundary: false, supsubPlacement: "over-under", paddedBody: true, boxType: "ord", svgAbove: options.command.slice(1) })) }); defineFunction( [ "underrightarrow", "underleftarrow", "underleftrightarrow", "underlinesegment", "undergroup" ], "{:auto}", { createAtom: (options) => new OverunderAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), skipBoundary: false, supsubPlacement: "over-under", paddedBody: true, boxType: "rel", // Set the "svgBelow" to the name of a SVG object (which is the same // as the command name) svgBelow: options.command.slice(1) })) } ); defineFunction(["underbrace"], "{:auto}", { createAtom: (options) => new OverunderAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), skipBoundary: false, supsubPlacement: "over-under", paddedBody: true, boxType: "ord", svgBelow: options.command.slice(1) })) }); defineFunction( [ "xrightarrow", "longrightarrow", // From mhchem.sty package "xleftarrow", "longleftarrow", // From mhchem.sty package "xRightarrow", "xLeftarrow", "xleftharpoonup", "xleftharpoondown", "xrightharpoonup", "xrightharpoondown", "xlongequal", "xtwoheadleftarrow", "xtwoheadrightarrow", "xleftrightarrow", "longleftrightarrow", // From mhchem.sty package "xLeftrightarrow", "xrightleftharpoons", // From mhchem.sty package "longrightleftharpoons", "xleftrightharpoons", "xhookleftarrow", "xhookrightarrow", "xmapsto", "xtofrom", "xleftrightarrows", // From mhchem.sty package "longleftrightarrows", // From mhchem.sty package "xRightleftharpoons", // From mhchem.sty package "longRightleftharpoons", // From mhchem.sty package "xLeftrightharpoons", // From mhchem.sty package "longLeftrightharpoons" // From mhchem.sty package ], "[:auto]{:auto}", { createAtom: (options) => { var _a3, _b3, _c2, _d2, _e; return new OverunderAtom(__spreadProps(__spreadValues({}, options), { // Set the "svgBody" to the name of a SVG object (which is the same // as the command name) svgBody: options.command.slice(1), // The overscript is optional, i.e. `\xtofrom` is valid above: ((_b3 = argAtoms((_a3 = options.args) == null ? void 0 : _a3[1])) == null ? void 0 : _b3.length) === 0 ? void 0 : argAtoms((_c2 = options.args) == null ? void 0 : _c2[1]), below: (_e = argAtoms((_d2 = options.args) == null ? void 0 : _d2[0])) != null ? _e : null, skipBoundary: false, supsubPlacement: "over-under", paddedBody: true, paddedLabels: true, boxType: "rel" })); }, serialize: (atom, options) => atom.command + (!atom.hasEmptyBranch("below") ? `[${atom.belowToLatex(options)}]` : "") + `{${atom.aboveToLatex(options)}}${atom.supsubToLatex(options)}` } ); // src/latex-commands/functions.ts defineFunction( [ "arccos", "arcsin", "arctan", "arctg", // Not LaTeX standard. Used in France "arcctg", // Not LaTeX standard. Used in France "arg", "ch", // Not LaTeX standard. \cosh "cos", "cosh", "cot", "cotg", // Not LaTeX standard. Used in France "coth", "ctg", // Not LaTeX standard. Used in France "cth", "csc", // Not LaTeX standard. \cth "cosec", // Not LaTeX standard. "deg", "dim", "exp", "gcd", "hom", "inf", "ker", "lb", // Not LaTeX standard. US Dept of Commerce recommendation for log2 "lg", // Not LaTeX standard. In German and Russian literature, log10. // Sometimes used as the log2 "ln", "log", "Pr", "sec", "sh", // Not LaTeX standard. \sinh "sin", "sinh", "sup", "tan", "tanh", "tg", // Not LaTeX standard. Used in France "th", // Not LaTeX standard. \tanh "arcsec", "arccsc", "arsinh", "arcosh", "artanh", "arcsech", "arccsch" ], "", { isFunction: true, ifMode: "math", createAtom: (options) => new OperatorAtom(options.command.slice(1), __spreadProps(__spreadValues({}, options), { limits: "adjacent", isFunction: true, variant: "main", variantStyle: "up" })) } ); defineFunction(["liminf", "limsup"], "", { ifMode: "math", createAtom: (options) => new OperatorAtom( { "\\liminf": "lim inf", "\\limsup": "lim sup" }[options.command], __spreadProps(__spreadValues({}, options), { limits: "over-under", variant: "main" }) ) }); defineFunction(["lim", "mod"], "", { ifMode: "math", createAtom: (options) => new OperatorAtom(options.command.slice(1), __spreadProps(__spreadValues({}, options), { limits: "over-under", variant: "main" })) }); defineFunction(["det", "max", "min"], "", { ifMode: "math", isFunction: true, createAtom: (options) => new OperatorAtom(options.command.slice(1), __spreadProps(__spreadValues({}, options), { limits: "over-under", isFunction: true, variant: "main" })) }); defineFunction(["ang"], "{:math}", { ifMode: "math", createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), serialize: (atom, options) => `\\ang{${atom.bodyToLatex(options)}}`, render: (atom, context) => { const box = atom.createBox(context); const caret = box.caret; box.caret = void 0; const deg = new Box("\xB0", { style: __spreadProps(__spreadValues({}, atom.style), { variant: "normal", variantStyle: "up" }) }); return new Box([box, deg], { type: "inner", isSelected: atom.isSelected, caret }); } }); defineFunction("sqrt", "[index:auto]{radicand:expression}", { ifMode: "math", createAtom: (options) => new SurdAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]), index: options.args[0] ? argAtoms(options.args[0]) : void 0 })) }); defineFunction( ["frac", "dfrac", "tfrac", "cfrac", "binom", "dbinom", "tbinom"], "{:expression}{:expression}", { ifMode: "math", createAtom: (options) => { const genfracOptions = __spreadValues({}, options); const command = options.command; const args = options.args; switch (command) { case "\\dfrac": case "\\frac": case "\\tfrac": genfracOptions.hasBarLine = true; break; case "\\atopfrac": genfracOptions.hasBarLine = false; break; case "\\dbinom": case "\\binom": case "\\tbinom": genfracOptions.hasBarLine = false; genfracOptions.leftDelim = "("; genfracOptions.rightDelim = ")"; break; case "\\cfrac": genfracOptions.hasBarLine = true; genfracOptions.continuousFraction = true; break; default: } switch (command) { case "\\dfrac": case "\\dbinom": genfracOptions.mathstyleName = "displaystyle"; break; case "\\tfrac": case "\\tbinom": genfracOptions.mathstyleName = "textstyle"; break; default: } return new GenfracAtom( !args[0] ? [new PlaceholderAtom()] : argAtoms(args[0]), !args[1] ? [new PlaceholderAtom()] : argAtoms(args[1]), genfracOptions ); }, serialize: (atom, options) => { const numer = atom.aboveToLatex(options); const denom = atom.belowToLatex(options); if (/^[0-9]$/.test(numer) && /^[0-9]$/.test(denom)) return `${atom.command}${numer}${denom}`; return latexCommand(atom.command, numer, denom); } } ); defineFunction(["brace", "brack"], "", { infix: true, createAtom: (options) => new GenfracAtom(argAtoms(options.args[0]), argAtoms(options.args[1]), __spreadProps(__spreadValues({}, options), { hasBarLine: false, leftDelim: options.command === "\\brace" ? "\\lbrace" : "\\lbrack", rightDelim: options.command === "\\brace" ? "\\rbrace" : "\\rbrack" })), serialize: (atom, options) => joinLatex([ atom.aboveToLatex(options), atom.command, atom.belowToLatex(options) ]) }); defineFunction(["over", "atop", "choose"], "", { infix: true, createAtom: (options) => { let leftDelim = void 0; let rightDelim = void 0; const args = options.args; if (options.command === "\\choose") { leftDelim = "("; rightDelim = ")"; } return new GenfracAtom(argAtoms(args[0]), argAtoms(args[1]), __spreadProps(__spreadValues({}, options), { hasBarLine: options.command === "\\over", leftDelim, rightDelim })); }, serialize: (atom, options) => joinLatex([ atom.aboveToLatex(options), atom.command, atom.belowToLatex(options) ]) }); defineFunction( ["overwithdelims", "atopwithdelims"], "{numer:auto}{denom:auto}{left-delim:delim}{right-delim:delim}", { infix: true, createAtom: (options) => { var _a3, _b3; const args = options.args; return new GenfracAtom(argAtoms(args[0]), argAtoms(args[1]), __spreadProps(__spreadValues({}, options), { leftDelim: (_a3 = args[2]) != null ? _a3 : ".", rightDelim: (_b3 = args[3]) != null ? _b3 : ".", hasBarLine: false })); }, serialize: (atom, options) => `${atom.aboveToLatex(options)} ${atom.command}${atom.leftDelim}${atom.rightDelim}${atom.belowToLatex(options)}` } ); defineFunction("pdiff", "{numerator}{denominator}", { ifMode: "math", createAtom: (options) => new GenfracAtom(argAtoms(options.args[0]), argAtoms(options.args[1]), __spreadProps(__spreadValues({}, options), { hasBarLine: true, numerPrefix: "\u2202", denomPrefix: "\u2202" })) }); defineFunction( [ "sum", "prod", "bigcup", "bigcap", "coprod", "bigvee", "bigwedge", "biguplus", "bigotimes", "bigoplus", "bigodot", "bigsqcup", "intop" ], "", { ifMode: "math", createAtom: (options) => new ExtensibleSymbolAtom( { coprod: "\u2210", bigvee: "\u22C1", bigwedge: "\u22C0", biguplus: "\u2A04", bigcap: "\u22C2", bigcup: "\u22C3", intop: "\u222B", prod: "\u220F", sum: "\u2211", bigotimes: "\u2A02", bigoplus: "\u2A01", bigodot: "\u2A00", bigsqcup: "\u2A06", smallint: "\u222B" }[options.command.slice(1)], __spreadProps(__spreadValues({}, options), { limits: "auto", variant: "main" }) ) } ); defineFunction("smallint", "", { ifMode: "math", createAtom: (options) => new OperatorAtom("\u222B", __spreadProps(__spreadValues({}, options), { limits: "adjacent", variant: "main" })) }); var EXTENSIBLE_SYMBOLS = { int: "\u222B", iint: "\u222C", iiint: "\u222D", oint: "\u222E", oiint: "\u222F", oiiint: "\u2230", intclockwise: "\u2231", varointclockwise: "\u2232", ointctrclockwise: "\u2233", intctrclockwise: "\u2A11", sqcup: "\u2294", sqcap: "\u2293", uplus: "\u228E", wr: "\u2240", amalg: "\u2A3F", Cap: "\u22D2", Cup: "\u22D3", doublecap: "\u22D2", doublecup: "\u22D3" }; defineFunction(Object.keys(EXTENSIBLE_SYMBOLS), "", { ifMode: "math", createAtom: (options) => { const command = options.command; const symbol = EXTENSIBLE_SYMBOLS[command.slice(1)]; return new ExtensibleSymbolAtom(symbol, __spreadProps(__spreadValues({}, options), { limits: "adjacent", variant: { "\u22D2": "ams", "\u22D3": "ams" }[symbol] })); } }); defineFunction(["Re", "Im"], "", { ifMode: "math", createAtom: (options) => new OperatorAtom( { "\\Re": "\u211C", "\\Im": "\u2111" }[options.command], __spreadProps(__spreadValues({}, options), { limits: "adjacent", isFunction: true, variant: "fraktur" }) ) }); defineFunction("middle", "{:delim}", { ifMode: "math", createAtom: (options) => { var _a3; return new MiddleDelimAtom(__spreadProps(__spreadValues({}, options), { delim: (_a3 = options.args[0]) != null ? _a3 : "|", size: 1 })); } }); defineFunction("the", "{:value}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { captureSelection: true, verbatimLatex: null // disable verbatim LaTeX })), render: (atom, parent) => { var _a3; const ctx = new Context({ parent }, atom.style); let classes = ""; if (atom.isSelected) classes += " ML__selected"; const arg = ctx.evaluate(atom.args[0]); return new Box( ((_a3 = serializeLatexValue(arg)) != null ? _a3 : "").split("").map( (x) => new Box(x, { type: "ord", classes, mode: atom.mode, isSelected: atom.isSelected, style: __spreadValues({ variant: "main" }, atom.style) }) ), { type: "lift", style: atom.style, caret: atom.caret, isSelected: atom.isSelected, classes } ).wrap(ctx); }, serialize: (atom) => { var _a3; return `\\the${(_a3 = serializeLatexValue(atom.args[0])) != null ? _a3 : "\\relax"}`; } }); // src/latex-commands/styling.ts defineFunction("mathtip", "{:auto}{:math}", { createAtom: (options) => new TooltipAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), tooltip: argAtoms(options.args[1]), content: "math" })), serialize: (atom, options) => options.skipStyles ? atom.bodyToLatex(options) : `\\texttip{${atom.bodyToLatex(options)}}{${Atom.serialize( [atom.tooltip], __spreadProps(__spreadValues({}, options), { defaultMode: "math" }) )}}` }); defineFunction("texttip", "{:auto}{:text}", { createAtom: (options) => new TooltipAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), tooltip: argAtoms(options.args[1]), content: "text" })), serialize: (atom, options) => options.skipStyles ? atom.bodyToLatex(options) : `\\texttip{${atom.bodyToLatex(options)}}{${Atom.serialize( [atom.tooltip], __spreadProps(__spreadValues({}, options), { defaultMode: "text" }) )}}` }); defineFunction("error", "{:math}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), serialize: (atom, options) => `\\error{${atom.bodyToLatex(options)}}`, render: (atom, context) => atom.createBox(context, { classes: "ML__error" }) }); defineFunction("ensuremath", "{:math}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), serialize: (atom, options) => `${atom.command}{${atom.bodyToLatex(__spreadProps(__spreadValues({}, options), { defaultMode: "math" }))}}` }); defineFunction("color", "{:value}", { applyStyle: (_name, args, context) => { var _a3, _b3; return { verbatimColor: (_a3 = serializeLatexValue(args[0])) != null ? _a3 : void 0, color: context.toColor((_b3 = args[0]) != null ? _b3 : { string: "red" }) }; } }); defineFunction("textcolor", "{:value}{content:auto*}", { applyStyle: (_name, args, context) => { var _a3, _b3; return { verbatimColor: (_a3 = serializeLatexValue(args[0])) != null ? _a3 : void 0, color: context.toColor((_b3 = args[0]) != null ? _b3 : { string: "red" }) }; } }); defineFunction("boxed", "{content:math}", { createAtom: (options) => new BoxAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), framecolor: { string: "black" } })) }); defineFunction("colorbox", "{:value}{:text*}", { applyStyle: (_name, args, context) => { var _a3, _b3; return { verbatimBackgroundColor: (_a3 = serializeLatexValue(args[0])) != null ? _a3 : void 0, backgroundColor: context.toBackgroundColor( (_b3 = args[0]) != null ? _b3 : { string: "yellow" } ) }; } }); defineFunction( "fcolorbox", "{frame-color:value}{background-color:value}{content:text}", { applyMode: "text", createAtom: (options) => { var _a3, _b3; return new BoxAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[2]), framecolor: (_a3 = options.args[0]) != null ? _a3 : { string: "blue" }, backgroundcolor: (_b3 = options.args[1]) != null ? _b3 : { string: "yellow" } })); }, serialize: (atom, options) => { var _a3, _b3; return options.skipStyles ? atom.bodyToLatex(__spreadProps(__spreadValues({}, options), { defaultMode: "text" })) : latexCommand( atom.command, (_a3 = serializeLatexValue(atom.framecolor)) != null ? _a3 : "", (_b3 = serializeLatexValue(atom.backgroundcolor)) != null ? _b3 : "", atom.bodyToLatex(__spreadProps(__spreadValues({}, options), { defaultMode: "text" })) ); } } ); defineFunction("bbox", "[:bbox]{body:auto}", { createAtom: (options) => { var _a3; const arg = options.args[0]; const body = argAtoms(options.args[1]); if (!arg) return new BoxAtom(__spreadProps(__spreadValues({}, options), { body })); return new BoxAtom(__spreadProps(__spreadValues({}, options), { body, padding: arg.padding, border: arg.border, backgroundcolor: (_a3 = arg.backgroundcolor) != null ? _a3 : void 0 })); }, serialize: (atom, options) => { var _a3, _b3; if (options.skipStyles) return atom.bodyToLatex(options); let result = atom.command; if (Number.isFinite(atom.padding) || atom.border !== void 0 || atom.backgroundcolor !== void 0) { const bboxParameters = []; if (atom.padding) bboxParameters.push((_a3 = serializeLatexValue(atom.padding)) != null ? _a3 : ""); if (atom.border) bboxParameters.push(`border: ${atom.border}`); if (atom.backgroundcolor) bboxParameters.push((_b3 = serializeLatexValue(atom.backgroundcolor)) != null ? _b3 : ""); result += `[${bboxParameters.join(",")}]`; } return latexCommand(result, atom.bodyToLatex(options)); } }); defineFunction( ["displaystyle", "textstyle", "scriptstyle", "scriptscriptstyle"], "{:rest}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), render: (atom, context) => { const ctx = new Context( { parent: context, mathstyle: atom.command.slice(1) }, atom.style ); const box = Atom.createBox(ctx, atom.body, { type: "lift" }); if (atom.caret) box.caret = atom.caret; return atom.bind(context, box); }, serialize: (atom, options) => options.skipStyles ? atom.bodyToLatex(options) : `{${joinLatex([atom.command, atom.bodyToLatex(options)])}}` } ); defineFunction( [ "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large", "Large", "LARGE", "huge", "Huge" ], "", { // TeX behaves very inconsistently when sizing commands are applied // to math mode. We allow sizing commands to be applied in both math and // text mode applyStyle: (name) => { return { fontSize: { "\\tiny": 1, "\\scriptsize": 2, // Not to be confused with \scriptstyle "\\footnotesize": 3, "\\small": 4, "\\normalsize": 5, "\\large": 6, "\\Large": 7, "\\LARGE": 8, "\\huge": 9, "\\Huge": 10 }[name] }; } } ); defineFunction("fontseries", "{:string}", { ifMode: "text", applyStyle: (_name, args) => { var _a3; return { fontSeries: (_a3 = args[0]) != null ? _a3 : "auto" }; } }); defineFunction("fontshape", "{:string}", { ifMode: "text", applyStyle: (_name, args) => { var _a3; return { fontShape: (_a3 = args[0]) != null ? _a3 : "auto" }; } }); defineFunction("fontfamily", "{:string}", { ifMode: "text", applyStyle: (_name, args) => { var _a3; return { fontFamily: (_a3 = args[0]) != null ? _a3 : "roman" }; } }); defineFunction("selectfont", "", { ifMode: "text", applyStyle: () => ({}) }); defineFunction("bf", "{:rest}", { applyStyle: () => ({ fontSeries: "b", fontShape: "n", fontFamily: "roman" }) }); defineFunction(["boldsymbol", "bm"], "{:math}", { applyMode: "math", createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), serialize: (atom, options) => `${atom.command}{${atom.bodyToLatex(options)}}`, render: (atom, context) => atom.createBox(context, { classes: "ML__boldsymbol" }) }); defineFunction("bold", "{:math*}", { applyMode: "math", applyStyle: () => ({ variantStyle: "bold" }) }); defineFunction("bfseries", "{:rest}", { applyMode: "text", applyStyle: () => ({ fontSeries: "b" }) }); defineFunction("mdseries", "{:rest}", { applyMode: "text", applyStyle: () => ({ fontSeries: "m" }) }); defineFunction("upshape", "{:rest}", { applyMode: "text", applyStyle: () => ({ fontShape: "n" }) }); defineFunction("slshape", "{:rest}", { applyMode: "text", applyStyle: () => ({ fontShape: "sl" }) }); defineFunction("scshape", "{:rest}", { applyMode: "text", applyStyle: () => ({ fontShape: "sc" }) }); defineFunction("textbf", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontSeries: "b" }) }); defineFunction("textmd", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontSeries: "m" }) }); defineFunction("textup", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontShape: "n" }) }); defineFunction("textnormal", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontShape: "n", fontSeries: "m" }) }); defineFunction("textsl", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontShape: "sl" }) }); defineFunction("textit", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontShape: "it" }) }); defineFunction("textsc", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontShape: "sc" }) }); defineFunction("textrm", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontFamily: "roman" }) }); defineFunction("textsf", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontFamily: "sans-serif" }) }); defineFunction("texttt", "{:text*}", { applyMode: "text", applyStyle: () => ({ fontFamily: "monospace" }) }); defineFunction("mathbf", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "normal", variantStyle: "bold" }) }); defineFunction("mathit", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "main", variantStyle: "italic" }) }); defineFunction("mathnormal", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "normal", variantStyle: "italic" }) }); defineFunction("mathbfit", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "main", variantStyle: "bolditalic" }) }); defineFunction("mathrm", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "normal", variantStyle: "up" }) }); defineFunction("mathsf", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "sans-serif", variantStyle: "up" }) }); defineFunction("mathtt", "{:math*}", { applyMode: "math", applyStyle: () => ({ variant: "monospace", variantStyle: "up" }) }); defineFunction("it", "{:rest}", { applyStyle: () => ({ fontSeries: "m", fontShape: "it", fontFamily: "roman", variantStyle: "italic" // For math mode }) }); defineFunction("rmfamily", "", { applyStyle: () => ({ fontFamily: "roman" }) }); defineFunction("sffamily", "", { applyStyle: () => ({ fontFamily: "sans-serif" }) }); defineFunction("ttfamily", "", { applyStyle: () => ({ fontFamily: "monospace" }) }); defineFunction(["Bbb", "mathbb"], "{:math*}", { applyStyle: () => ({ variant: "double-struck", variantStyle: "up" }) }); defineFunction(["frak", "mathfrak"], "{:math*}", { applyStyle: () => ({ variant: "fraktur", variantStyle: "up" }) }); defineFunction("mathcal", "{:math*}", { applyStyle: () => ({ variant: "calligraphic", variantStyle: "up" }) }); defineFunction("mathscr", "{:math*}", { applyStyle: () => ({ variant: "script", variantStyle: "up" }) }); defineFunction("mbox", "{:text}", { ifMode: "math", createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { type: "mord", body: argAtoms(options.args[0]), mode: "math" })), serialize: (atom, options) => latexCommand( "\\mbox", atom.bodyToLatex(__spreadProps(__spreadValues({}, options), { defaultMode: "text" })) ) }); defineFunction("text", "{:text}", { ifMode: "math", applyMode: "text" }); defineFunction(["class", "htmlClass"], "{name:string}{content:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]) })), serialize: (atom, options) => { if (!atom.args[0] || options.skipStyles) return atom.bodyToLatex(options); return `${atom.command}{${atom.args[0]}}{${atom.bodyToLatex( options )}}`; }, render: (atom, context) => { var _a3; return atom.createBox(context, { classes: (_a3 = atom.args[0]) != null ? _a3 : "" }); } }); defineFunction(["cssId", "htmlId"], "{id:string}{content:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]) })), serialize: (atom, options) => { var _a3; if (!((_a3 = atom.args) == null ? void 0 : _a3[0]) || options.skipStyles) return atom.bodyToLatex(options); return `${atom.command}{${atom.args[0]}}{${atom.bodyToLatex( options )}}`; }, render: (atom, context) => { var _a3; const box = atom.createBox(context); box.cssId = (_a3 = atom.args[0]) != null ? _a3 : ""; return box; } }); defineFunction("htmlData", "{data:string}{content:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]) })), serialize: (atom, options) => { var _a3; if (!((_a3 = atom.args) == null ? void 0 : _a3[0]) || options.skipStyles) return atom.bodyToLatex(options); return `\\htmlData{${atom.args[0]}}{${atom.bodyToLatex( options )}}`; }, render: (atom, context) => { var _a3; const box = atom.createBox(context); box.htmlData = (_a3 = atom.args[0]) != null ? _a3 : ""; return box; } }); defineFunction(["style", "htmlStyle"], "{data:string}{content:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]) })), serialize: (atom, options) => { var _a3; if (!((_a3 = atom.args) == null ? void 0 : _a3[0]) || options.skipStyles) return atom.bodyToLatex(options); return `${atom.command}{${atom.args[0]}}{${atom.bodyToLatex( options )}}`; }, render: (atom, context) => { var _a3; const box = atom.createBox(context); box.htmlStyle = (_a3 = atom.args[0]) != null ? _a3 : ""; return box; } }); defineFunction("em", "{:rest}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), serialize: (atom, options) => options.skipStyles ? atom.bodyToLatex(options) : `{\\em ${atom.bodyToLatex(options)}}`, render: (atom, context) => atom.createBox(context, { classes: "ML__emph", boxType: "lift" }) }); defineFunction("emph", "{:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]) })), serialize: (atom, options) => options.skipStyles ? atom.bodyToLatex(options) : `\\emph{${atom.bodyToLatex(options)}}`, render: (atom, context) => atom.createBox(context, { classes: "ML__emph", boxType: "lift" }) }); var DELIMITER_SIZES = { "\\bigl": { mclass: "mopen", size: 1 }, "\\Bigl": { mclass: "mopen", size: 2 }, "\\biggl": { mclass: "mopen", size: 3 }, "\\Biggl": { mclass: "mopen", size: 4 }, "\\bigr": { mclass: "mclose", size: 1 }, "\\Bigr": { mclass: "mclose", size: 2 }, "\\biggr": { mclass: "mclose", size: 3 }, "\\Biggr": { mclass: "mclose", size: 4 }, "\\bigm": { mclass: "mrel", size: 1 }, "\\Bigm": { mclass: "mrel", size: 2 }, "\\biggm": { mclass: "mrel", size: 3 }, "\\Biggm": { mclass: "mrel", size: 4 }, "\\big": { mclass: "mord", size: 1 }, "\\Big": { mclass: "mord", size: 2 }, "\\bigg": { mclass: "mord", size: 3 }, "\\Bigg": { mclass: "mord", size: 4 } }; defineFunction( [ "bigl", "Bigl", "biggl", "Biggl", "bigr", "Bigr", "biggr", "Biggr", "bigm", "Bigm", "biggm", "Biggm", "big", "Big", "bigg", "Bigg" ], "{:delim}", { createAtom: (options) => { var _a3; return new SizedDelimAtom(__spreadProps(__spreadValues({}, options), { delim: (_a3 = options.args[0]) != null ? _a3 : ".", size: DELIMITER_SIZES[options.command].size, delimType: DELIMITER_SIZES[options.command].mclass })); } } ); defineFunction( [ "hspace", "hspace*" // \hspace* inserts a non-breakable space, but since we don't line break... // it's the same as \hspace. ], "{width:value}", { createAtom: (options) => { var _a3; return new SpacingAtom(__spreadProps(__spreadValues({}, options), { width: (_a3 = options.args[0]) != null ? _a3 : { dimension: 0 } })); } } ); defineFunction(["mkern", "kern", "mskip", "hskip", "mspace"], "{width:value}", { createAtom: (options) => { var _a3; return new SpacingAtom(__spreadProps(__spreadValues({}, options), { width: (_a3 = options.args[0]) != null ? _a3 : { dimension: 0 } })); } }); defineFunction("mathchoice", "{:math}{:math}{:math}{:math}", { // display, text, script and scriptscript createAtom: (options) => new Atom(options), render: (atom, context) => { let i = 0; const d = context.mathstyle.id; if (d === T || d === Tc) i = 1; if (d === S || d === Sc) i = 2; if (d === SS || d === SSc) i = 3; const body = argAtoms(atom.args[i]); return Atom.createBox(context, body); }, serialize: (atom, options) => `\\mathchoice{${Atom.serialize( atom.args[0], options )}}{${Atom.serialize(atom.args[1], options)}}{${Atom.serialize( atom.args[2], options )}}{${Atom.serialize(atom.args[3], options)}}` }); defineFunction("mathop", "{:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { type: "mop", body: argAtoms(options.args[0]), limits: "over-under", isFunction: true, captureSelection: true })), render: (atom, context) => { var _a3; let base = Atom.createBox(context, atom.body); if (atom.superscript || atom.subscript) { const limits = (_a3 = atom.subsupPlacement) != null ? _a3 : "auto"; base = limits === "over-under" || limits === "auto" && context.isDisplayStyle ? atom.attachLimits(context, { base }) : atom.attachSupsub(context, { base }); } return new Box(atom.bind(context, base), { type: "op", isSelected: atom.isSelected, classes: "op-group" }); }, serialize: (atom, options) => { const result = [latexCommand(atom.command, atom.bodyToLatex(options))]; if (atom.explicitSubsupPlacement) { if (atom.subsupPlacement === "over-under") result.push("\\limits"); if (atom.subsupPlacement === "adjacent") result.push("\\nolimits"); if (atom.subsupPlacement === "auto") result.push("\\displaylimits"); } result.push(atom.supsubToLatex(options)); return joinLatex(result); } }); defineFunction( [ "mathbin", "mathrel", "mathopen", "mathclose", "mathpunct", "mathord", "mathinner" ], "{:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { type: { "\\mathbin": "mbin", "\\mathrel": "mrel", "\\mathopen": "mopen", "\\mathclose": "mclose", "\\mathpunct": "mpunct", "\\mathord": "mord", "\\mathinner": "minner" }[options.command], body: argAtoms(options.args[0]) })) } ); defineFunction(["operatorname", "operatorname*"], "{operator:math}", { createAtom: (options) => { const body = argAtoms(options.args[0]).map((x) => { var _a3; if (x.type !== "first") { x.type = "mord"; x.value = (_a3 = { "\u2217": "*", "\u2212": "-" }[x.value]) != null ? _a3 : x.value; x.isFunction = false; if (!x.style.variant && !x.style.variantStyle) { x.style.variant = "main"; x.style.variantStyle = "up"; } } return x; }); return new Atom(__spreadProps(__spreadValues({}, options), { type: "mop", body, isFunction: true, limits: options.command === "\\operatorname" ? "adjacent" : "over-under" })); }, render: (atom, context) => { var _a3; let base = Atom.createBox(context, atom.body); if (atom.superscript || atom.subscript) { const limits = (_a3 = atom.subsupPlacement) != null ? _a3 : "auto"; base = limits === "over-under" || limits === "auto" && context.isDisplayStyle ? atom.attachLimits(context, { base }) : atom.attachSupsub(context, { base }); } if (atom.caret) base.caret = atom.caret; return new Box(atom.bind(context, base), { type: "op", isSelected: atom.isSelected, classes: "op-group" }); }, serialize: (atom, options) => { const result = [latexCommand(atom.command, atom.bodyToLatex(options))]; if (atom.explicitSubsupPlacement) { if (atom.subsupPlacement === "over-under") result.push("\\limits"); if (atom.subsupPlacement === "adjacent") result.push("\\nolimits"); if (atom.subsupPlacement === "auto") result.push("\\displaylimits"); } result.push(atom.supsubToLatex(options)); return joinLatex(result); } }); defineFunction(["char", "unicode"], "{charcode:value}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { type: options.mode === "text" ? "text" : "mord" })), serialize: (atom) => { var _a3; return `${atom.command}${serializeLatexValue( (_a3 = atom.args[0]) != null ? _a3 : { number: 10067, base: "hexadecimal" } )}`; }, render: (atom, context) => { let value = context.evaluate(atom.args[0]); if (!value || !("number" in value)) value = { number: 10067, base: "hexadecimal" }; atom.value = String.fromCodePoint(value.number); return atom.createBox(context); } }); defineFunction("rule", "[raise:value]{width:value}{thickness:value}", { createAtom: (options) => new Atom(options), render: (atom, context) => { var _a3, _b3, _c2; const ctx = new Context( { parent: context, mathstyle: "textstyle" }, atom.style ); const shift = ctx.toEm((_a3 = atom.args[0]) != null ? _a3 : { dimension: 0 }); const width = ctx.toEm((_b3 = atom.args[1]) != null ? _b3 : { dimension: 10 }); const height = ctx.toEm((_c2 = atom.args[2]) != null ? _c2 : { dimension: 10 }); const result = new Box(null, { classes: "rule", type: "ord" }); result.width = width; result.height = height + shift; result.depth = -shift; result.setStyle("border-right-width", width, "em"); result.setStyle("border-top-width", height, "em"); result.setStyle("border-color", atom.style.color); result.setStyle("vertical-align", shift, "em"); if (atom.isSelected) result.setStyle("opacity", "50%"); atom.bind(ctx, result); if (atom.caret) result.caret = atom.caret; return result.wrap(context); }, serialize: (atom) => `\\rule${atom.args[0] ? `[${serializeLatexValue(atom.args[0])}]` : ""}{${serializeLatexValue(atom.args[1])}}{${serializeLatexValue( atom.args[2] )}}` }); defineFunction(["overline", "underline"], "{:auto}", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]) })), render: (atom, parentContext) => { const position = atom.command.substring(1); const context = new Context( { parent: parentContext, mathstyle: "cramp" }, atom.style ); const inner = Atom.createBox(context, atom.body); if (!inner) return null; const ruleThickness = context.metrics.defaultRuleThickness / context.scalingFactor; const line = new Box(null, { classes: position + "-line" }); line.height = ruleThickness; line.maxFontSize = ruleThickness * 1.125 * context.scalingFactor; let stack; if (position === "overline") { stack = new VBox({ shift: 0, children: [ { box: inner }, 3 * ruleThickness, { box: line }, ruleThickness ] }); } else { stack = new VBox({ top: inner.height, children: [ ruleThickness, { box: line }, 3 * ruleThickness, { box: inner } ] }); } if (atom.caret) stack.caret = atom.caret; return new Box(stack, { classes: position, type: "ignore" }); } }); defineFunction("overset", "{:auto}{base:auto}", { createAtom: (options) => { const body = argAtoms(options.args[1]); return new OverunderAtom(__spreadProps(__spreadValues({}, options), { above: argAtoms(options.args[0]), body, skipBoundary: false, boxType: atomsBoxType(body) })); }, serialize: (atom, options) => latexCommand( atom.command, atom.aboveToLatex(options), atom.bodyToLatex(options) ) }); defineFunction("underset", "{:auto}{base:auto}", { createAtom: (options) => { const body = argAtoms(options.args[1]); return new OverunderAtom(__spreadProps(__spreadValues({}, options), { below: argAtoms(options.args[0]), body, skipBoundary: false, boxType: atomsBoxType(body) })); }, serialize: (atom, options) => latexCommand( atom.command, atom.belowToLatex(options), atom.bodyToLatex(options) ) }); defineFunction("overunderset", "{above:auto}{below:auto}{base:auto}", { createAtom: (options) => { const body = argAtoms(options.args[2]); return new OverunderAtom(__spreadProps(__spreadValues({}, options), { above: argAtoms(options.args[0]), below: argAtoms(options.args[1]), body, skipBoundary: false, boxType: atomsBoxType(body) })); }, serialize: (atom, options) => latexCommand( atom.command, atom.belowToLatex(options), atom.bodyToLatex(options) ) }); defineFunction( ["stackrel", "stackbin"], "[below:auto]{above:auto}{base:auto}", { createAtom: (options) => new OverunderAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[2]), above: argAtoms(options.args[1]), below: argAtoms(options.args[0]), skipBoundary: false, boxType: options.command === "\\stackrel" ? "rel" : "bin" })), serialize: (atom, options) => latexCommand( atom.command, atom.aboveToLatex(options), atom.bodyToLatex(options) ) } ); defineFunction("smash", "[:string]{:auto}", { createAtom: (options) => { var _a3, _b3, _c2, _d2; return new PhantomAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]), smashHeight: (_b3 = (_a3 = options.args[0]) == null ? void 0 : _a3.includes("t")) != null ? _b3 : true, smashDepth: (_d2 = (_c2 = options.args[0]) == null ? void 0 : _c2.includes("b")) != null ? _d2 : true })); } }); defineFunction(["vphantom"], "{:auto}", { createAtom: (options) => new PhantomAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), isInvisible: true, smashWidth: true })) }); defineFunction(["hphantom"], "{:auto}", { createAtom: (options) => new PhantomAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), isInvisible: true, smashHeight: true, smashDepth: true })) }); defineFunction(["phantom"], "{:auto}", { createAtom: (options) => new PhantomAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), isInvisible: true })) }); defineFunction("not", "{:math}", { createAtom: (options) => { const body = argAtoms(options.args[0]); if (body.length === 0) return new Atom(__spreadProps(__spreadValues({}, options), { type: "mrel", value: "\uE020" })); return new Atom(__spreadProps(__spreadValues({}, options), { body: [ new OverlapAtom(__spreadProps(__spreadValues({}, options), { body: "\uE020", align: "right" })), ...body ], captureSelection: true })); }, serialize: (atom, options) => { const arg = atom.args[0]; const isGroup = arg && typeof arg === "object" && "group" in arg; if (atom.value !== "\uE020") { return isGroup ? `\\not{${Atom.serialize(arg.group, options)}}` : `\\not${Atom.serialize(arg, options)}`; } return isGroup ? `\\not{}` : `\\not`; }, render: (atom, context) => { if (atom.value) return atom.createBox(context); const isGroup = atom.args[0] && typeof atom.args[0] === "object" && "group" in atom.args[0]; const type = isGroup ? "ord" : atomsBoxType(argAtoms(atom.args[0])); const box = Atom.createBox(context, atom.body, { type }); if (atom.caret) box.caret = atom.caret; return atom.bind(context, box); } }); defineFunction(["ne", "neq"], "", { createAtom: (options) => new Atom(__spreadProps(__spreadValues({}, options), { type: "mrel", body: [ new OverlapAtom(__spreadProps(__spreadValues({}, options), { body: "\uE020", align: "right", boxType: "rel" })), new Atom(__spreadProps(__spreadValues({}, options), { value: "=" })) ], captureSelection: true })), serialize: (atom) => atom.command }); defineFunction("rlap", "{:auto}", { createAtom: (options) => new OverlapAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), align: "right" })) }); defineFunction("llap", "{:auto}", { createAtom: (options) => new OverlapAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), align: "left" })) }); defineFunction("mathrlap", "{:math}", { createAtom: (options) => new OverlapAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), align: "left" })) }); defineFunction("mathllap", "{:math}", { createAtom: (options) => new OverlapAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[0]), align: "left" })) }); defineFunction("raisebox", "{:value}{:text}", { createAtom: (options) => { var _a3; return new BoxAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]), padding: { dimension: 0 }, offset: (_a3 = options.args[0]) != null ? _a3 : { dimension: 0 } })); }, serialize: (atom, options) => { var _a3; return latexCommand( "\\raisebox", (_a3 = serializeLatexValue(atom.offset)) != null ? _a3 : "0pt", atom.bodyToLatex(options) ); } }); defineFunction("raise", "{:value}{:auto}", { createAtom: (options) => { var _a3; return new BoxAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]), padding: { dimension: 0 }, offset: (_a3 = options.args[0]) != null ? _a3 : { dimension: 0 } })); }, serialize: (atom, options) => { var _a3; return latexCommand( "\\raise", (_a3 = serializeLatexValue(atom.offset)) != null ? _a3 : "0pt", atom.bodyToLatex(options) ); } }); defineFunction("lower", "{:value}{:auto}", { createAtom: (options) => { var _a3; return new BoxAtom(__spreadProps(__spreadValues({}, options), { body: argAtoms(options.args[1]), padding: { dimension: 0 }, offset: (_a3 = multiplyLatexValue(options.args[0], -1)) != null ? _a3 : { dimension: 0 } })); }, serialize: (atom, options) => { var _a3, _b3; return latexCommand( "\\lower", (_b3 = serializeLatexValue( multiplyLatexValue((_a3 = atom.offset) != null ? _a3 : { dimension: 0 }, -1) )) != null ? _b3 : "0pt", atom.bodyToLatex(options) ); } }); // src/latex-commands/symbols.ts defineSymbols("0123456789/@.?!"); defineSymbolRange(65, 90); defineSymbolRange(97, 122); defineSymbols([ ["\\forall", 8704], ["\\exists", 8707], ["\\nexists", 8708, "mord", "ams"], ["\\mid", 8739, "mrel"], ["\\top", 8868], ["\\bot", 8869] ]); defineSymbols([ ["\\#", 35], ["\\&", 38], ["\\parallelogram", 9649], ["\\spadesuit", 9824], ["\\heartsuit", 9825], ["\\diamondsuit", 9826], ["\\clubsuit", 9827], ["\\flat", 9837], ["\\natural", 9838], ["\\sharp", 9839] ]); defineSymbols([ ["\\backslash", 92], ["\\nabla", 8711], ["\\partial", 8706], ["\\ell", 8467], ["\\hbar", 8463], ["\\Q", 81, "mord", "double-struck"], // NOTE: Check if standard LaTeX ["\\C", 67, "mord", "double-struck"], // NOTE: Check if standard LaTeX ["\\P", 80, "mord", "double-struck"], // NOTE: Check if standard LaTeX ["\\pounds", 163], ["\\euro", 8364] // NOTE: not TeX built-in, but textcomp package // TODO Koppa, Stigma, Sampi ]); defineSymbols( [ ["\\rightarrow", 8594], ["\\to", 8594], ["\\leftarrow", 8592], ["\\gets", 8592], ["\\Rightarrow", 8658], ["\\Leftarrow", 8656], ["\\longrightarrow", 10230], ["\\longleftarrow", 10229], ["\\Longrightarrow", 10233], ["\\implies", 10233], ["\\Longleftarrow", 10232], ["\\impliedby", 10232], ["\\longleftrightarrow", 10231], ["\\biconditional", 10231], ["\\Longleftrightarrow", 10234], ["\\mapsto", 8614], ["\\longmapsto", 10236], ["\\uparrow", 8593], ["\\downarrow", 8595], ["\\Uparrow", 8657], ["\\Downarrow", 8659], ["\\updownarrow", 8597], ["\\Updownarrow", 8661], ["\\hookrightarrow", 8618], ["\\hookleftarrow", 8617], ["\\rightharpoonup", 8640], ["\\leftharpoonup", 8636], ["\\rightharpoondown", 8641], ["\\leftharpoondown", 8637], ["\\searrow", 8600], ["\\nearrow", 8599], ["\\swarrow", 8601], ["\\nwarrow", 8598], ["\\originalof", 8886], ["\\laplace", 8886], ["\\imageof", 8887], ["\\Laplace", 8887] ], "mrel" ); defineSymbols([ ["\\mapsfrom", 8612, "mrel"], ["\\Mapsfrom", 10502, "mrel"], ["\\MapsTo", 10503, "mrel"], ["\\Yup", 8516, "mord"], ["\\lightning", 8623, "mrel"], ["\\leftarrowtriangle", 8701, "mrel"], ["\\rightarrowtriangle", 8702, "mrel"], ["\\leftrightarrowtriangle", 8703, "mrel"], ["\\boxdot", 8865, "mbin"], ["\\bigtriangleup", 9651, "mbin"], ["\\bigtriangledown", 9661, "mbin"], ["\\boxbar", 9707, "mbin"], ["\\Lbag", 10181, "mopen"], ["\\Rbag", 10182, "mclose"], ["\\llbracket", 10214, "mopen"], ["\\rrbracket", 10215, "mclose"], ["\\longmapsfrom", 10235, "mrel"], ["\\Longmapsfrom", 10237, "mrel"], ["\\Longmapsto", 10238, "mrel"], ["\\boxslash", 10692, "mbin"], ["\\boxbslash", 10693, "mbin"], ["\\boxast", 10694, "mbin"], ["\\boxcircle", 10695, "mbin"], ["\\boxbox", 10696, "mbin"], ["\\fatsemi", 10783, "mop"], ["\\leftslice", 10918, "mrel"], ["\\rightslice", 10919, "mrel"], ["\\interleave", 10996, "mbin"], ["\\biginterleave", 11004, "mop"], ["\\sslash", 11005, "mbin"], ["\\talloblong", 11006, "mbin"] ]); defineSymbols([ // 'ams' Delimiters ["\\lbrace", 123, "mopen"], ["\\rbrace", 125, "mclose"], ["\\lparen", 40, "mopen"], // mathtools.sty ["\\rparen", 41, "mclose"], // mathtools.sty ["\\langle", 10216, "mopen"], ["\\rangle", 10217, "mclose"], ["\\lfloor", 8970, "mopen"], ["\\rfloor", 8971, "mclose"], ["\\lceil", 8968, "mopen"], ["\\rceil", 8969, "mclose"], ["\\vert", 8739], ["\\lvert", 8739, "mopen"], ["\\rvert", 8739, "mclose"], ["\\|", 8741], ["\\Vert", 8741], ["\\mVert", 8741], ["\\lVert", 8741, "mopen"], ["\\rVert", 8741, "mclose"], ["\\lbrack", 91, "mopen"], ["\\rbrack", 93, "mclose"], ["\\{", 123, "mopen"], ["\\}", 125, "mclose"], ["(", 40, "mopen"], [")", 41, "mclose"], ["[", 91, "mopen"], ["]", 93, "mclose"], ["\\ulcorner", 9484, "mopen", "ams"], ["\\urcorner", 9488, "mclose", "ams"], ["\\llcorner", 9492, "mopen", "ams"], ["\\lrcorner", 9496, "mclose", "ams"], // Large Delimiters ["\\lgroup", 10222, "mopen"], ["\\rgroup", 10223, "mclose"], ["\\lmoustache", 9136, "mopen"], ["\\rmoustache", 9137, "mclose"] // defineSymbol('\\ne', 0x2260, 'mrel'], // defineSymbol('\\neq', 0x2260, 'mrel'], // defineSymbol( '\\longequal', 0xF7D9, 'mrel', MAIN], // NOTE: Not TeX ]); defineSymbols( [ // 'ams' arrows ["\\dashrightarrow", 8674], ["\\dashleftarrow", 8672], ["\\Rrightarrow", 8667], ["\\Lleftarrow", 8666], ["\\leftrightarrows", 8646], ["\\rightleftarrows", 8644], ["\\curvearrowright", 8631], ["\\curvearrowleft", 8630], ["\\rightrightarrows", 8649], ["\\leftleftarrows", 8647], ["\\upuparrows", 8648], ["\\downdownarrows", 8650], ["\\vartriangle", 9651], ["\\triangleq", 8796], ["\\vartriangleleft", 8882], ["\\trianglelefteq", 8884], ["\\ntriangleleft", 8938], ["\\ntrianglelefteq", 8940], ["\\vartriangleright", 8883], ["\\trianglerighteq", 8885], ["\\ntriangleright", 8939], ["\\ntrianglerighteq", 8941], ["\\blacktriangleleft", 9664], ["\\blacktriangleright", 9654], ["\\leftarrowtail", 8610], ["\\rightarrowtail", 8611], ["\\looparrowright", 8620], ["\\looparrowleft", 8619], ["\\twoheadleftarrow", 8606], ["\\twoheadrightarrow", 8608], ["\\twoheadrightarrowtail", 10518], ["\\rightleftharpoons", 8652], ["\\leftrightharpoons", 8651], ["\\Rsh", 8625], ["\\Lsh", 8624], // 'ams' Relations ["\\circlearrowright", 8635], ["\\circlearrowleft", 8634], ["\\restriction", 8638], ["\\upharpoonright", 8638], ["\\upharpoonleft", 8639], ["\\downharpoonright", 8642], ["\\downharpoonleft", 8643], ["\\rightsquigarrow", 8669], ["\\leadsto", 8669], ["\\leftrightsquigarrow", 8621], ["\\multimap", 8888], // 'ams' Negated Arrows ["\\nleftarrow", 8602], ["\\nrightarrow", 8603], ["\\nRightarrow", 8655], ["\\nLeftarrow", 8653], ["\\nleftrightarrow", 8622], ["\\nLeftrightarrow", 8654], ["\\nvrightarrow", 8696], ["\\nvtwoheadrightarrow", 10496], ["\\nvrightarrowtail", 10516], ["\\nvtwoheadrightarrowtail", 10519], // 'ams' Negated Relations ["\\shortparallel", 8741], ["\\nless", 8814], ["\\nleqslant", 57360], ["\\lneq", 10887], ["\\lneqq", 8808], ["\\nleqq", 57361], ["\\lvertneqq", 57356], ["\\lnsim", 8934], ["\\lnapprox", 10889], ["\\nprec", 8832], ["\\npreceq", 8928], ["\\precnsim", 8936], ["\\precnapprox", 10937], ["\\nsim", 8769], ["\\nshortmid", 57350], ["\\nmid", 8740], ["\\nvdash", 8876], ["\\nvDash", 8877], ["\\ngtr", 8815], ["\\ngeqslant", 57359], ["\\ngeqq", 57358], ["\\gneq", 10888], ["\\gneqq", 8809], ["\\gvertneqq", 57357], ["\\gnsim", 8935], ["\\gnapprox", 10890], ["\\nsucc", 8833], ["\\nsucceq", 8929], ["\\succnsim", 8937], ["\\succnapprox", 10938], ["\\ncong", 8774], ["\\nshortparallel", 57351], ["\\nparallel", 8742], ["\\nVDash", 8879], ["\\nsupseteqq", 57368], ["\\supsetneq", 8843], ["\\varsupsetneq", 57371], ["\\supsetneqq", 10956], ["\\varsupsetneqq", 57369], ["\\nVdash", 8878], ["\\precneqq", 10933], ["\\succneqq", 10934], ["\\nsubseteqq", 57366], ["\\leqslant", 10877], ["\\geqslant", 10878], ["\\gtrsim", 8819], ["\\approxeq", 8778], ["\\thickapprox", 8776], ["\\lessapprox", 10885], ["\\gtrapprox", 10886], ["\\precapprox", 10935], ["\\succapprox", 10936], ["\\thicksim", 8764], ["\\succsim", 8831], ["\\precsim", 8830], ["\\backsim", 8765], ["\\eqsim", 8770], ["\\backsimeq", 8909], ["\\lesssim", 8818], ["\\nleq", 8816], ["\\ngeq", 8817], ["\\smallsmile", 8995], ["\\smallfrown", 8994], ["\\leqq", 8806], ["\\eqslantless", 10901], ["\\lll", 8920], ["\\lessgtr", 8822], ["\\lesseqgtr", 8922], ["\\lesseqqgtr", 10891], ["\\risingdotseq", 8787], ["\\fallingdotseq", 8786], ["\\subseteqq", 10949], ["\\Subset", 8912], ["\\sqsubset", 8847], ["\\preccurlyeq", 8828], ["\\curlyeqprec", 8926], ["\\vDash", 8872], ["\\Vvdash", 8874], ["\\bumpeq", 8783], ["\\Bumpeq", 8782], ["\\geqq", 8807], ["\\eqslantgtr", 10902], ["\\ggg", 8921], ["\\gtrless", 8823], ["\\gtreqless", 8923], ["\\gtreqqless", 10892], ["\\supseteqq", 10950], ["\\Supset", 8913], ["\\sqsupset", 8848], ["\\succcurlyeq", 8829], ["\\curlyeqsucc", 8927], ["\\Vdash", 8873], ["\\shortmid", 8739], ["\\between", 8812], ["\\pitchfork", 8916], ["\\varpropto", 8733], ["\\backepsilon", 8717], ["\\llless", 8920], ["\\gggtr", 8921], ["\\doteqdot", 8785], ["\\Doteq", 8785], ["\\eqcirc", 8790], ["\\circeq", 8791], ["\\therefore", 8756], ["\\because", 8757] ], "mrel", "ams" ); defineSymbols( [ ["+", 43], ["-", 8722], ["\u2212", 8722], ["\\pm", 177], ["\\mp", 8723], ["*", 8727], ["\\times", 215], ["\\div", 247], ["\\divides", 8739], ["\\cdot", 8901], ["\\cap", 8745], ["\\cup", 8746], ["\\setminus", 8726], ["\\land", 8743], ["\\wedge", 8743], ["\\lor", 8744], ["\\vee", 8744], ["\\circ", 8728], ["\\bigcirc", 9711], ["\\bullet", 8729], ["\\oplus", 8853], ["\\ominus", 8854], ["\\otimes", 8855], ["\\odot", 8857], ["\\oslash", 8856], ["\\bigtriangleup", 9651], ["\\bigtriangledown", 9661], ["\\triangleleft", 9667], ["\\triangleright", 9657], ["\\And", 38], ["\\dagger", 8224], ["\\dag", 8224], ["\\ddag", 8225], ["\\ddagger", 8225], ["\\ast", 8727], ["\\star", 8902], ["\\bigstar", 9733], ["\\diamond", 8900] ], "mbin" ); defineSymbols( [ ["\\lhd", 8882], ["\\rhd", 8883], ["\\lessdot", 8918], ["\\gtrdot", 8919], ["\\ltimes", 8905], ["\\rtimes", 8906], ["\\leftthreetimes", 8907], ["\\rightthreetimes", 8908], ["\\intercal", 8890], ["\\dotplus", 8724], ["\\doublebarwedge", 10846], ["\\divideontimes", 8903], ["\\centerdot", 8901], ["\\smallsetminus", 8726], ["\\barwedge", 8892], ["\\veebar", 8891], ["\\nor", 8891], // NOTE: Not TeX, Mathematica ["\\curlywedge", 8911], ["\\curlyvee", 8910], ["\\boxminus", 8863], ["\\boxplus", 8862], ["\\boxtimes", 8864], ["\\boxdot", 8865], ["\\circleddash", 8861], ["\\circledast", 8859], ["\\circledcirc", 8858], ["\\unlhd", 8884], ["\\unrhd", 8885] ], "mbin", "ams" ); defineSymbols([ ["\\surd", 8730], // From MnSymbol package ["\\infty", 8734], ["\\prime", 8242], ["\\doubleprime", 8243], // NOTE: Not in TeX, but Mathematica ["\\angle", 8736], ["`", 8216], ["\\$", 36], ["\\%", 37], ["\\_", 95], // Note: In TeX, greek symbols are only available in Math mode ["\\alpha", 945], ["\\beta", 946], ["\\gamma", 947], ["\\delta", 948], ["\\epsilon", 1013], ["\\varepsilon", 949], ["\\zeta", 950], ["\\eta", 951], ["\\theta", 952], ["\\vartheta", 977], ["\\iota", 953], ["\\kappa", 954], ["\\varkappa", 1008, "mord", "ams"], ["\\lambda", 955], ["\\mu", 956], ["\\nu", 957], ["\\xi", 958], ["\\omicron", 111], ["\\pi", 960], ["\\varpi", 982], ["\\rho", 961], ["\\varrho", 1009], ["\\sigma", 963], ["\\varsigma", 962], ["\\tau", 964], ["\\phi", 981], ["\\varphi", 966], ["\\upsilon", 965], ["\\chi", 967], ["\\psi", 968], ["\\omega", 969], ["\\Gamma", 915], ["\\Delta", 916], ["\\Theta", 920], ["\\Lambda", 923], ["\\Xi", 926], ["\\Pi", 928], ["\\Sigma", 931], ["\\Upsilon", 933], ["\\Phi", 934], ["\\Psi", 936], ["\\Omega", 937], // 'ams' Greek ["\\digamma", 989, "mord", "ams"], ["\\emptyset", 8709] ]); defineSymbols( [ ["=", 61], ["<", 60], ["\\lt", 60], [">", 62], ["\\gt", 62], ["\\le", 8804], ["\\leq", 8804], ["\\ge", 8805], ["\\geq", 8805], ["\\ll", 8810], ["\\gg", 8811], ["\\coloneq", 8788], // Prefered form as of Summer 2022. See § 3.7.3 https://ctan.math.illinois.edu/macros/latex/contrib/mathtools/mathtools.pdf) ["\\coloneqq", 8788], // Legacy form ["\\colonequals", 8788], // From the colonequals package ["\\measeq", 8797], // MEASSURED BY ["\\eqdef", 8798], ["\\questeq", 8799], // QUESTIONED EQUAL TO [":", 58], ["\\cong", 8773], ["\\equiv", 8801], ["\\prec", 8826], ["\\preceq", 10927], ["\\succ", 8827], ["\\succeq", 10928], ["\\perp", 8869], ["\\propto", 8733], ["\\Colon", 8759], ["\\smile", 8995], ["\\frown", 8994], ["\\sim", 8764], ["\\doteq", 8784], ["\\bowtie", 8904], ["\\Join", 8904], ["\\asymp", 8781], ["\\sqsubseteq", 8849], ["\\sqsupseteq", 8850], ["\\approx", 8776], // In TeX, '~' is a spacing command (non-breaking space). // However, '~' is used as an ASCII Math shortctut character, so define a \\~ // command which maps to the '~' character ["\\~", 126], ["\\leftrightarrow", 8596], ["\\Leftrightarrow", 8660], ["\\models", 8872], ["\\vdash", 8866], ["\\dashv", 8867], ["\\roundimplies", 10608], ["\\in", 8712], ["\\notin", 8713], // defineSymbol('\\not', 0x0338], // defineSymbol('\\not', 0xe020], ["\\ni", 8715], ["\\owns", 8715], ["\\subset", 8834], ["\\supset", 8835], ["\\subseteq", 8838], ["\\supseteq", 8839], ["\\differencedelta", 8710], ["\\mvert", 8739], ["\\parallel", 8741], ["\\simeq", 8771] ], "mrel" ); defineSymbols( [ ["\\lnot", 172], ["\\neg", 172], ["\\triangle", 9651], ["\\subsetneq", 8842], ["\\varsubsetneq", 57370], ["\\subsetneqq", 10955], ["\\varsubsetneqq", 57367], ["\\nsubset", 8836], // NOTE: Not TeX? ["\\nsupset", 8837], // NOTE: Not TeX? ["\\nsubseteq", 8840], ["\\nsupseteq", 8841] ], "mrel", "ams" ); defineSymbols([ ["\\wp", 8472], ["\\aleph", 8501] ]); defineSymbols( [ ["\\blacktriangle", 9650], ["\\hslash", 8463], ["\\Finv", 8498], ["\\Game", 8513], ["\\eth", 240], ["\\mho", 8487], ["\\Bbbk", 107], ["\\yen", 165], ["\\square", 9633], ["\\Box", 9633], ["\\blacksquare", 9632], ["\\circledS", 9416], ["\\circledR", 174], ["\\triangledown", 9661], ["\\blacktriangledown", 9660], ["\\checkmark", 10003], ["\\diagup", 9585], ["\\measuredangle", 8737], ["\\sphericalangle", 8738], ["\\backprime", 8245], ["\\backdoubleprime", 8246], ["\\Diamond", 9674], ["\\lozenge", 9674], ["\\blacklozenge", 10731], ["\\varnothing", 8709], ["\\complement", 8705], ["\\maltese", 10016], // 'ams' Hebrew ["\\beth", 8502], ["\\daleth", 8504], ["\\gimel", 8503] ], "mord", "ams" ); defineSymbols( [ // See http://tex.stackexchange.com/questions/41476/lengths-and-when-to-use-them ["\\ ", 160], ["~", 160] ], "space" ); defineFunction( ["!", ",", ":", ";", ">", "enskip", "enspace", "quad", "qquad"], "", { createAtom: (options) => new SpacingAtom(options) } ); defineFunction("space", "", { createAtom: (options) => new SpacingAtom(options) }); defineSymbols( [ ["\\colon", 58], ["\\cdotp", 8901], ["\\vdots", 8942, "mord"], ["\\ldotp", 46], [",", 44], [";", 59] ], "mpunct" ); defineSymbols( [ ["\\cdots", 8943], ["\\ddots", 8945], ["\\ldots", 8230], ["\\mathellipsis", 8230] ], "minner" ); defineSymbols([ ["\\/", 47], ["|", 8739, "mord"], ["\\imath", 305], ["\\jmath", 567], ["\\degree", 176], ["'", 8242], // Prime ['"', 8221] // Double Prime // defineSymbol( "\'', 0x2033, 'mord', MAIN], // Double Prime ]); // src/formats/atom-to-math-ml.ts var APPLY_FUNCTION = ""; var INVISIBLE_TIMES = ""; function xmlEscape(string) { return string.replace(/"/g, """).replace(/'/g, "'").replace(//g, ">"); } function makeID(id, options) { if (!id || !options.generateID) return ""; return ` extid="${id}"`; } function scanIdentifier(stream, final, options) { var _a3, _b3, _c2, _d2, _e, _f, _g, _h, _i, _j, _k; let result = false; final = final != null ? final : stream.atoms.length; let mathML = ""; let body = ""; let atom = stream.atoms[stream.index]; const variant = (_b3 = (_a3 = atom.style) == null ? void 0 : _a3.variant) != null ? _b3 : ""; const variantStyle = (_d2 = (_c2 = atom.style) == null ? void 0 : _c2.variantStyle) != null ? _d2 : ""; let variantProp = ""; if (variant || variantStyle) { const unicodeVariant = mathVariantToUnicode( atom.value, (_e = atom.style) == null ? void 0 : _e.variant, (_f = atom.style) == null ? void 0 : _f.variantStyle ); if (unicodeVariant !== atom.value) { stream.index += 1; mathML = `${unicodeVariant}`; if (!parseSubsup(mathML, stream, options)) { stream.mathML += mathML; stream.lastType = "mi"; } return true; } variantProp = (_g = { "upnormal": "normal", "boldnormal": "bold", "italicmain": "italic", "bolditalicmain": "bold-italic", "updouble-struck": "double-struck", "double-struck": "double-struck", "boldfraktur": "bold-fraktur", "calligraphic": "script", "upcalligraphic": "script", "script": "script", "boldscript": "bold-script", "boldcalligraphic": "bold-script", "fraktur": "fraktur", "upsans-serif": "sans-serif", "boldsans-serif": "bold-sans-serif", "italicsans-serif": "sans-serif-italic", "bolditalicsans-serif": "sans-serif-bold-italic", "monospace": "monospace" }[variantStyle + variant]) != null ? _g : ""; variantProp = ` mathvariant="${variantProp}"`; } const SPECIAL_IDENTIFIERS2 = { "\\exponentialE": "ⅇ", "\\imaginaryI": "ⅈ", "\\differentialD": "ⅆ", "\\capitalDifferentialD": "ⅅ", "\\alpha": "α", "\\pi": "π", "\\infty": "∞", "\\forall": "∀", "\\nexists": "∄", "\\exists": "∃", "\\hbar": "\u210F", "\\cdotp": "\u22C5", "\\ldots": "\u2026", "\\cdots": "\u22EF", "\\ddots": "\u22F1", "\\vdots": "\u22EE", "\\ldotp": "." }; if (atom.command === "!") { stream.index += 1; mathML = "!"; if (!parseSubsup(mathML, stream, options)) { stream.mathML += mathML; stream.lastType = "mo"; } return true; } if (SPECIAL_IDENTIFIERS2[atom.command]) { stream.index += 1; let mathML2 = `${SPECIAL_IDENTIFIERS2[atom.command]}`; if (stream.lastType === "mi" || stream.lastType === "mn" || stream.lastType === "mtext" || stream.lastType === "fence") mathML2 = INVISIBLE_TIMES + mathML2; if (!parseSubsup(mathML2, stream, options)) { stream.mathML += mathML2; stream.lastType = "mi"; } return true; } if (atom.command === "\\operatorname") { body = toString2(atom.body); stream.index += 1; } else { if (variant || variantStyle) { while (stream.index < final && (atom.type === "mord" || atom.type === "macro") && !atom.isDigit() && variant === ((_i = (_h = atom.style) == null ? void 0 : _h.variant) != null ? _i : "") && variantStyle === ((_k = (_j = atom.style) == null ? void 0 : _j.variantStyle) != null ? _k : "")) { body += toString2([atom]); stream.index += 1; atom = stream.atoms[stream.index]; } } else if ((atom.type === "mord" || atom.type === "macro") && !atom.isDigit()) { body += toString2([atom]); stream.index += 1; } } if (body.length > 0) { result = true; mathML = `${body}`; const lastType = stream.lastType; if (mathML.endsWith(">f") || mathML.endsWith(">g")) { mathML += APPLY_FUNCTION; stream.lastType = "applyfunction"; } else stream.lastType = /^(.*)<\/mo>$/.test(mathML) ? "mo" : "mi"; if (!parseSubsup(mathML, stream, options)) { if (lastType === "mi" || lastType === "mn" || lastType === "mtext" || lastType === "fence") mathML = INVISIBLE_TIMES + mathML; stream.mathML += mathML; } } return result; } function isSuperscriptAtom(stream) { return stream.index < stream.atoms.length && stream.atoms[stream.index].superscript && stream.atoms[stream.index].type === "subsup"; } function indexOfSuperscriptInNumber(stream) { let result = -1; let i = stream.index; let done = false; let found = false; while (i < stream.atoms.length && !done && !found) { const atom = stream.atoms[i]; done = !atom.isDigit(); found = !done && atom.superscript !== void 0; i++; } if (found) result = i - 1; return result; } function parseSubsup(base, stream, options) { var _a3; let atom = stream.atoms[stream.index - 1]; if (!atom) return false; if (!atom.superscript && !atom.subscript) { if (((_a3 = stream.atoms[stream.index]) == null ? void 0 : _a3.type) === "subsup") { atom = stream.atoms[stream.index]; stream.index += 1; } else return false; } const lastType = stream.lastType; stream.lastType = ""; const superscript = toMathML(atom.superscript, options); stream.lastType = ""; const subscript = toMathML(atom.subscript, options); stream.lastType = lastType; if (!superscript && !subscript) return false; let mathML = ""; if (superscript && subscript) mathML = `${base}${subscript}${superscript}`; else if (superscript) mathML = `${base}${superscript}`; else if (subscript) mathML = `${base}${subscript}`; stream.mathML += mathML; stream.lastType = ""; return true; } function scanText(stream, final, options) { final = final != null ? final : stream.atoms.length; const initial = stream.index; let mathML = ""; while (stream.index < final && stream.atoms[stream.index].mode === "text") { mathML += stream.atoms[stream.index].value ? stream.atoms[stream.index].value : " "; stream.index += 1; } if (mathML.length > 0) { stream.mathML += `${mathML}`; stream.lastType = "mtext"; return true; } return false; } function scanNumber(stream, final, options) { final = final != null ? final : stream.atoms.length; const initial = stream.index; let mathML = ""; let superscript = indexOfSuperscriptInNumber(stream); if (superscript >= 0 && superscript < final) final = superscript; while (stream.index < final && stream.atoms[stream.index].isDigit()) { mathML += stream.atoms[stream.index].asDigit(); stream.index += 1; } if (mathML.length <= 0) return false; mathML = "" + mathML + ""; if (superscript < 0 && isSuperscriptAtom(stream)) { superscript = stream.index; stream.index += 1; } if (!parseSubsup(mathML, stream, options)) { stream.mathML += mathML; stream.lastType = "mn"; } return true; } function scanFence(stream, final, options) { let result = false; final = final != null ? final : stream.atoms.length; let mathML = ""; let lastType = ""; if (stream.index < final && stream.atoms[stream.index].type === "mopen") { let found = false; let depth = 0; const openIndex = stream.index; let closeIndex = -1; let index = openIndex + 1; while (index < final && !found) { if (stream.atoms[index].type === "mopen") depth += 1; else if (stream.atoms[index].type === "mclose") depth -= 1; if (depth === -1) { found = true; closeIndex = index; } index += 1; } if (found) { mathML = ""; mathML += toMo(stream.atoms[openIndex], options); mathML += toMathML(stream.atoms, options, openIndex + 1, closeIndex); mathML += toMo(stream.atoms[closeIndex], options); mathML += ""; stream.index = closeIndex + 1; if (stream.lastType === "mi" || stream.lastType === "mn" || stream.lastType === "mfrac" || stream.lastType === "fence") stream.mathML += INVISIBLE_TIMES; if (parseSubsup(mathML, stream, options)) { result = true; stream.lastType = ""; mathML = ""; } lastType = "fence"; } } if (mathML.length > 0) { result = true; stream.mathML += mathML; stream.lastType = lastType; } return result; } function scanOperator(stream, final, options) { let result = false; final = final != null ? final : stream.atoms.length; let mathML = ""; let lastType = ""; const atom = stream.atoms[stream.index]; if (!atom) return false; const SPECIAL_OPERATORS2 = { "\\ne": "≠", "\\neq": "&neq;", "\\pm": "±", "\\times": "×", "\\colon": ":", "\\vert": "|", "\\Vert": "\u2225", "\\mid": "\u2223", "\\{": "{", "\\}": "}", "\\lbrace": "{", "\\rbrace": "}", "\\lbrack": "[", "\\rbrack": "]", "\\lparen": "(", "\\rparen": ")", "\\langle": "\u27E8", "\\rangle": "\u27E9", "\\lfloor": "\u230A", "\\rfloor": "\u230B", "\\lceil": "\u2308", "\\rceil": "\u2309" }; if (SPECIAL_OPERATORS2[atom.command]) { stream.index += 1; const mathML2 = `${SPECIAL_OPERATORS2[atom.command]}`; if (!parseSubsup(mathML2, stream, options)) { stream.mathML += mathML2; stream.lastType = "mo"; } return true; } if (stream.index < final && (atom.type === "mbin" || atom.type === "mrel")) { mathML += atomToMathML(stream.atoms[stream.index], options); stream.index += 1; lastType = "mo"; } else if (stream.index < final && (atom.type === "mop" || atom.type === "operator" || atom.type === "extensible-symbol")) { if (atom.subsupPlacement === "over-under" && (atom.superscript || atom.subscript)) { const op = toMo(atom, options); if (atom.superscript && atom.subscript) { mathML += "" + op; mathML += toMathML(atom.subscript, options); mathML += toMathML(atom.superscript, options); mathML += ""; } else if (atom.superscript) { mathML += "" + op; mathML += toMathML(atom.superscript, options); mathML += ""; } else if (atom.subscript) { mathML += "" + op; mathML += toMathML(atom.subscript, options); mathML += ""; } stream.mathML += mathML; stream.lastType = "mo"; stream.index += 1; return true; } { const atom2 = stream.atoms[stream.index]; const isUnit = atom2.value === "\\operatorname"; const op = isUnit ? '" + toString2(atom2.value) + "" : toMo(atom2, options); mathML += op; if (!isUnit && !/^(.*)<\/mo>$/.test(op)) { mathML += APPLY_FUNCTION; lastType = "applyfunction"; } else lastType = isUnit ? "mi" : "mo"; } if ((stream.lastType === "mi" || stream.lastType === "mn") && !/^(.*)<\/mo>$/.test(mathML)) mathML = INVISIBLE_TIMES + mathML; stream.index += 1; } if (mathML.length > 0) { result = true; if (!parseSubsup(mathML, stream, options)) { stream.mathML += mathML; stream.lastType = lastType; } } return result; } function toMathML(input, options, initial, final) { options != null ? options : options = {}; const result = { atoms: [], index: initial != null ? initial : 0, mathML: "", lastType: "" }; if (typeof input === "number" || typeof input === "boolean") result.mathML = input.toString(); else if (typeof input === "string") result.mathML = input; else if (input instanceof Atom) result.mathML = atomToMathML(input, options); else if (Array.isArray(input)) { result.atoms = input; let count = 0; final = final ? final : input ? input.length : 0; while (result.index < final) { if (scanText(result, final, options) || scanNumber(result, final, options) || scanIdentifier(result, final, options) || scanOperator(result, final, options) || scanFence(result, final, options)) count += 1; else if (result.index < final) { let mathML = atomToMathML(result.atoms[result.index], options); if (result.lastType === "mn" && mathML.length > 0 && result.atoms[result.index].type === "genfrac") { mathML = "" + mathML; } if (result.atoms[result.index].type === "genfrac") result.lastType = "mfrac"; else result.lastType = ""; result.index += 1; if (parseSubsup(mathML, result, options)) count += 1; else { if (mathML.length > 0) { result.mathML += mathML; count += 1; } } } } if (count > 1) result.mathML = "" + result.mathML + ""; } return result.mathML; } function toMo(atom, options) { let result = ""; const body = toString2(atom.value); if (body) result = "" + body + ""; return result; } function toString2(atoms) { if (!atoms) return ""; if (typeof atoms === "string") return xmlEscape(atoms); if (!Array.isArray(atoms) && typeof atoms.body === "string") return xmlEscape(atoms.body); let result = ""; for (const atom of atoms) if (typeof atom.value === "string") result += atom.value; return xmlEscape(result); } function atomToMathML(atom, options) { var _a3, _b3, _c2, _d2, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v; if (atom.mode === "text") return `${atom.value}`; const SVG_CODE_POINTS = { widehat: "^", widecheck: "\u02C7", widetilde: "~", utilde: "~", overleftarrow: "\u2190", underleftarrow: "\u2190", xleftarrow: "\u2190", longleftarrow: "\u2190", overrightarrow: "\u2192", underrightarrow: "\u2192", xrightarrow: "\u2192", longrightarrow: "\u2192", underbrace: "\u23DF", overbrace: "\u23DE", overgroup: "\u23E0", undergroup: "\u23E1", overleftrightarrow: "\u2194", underleftrightarrow: "\u2194", xleftrightarrow: "\u2194", Overrightarrow: "\u21D2", xRightarrow: "\u21D2", overleftharpoon: "\u21BC", xleftharpoonup: "\u21BC", overrightharpoon: "\u21C0", xrightharpoonup: "\u21C0", xLeftarrow: "\u21D0", xLeftrightarrow: "\u21D4", xhookleftarrow: "\u21A9", xhookrightarrow: "\u21AA", xmapsto: "\u21A6", xrightharpoondown: "\u21C1", xleftharpoondown: "\u21BD", xrightleftharpoons: "\u21CC", longrightleftharpoons: "\u21CC", xleftrightharpoons: "\u21CB", xtwoheadleftarrow: "\u219E", xtwoheadrightarrow: "\u21A0", xlongequal: "=", xtofrom: "\u21C4", xleftrightarrows: "\u21C4", xRightleftharpoons: "\u21CC", // Not a perfect match. longRightleftharpoons: "\u21CC", // Not a perfect match. xLeftrightharpoons: "\u21CB", // None better available. longLeftrightharpoons: "\u21CB" // None better available. }; const SPACING = { "\\!": -3 / 18, "\\ ": 6 / 18, "\\,": 3 / 18, "\\:": 4 / 18, "\\>": 4 / 18, "\\;": 5 / 18, "\\enspace": 0.5, "\\quad": 1, "\\qquad": 2, "\\enskip": 0.5 }; let result = ""; let sep = ""; let col; let row; let i; let underscript; let overscript; let body; const { command } = atom; if (atom.command === "\\error") { return `${toMathML( atom.body, options )}`; } const SPECIAL_DELIMS = { "\\vert": "|", "\\Vert": "\u2225", "\\mid": "\u2223", "\\lbrack": "[", "\\rbrack": "]", "\\{": "{", "\\}": "}", "\\lbrace": "{", "\\rbrace": "}", "\\lparen": "(", "\\rparen": ")", "\\langle": "\u27E8", "\\rangle": "\u27E9", "\\lfloor": "\u230A", "\\rfloor": "\u230B", "\\lceil": "\u2308", "\\rceil": "\u2309" }; const SPECIAL_ACCENTS = { "\\vec": "⃗", "\\acute": "´", "\\grave": "`", "\\dot": "˙", "\\ddot": "¨", "\\tilde": "~", "\\bar": "¯", "\\breve": "˘", "\\check": "ˇ", "\\hat": "^" }; switch (atom.type) { case "first": break; case "group": case "root": result = toMathML(atom.body, options); break; case "array": if (atom.leftDelim && atom.leftDelim !== "." || atom.rightDelim && atom.rightDelim !== ".") { result += ""; if (atom.leftDelim && atom.leftDelim !== ".") { result += "" + (SPECIAL_DELIMS[atom.leftDelim] || atom.leftDelim) + ""; } } result += ""; } result += ""; } result += ""; if (atom.leftDelim && atom.leftDelim !== "." || atom.rightDelim && atom.rightDelim !== ".") { if (atom.rightDelim && atom.rightDelim !== ".") { result += "" + (SPECIAL_DELIMS[atom.leftDelim] || atom.rightDelim) + ""; } result += ""; } break; case "genfrac": if (atom.leftDelim || atom.rightDelim) result += ""; if (atom.leftDelim && atom.leftDelim !== ".") { result += "" + (SPECIAL_DELIMS[atom.leftDelim] || atom.leftDelim) + ""; } if (atom.hasBarLine) { result += ""; result += toMathML(atom.above, options) || " "; result += toMathML(atom.below, options) || " "; result += ""; } else { result += ""; result += "" + toMathML(atom.above, options) + ""; result += "" + toMathML(atom.below, options) + ""; result += ""; } if (atom.rightDelim && atom.rightDelim !== ".") { result += "" + (SPECIAL_DELIMS[atom.rightDelim] || atom.rightDelim) + ""; } if (atom.leftDelim || atom.rightDelim) result += ""; break; case "surd": if (!atom.hasEmptyBranch("above")) { result += ""; result += toMathML(atom.body, options); result += toMathML(atom.above, options); result += ""; } else { result += ""; result += toMathML(atom.body, options); result += ""; } break; case "leftright": const leftrightAtom = atom; const lDelim = leftrightAtom.leftDelim; result = ""; if (lDelim && lDelim !== ".") { result += `${(_a3 = SPECIAL_DELIMS[lDelim]) != null ? _a3 : lDelim}`; } if (atom.body) result += toMathML(atom.body, options); const rDelim = leftrightAtom.matchingRightDelim(); if (rDelim && rDelim !== ".") { result += `${(_b3 = SPECIAL_DELIMS[rDelim]) != null ? _b3 : rDelim}`; } result += ""; break; case "sizeddelim": case "delim": result += `${SPECIAL_DELIMS[atom.value] || atom.value}`; break; case "accent": result += '"; result += toMathML(atom.body, options); result += "" + (SPECIAL_ACCENTS[command] || atom.accent) + ""; result += ""; break; case "line": case "overlap": break; case "overunder": overscript = atom.above; underscript = atom.below; if ((atom.svgAbove || overscript) && (atom.svgBelow || underscript)) body = atom.body; else if (overscript && overscript.length > 0) { body = atom.body; if ((_d2 = (_c2 = atom.body) == null ? void 0 : _c2[0]) == null ? void 0 : _d2.below) { underscript = atom.body[0].below; body = atom.body[0].body; } else if (((_f = (_e = atom.body) == null ? void 0 : _e[0]) == null ? void 0 : _f.type) === "first" && ((_h = (_g = atom.body) == null ? void 0 : _g[1]) == null ? void 0 : _h.below)) { underscript = atom.body[1].below; body = atom.body[1].body; } } else if (underscript && underscript.length > 0) { body = atom.body; if ((_j = (_i = atom.body) == null ? void 0 : _i[0]) == null ? void 0 : _j.above) { overscript = atom.body[0].above; body = atom.body[0].body; } else if (((_l = (_k = atom.body) == null ? void 0 : _k[0]) == null ? void 0 : _l.type) === "first" && ((_n = (_m = atom.body) == null ? void 0 : _m[1]) == null ? void 0 : _n.above)) { overscript = atom.body[1].overscript; body = atom.body[1].body; } } if ((atom.svgAbove || overscript) && (atom.svgBelow || underscript)) { result += ``; result += (_o = SVG_CODE_POINTS[atom.svgBody]) != null ? _o : toMathML(body, options); result += (_p = SVG_CODE_POINTS[atom.svgBelow]) != null ? _p : toMathML(underscript, options); result += (_q = SVG_CODE_POINTS[atom.svgAbove]) != null ? _q : toMathML(overscript, options); result += ""; } else if (atom.svgAbove || overscript) { result += `` + ((_r = SVG_CODE_POINTS[atom.svgBody]) != null ? _r : toMathML(body, options)); result += (_s = SVG_CODE_POINTS[atom.svgAbove]) != null ? _s : toMathML(overscript, options); result += ""; } else if (atom.svgBelow || underscript) { result += `` + ((_t = SVG_CODE_POINTS[atom.svgBody]) != null ? _t : toMathML(body, options)); result += (_u = SVG_CODE_POINTS[atom.svgBelow]) != null ? _u : toMathML(underscript, options); result += ""; } break; case "placeholder": result += "?"; break; case "mord": { result = typeof atom.value === "string" ? atom.value : command; if (command === "\\char") { result = "&#x" + ("000000" + atom.args[0].number.toString(16)).slice(-4) + ";"; } else if (result.length > 0 && result.startsWith("\\")) { if (typeof atom.value === "string" && atom.value.charCodeAt(0) > 255) { result = "&#x" + ("000000" + atom.value.charCodeAt(0).toString(16)).slice(-4) + ";"; } else if (typeof atom.value === "string") result = atom.value.charAt(0); else { console.error("Did not expect this"); result = ""; } } const tag = /\d/.test(result) ? "mn" : "mi"; result = `<${tag}${makeID(atom.id, options)}>${xmlEscape( result )}`; break; } case "mbin": case "mrel": case "minner": result = toMo(atom, options); break; case "mpunct": result = '" + command + ""; break; case "mop": case "operator": case "extensible-symbol": if (atom.body !== "\u200B") { result = ""; result += command === "\\operatorname" ? atom.body : command || atom.body; result += ""; } break; case "box": result = '" + toMathML(atom.body, options) + ""; break; case "spacing": result += ''; break; case "enclose": result = '' + toMathML(atom.body, options) + ""; break; case "prompt": result = '' + toMathML(atom.body, options) + ""; break; case "space": result += " "; break; case "subsup": break; case "phantom": break; case "composition": break; case "rule": break; case "chem": break; case "mopen": result += toMo(atom, options); break; case "mclose": result += toMo(atom, options); break; case "macro": { const body2 = atom.command + toString2(atom.macroArgs); if (body2) result += `${body2}`; } break; case "latexgroup": result += toMathML(atom.body, options); break; case "latex": result += "" + atom.value + ""; break; case "tooltip": result += toMathML(atom.body, options); break; case "text": result += `${atom.value}`; break; default: if (atom.command === "\\displaystyle") { return `${toMathML(atom.body, options)}`; } if (atom.command === "\\textstyle") { return `${toMathML(atom.body, options)}`; } console.info("Unexpected element in conversion to MathML:", atom); } return result; } // src/formats/atom-to-speakable-text.ts var PRONUNCIATION = { "\\alpha": "alpha ", "\\mu": "mew ", "\\sigma": "sigma ", "\\pi": "pie ", "\\imaginaryI": "imaginary eye ", "\\imaginaryJ": "imaginary jay ", "\\sum": "Summation ", "\\prod": "Product ", "+": "plus ", "-": "minus ", ";": ' semi-colon ', ",": ' comma ', "|": 'Vertical bar', "(": 'Open paren. ', ")": ' Close paren. ', "=": "equals ", "<": "is less than ", "\\lt": "is less than ", "<=": "is less than or equal to ", "\\le": "is less than or equal to ", "\\gt": "is greater than ", ">": "is greater than ", "\\pm": "plus or minus", "\\mp": "minus or plus", "\\ge": "is greater than or equal to ", "\\geq": "is greater than or equal to ", "\\leq": "is less than or equal to ", "\\ne": "is not equal to ", "\\neq": "is not equal to ", "!": "factorial ", "\\sin": "sine ", "\\cos": "cosine ", "\u200B": "", "\u2212": "minus ", ":": ' such that ', "\\colon": ' such that ', "\\hbar": "etch bar ", "\\iff": 'if, and only if, ', "\\Longleftrightarrow": 'if, and only if, ', "\\land": "and ", "\\lor": "or ", "\\neg": "not ", "\\div": "divided by ", "\\forall": "for all ", "\\exists": "there exists ", "\\nexists": "there does not exists ", "\\in": "element of ", "\\N": 'the set n', "\\C": 'the set c', "\\Z": 'the set z', "\\Q": 'the set q', "\\infty": "infinity ", "\\nabla": "nabla ", "\\partial": "partial derivative of ", "\\cdot": "times ", "\\cdots": "dot dot dot ", "\\Rightarrow": "implies ", "\\lparen": 'open paren', "\\rparen": 'close paren', "\\lbrace": 'open brace', "\\{": 'open brace', "\\rbrace": 'close brace', "\\}": 'close brace', "\\langle": 'left angle bracket', "\\rangle": 'right angle bracket', "\\lfloor": 'open floor', "\\rfloor": 'close floor', "\\lceil": 'open ceiling', "\\rceil": 'close ceiling', "\\vert": 'vertical bar', "\\mvert": 'divides', "\\lvert": 'left vertical bar', "\\rvert": 'right vertical bar', // '\\lbrack': 'left bracket', // '\\rbrack': 'right bracket', "\\lbrack": ' open square bracket ', "\\rbrack": ' close square bracket ', // Need to add code to detect singluar/plural. Until then spoken as plural since that is vastly more common // note: need to worry about intervening ⁢. // note: need to also do this when in numerator of fraction and number preceeds fraction // note: need to do this for "mm": "millimeters", "cm": "centimeters", "km": "kilometers", "kg": "kilograms" }; var ENVIRONMENTS_NAMES = { "array": "array", "matrix": "matrix", "pmatrix": "parenthesis matrix", "bmatrix": "square brackets matrix", "Bmatrix": "braces matrix", "vmatrix": "bars matrix", "Vmatrix": "double bars matrix", "matrix*": "matrix", "smallmatrix": "small matrix" }; function getSpokenName(latex) { let result = ""; if (latex.startsWith("\\")) result = " " + latex.replace("\\", "") + " "; return result; } function isAtomic(atoms) { let count = 0; if (isArray(atoms)) { for (const atom of atoms) if (atom.type !== "first") count += 1; } return count === 1; } function atomicID(atoms) { if (isArray(atoms)) { for (const atom of atoms) if (atom.type !== "first" && atom.id) return atom.id.toString(); } return ""; } function atomicValue(atoms) { let result = ""; if (isArray(atoms)) { for (const atom of atoms) { if (atom.type !== "first" && typeof atom.value === "string") result += atom.value; } } return result; } function atomsAsText(atoms) { if (!atoms) return ""; return atoms.map((atom) => atom.value).join(""); } function atomToSpeakableFragment(mode, atom) { var _a3, _b3, _c2, _d2, _e; function letter(c) { if (!window.MathfieldElement.textToSpeechMarkup) { if (/[a-z]/.test(c)) return " '" + c.toUpperCase() + "'"; if (/[A-Z]/.test(c)) return " 'capital " + c.toUpperCase() + "'"; return c; } if (/[a-z]/.test(c)) return ` ${c}`; if (/[A-Z]/.test(c)) return `capital ${c.toLowerCase()}`; return c; } function emph(s) { return "" + s + ""; } if (!atom) return ""; let result = ""; if (isArray(atom)) { let isInDigitRun = false; let isInTextRun = false; for (let i = 0; i < atom.length; i++) { if (atom[i].type === "first") continue; if (atom[i].mode !== "text") isInTextRun = false; if (i < atom.length - 2 && atom[i].type === "mopen" && atom[i + 2].type === "mclose" && atom[i + 1].type === "mord") { result += " of "; result += emph(atomToSpeakableFragment(mode, atom[i + 1])); i += 2; } else if (atom[i].mode === "text") { if (isInTextRun) result += (_a3 = atom[i].value) != null ? _a3 : " "; else { isInTextRun = true; result += atomToSpeakableFragment("text", atom[i]); } } else if (atom[i].isDigit()) { if (isInDigitRun) result += atom[i].asDigit(); else { isInDigitRun = true; result += atomToSpeakableFragment(mode, atom[i]); } } else { isInDigitRun = false; result += atomToSpeakableFragment(mode, atom[i]); } } } else if (atom.mode === "text") { if (atom.id && mode === "math") result += ''; result += atom.value; } else { if (atom.id && mode === "math") result += ''; let numer = ""; let denom = ""; let body = ""; let supsubHandled = false; const { command } = atom; switch (command) { case "\\vec": return "vector " + atomToSpeakableFragment(mode, atom.body); case "\\acute": return atomToSpeakableFragment(mode, atom.body) + " acute"; case "\\grave": return atomToSpeakableFragment(mode, atom.body) + " grave"; case "\\dot": return "dot over" + atomToSpeakableFragment(mode, atom.body); case "\\ddot": return "double dot over" + atomToSpeakableFragment(mode, atom.body); case "\\mathring": return "ring over" + atomToSpeakableFragment(mode, atom.body); case "\\tilde": case "\\widetilde": return "tilde over" + atomToSpeakableFragment(mode, atom.body); case "\\bar": return atomToSpeakableFragment(mode, atom.body) + " bar"; case "\\breve": return atomToSpeakableFragment(mode, atom.body) + " breve"; case "\\check": case "\\widecheck": return "check over " + atomToSpeakableFragment(mode, atom.body); case "\\hat": case "\\widehat": return "hat over" + atomToSpeakableFragment(mode, atom.body); case "\\overarc": case "\\overparen": case "\\wideparen": return "arc over " + atomToSpeakableFragment(mode, atom.body); case "\\underarc": case "\\underparen": return "arc under " + atomToSpeakableFragment(mode, atom.body); } switch (atom.type) { case "prompt": const input = atom.body.length > 1 ? 'start input . ' + atomToSpeakableFragment(mode, atom.body) + '. end input' : "blank"; result += ' ' + input + '. ' + ((_b3 = atom.correctness) != null ? _b3 : "") + ' . '; break; case "array": const array = atom.array; const environment = atom.environmentName; if (Object.keys(ENVIRONMENTS_NAMES).includes(environment)) { result += ` begin ${ENVIRONMENTS_NAMES[environment]} `; for (let i = 0; i < array.length; i++) { if (i > 0) result += ","; result += ` row ${i + 1} `; for (let j = 0; j < array[i].length; j++) { if (j > 0) result += ","; result += ` column ${j + 1}: `; result += atomToSpeakableFragment("math", array[i][j]); } } result += ` end ${ENVIRONMENTS_NAMES[environment]} `; } break; case "group": if (command === "\\ne") result += " not equal "; else if (command === "\\not") { result += " not "; result += atomToSpeakableFragment("math", atom.body); } else { result += atomToSpeakableFragment("math", atom.body); } break; case "root": result += atomToSpeakableFragment("math", atom.body); break; case "genfrac": numer = atomToSpeakableFragment("math", atom.above); denom = atomToSpeakableFragment("math", atom.below); if (isAtomic(atom.above) && isAtomic(atom.below)) { const COMMON_FRACTIONS = { "1/2": " half ", "1/3": " one third ", "2/3": " two third", "1/4": " one quarter ", "3/4": " three quarter ", "1/5": " one fifth ", "2/5": " two fifths ", "3/5": " three fifths ", "4/5": " four fifths ", "1/6": " one sixth ", "5/6": " five sixths ", "1/8": " one eight ", "3/8": " three eights ", "5/8": " five eights ", "7/8": " seven eights ", "1/9": " one ninth ", "2/9": " two ninths ", "4/9": " four ninths ", "5/9": " five ninths ", "7/9": " seven ninths ", "8/9": " eight ninths " // '1/10': ' one tenth ', // '1/12': ' one twelfth ', // 'x/2': ' X over 2', }; const commonFraction = COMMON_FRACTIONS[atomicValue(atom.above) + "/" + atomicValue(atom.below)]; if (commonFraction) result = commonFraction; else result += numer + " over " + denom; } else { result += ' the fraction ' + numer + ' over ' + denom + '. End fraction.'; } break; case "surd": body = atomToSpeakableFragment("math", atom.body); if (atom.hasEmptyBranch("above")) { result += isAtomic(atom.body) ? " the square root of " + body + " , " : ' the square root of ' + body + '. End square root'; } else { let index = atomToSpeakableFragment("math", atom.above); index = index.trim(); const index2 = index.replace(//g, ""); if (index2 === "3") { result += ' the cube root of ' + body + '. End cube root'; } else if (index2 === "n") { result += ' the nth root of ' + body + '. End root'; } else { result += ' the root with index: ' + index + ', of ' + body + '. End root'; } } break; case "leftright": { const delimAtom = atom; result += (_c2 = delimAtom.leftDelim ? PRONUNCIATION[delimAtom.leftDelim] : void 0) != null ? _c2 : delimAtom.leftDelim; result += atomToSpeakableFragment("math", atom.body); result += (_d2 = delimAtom.rightDelim ? PRONUNCIATION[delimAtom.rightDelim] : void 0) != null ? _d2 : delimAtom.rightDelim; } break; case "rule": break; case "overunder": break; case "overlap": break; case "macro": const macroName = command.replace(/^\\/g, ""); const macro = getMacros()[macroName]; if (macro) { if (macro == null ? void 0 : macro.expand) result += atomToSpeakableFragment("math", atom.body); else result += `${macroName} `; } break; case "placeholder": result += "placeholder "; break; case "delim": case "sizeddelim": case "mord": case "minner": case "mbin": case "mrel": case "mpunct": case "mopen": case "mclose": { if (command === "\\mathbin" || command === "\\mathrel" || command === "\\mathopen" || command === "\\mathclose" || command === "\\mathpunct" || command === "\\mathord" || command === "\\mathinner") { result = atomToSpeakableFragment(mode, atom.body); break; } let atomValue = atom.isDigit() ? atom.asDigit() : atom.value; let latexValue = atom.command; if (atom.type === "delim" || atom.type === "sizeddelim") { latexValue = atom.value; atomValue = latexValue; } if (mode === "text") result += atomValue; else { if (atom.type === "mbin") result += ''; if (atomValue) { const value = PRONUNCIATION[atomValue] || (latexValue ? PRONUNCIATION[latexValue.trim()] : ""); if (value) result += " " + value; else { const spokenName = latexValue ? getSpokenName(latexValue.trim()) : ""; result += spokenName ? spokenName : letter(atomValue); } } else result += atomToSpeakableFragment("math", atom.body); if (atom.type === "mbin") result += ''; } break; } case "mop": case "operator": case "extensible-symbol": if (atom.value !== "\u200B") { const trimLatex = atom.command; if (trimLatex === "\\sum") { if (!atom.hasEmptyBranch("superscript") && !atom.hasEmptyBranch("subscript")) { let sup = atomToSpeakableFragment("math", atom.superscript); sup = sup.trim(); let sub = atomToSpeakableFragment("math", atom.subscript); sub = sub.trim(); result += ' the summation from ' + sub + ' to ' + sup + ' of '; supsubHandled = true; } else if (!atom.hasEmptyBranch("subscript")) { let sub = atomToSpeakableFragment("math", atom.subscript); sub = sub.trim(); result += ' the summation from ' + sub + ' of '; supsubHandled = true; } else result += " the summation of"; } else if (trimLatex === "\\prod") { if (!atom.hasEmptyBranch("superscript") && !atom.hasEmptyBranch("subscript")) { let sup = atomToSpeakableFragment("math", atom.superscript); sup = sup.trim(); let sub = atomToSpeakableFragment("math", atom.subscript); sub = sub.trim(); result += ' the product from ' + sub + ' to ' + sup + ' of '; supsubHandled = true; } else if (!atom.hasEmptyBranch("subscript")) { let sub = atomToSpeakableFragment("math", atom.subscript); sub = sub.trim(); result += ' the product from ' + sub + ' of '; supsubHandled = true; } else result += " the product of "; } else if (trimLatex === "\\int") { if (!atom.hasEmptyBranch("superscript") && !atom.hasEmptyBranch("subscript")) { let sup = atomToSpeakableFragment("math", atom.superscript); sup = sup.trim(); let sub = atomToSpeakableFragment("math", atom.subscript); sub = sub.trim(); result += ' the integral from ' + emph(sub) + ' to ' + emph(sup) + ' of '; supsubHandled = true; } else result += ' the integral of '; } else if (typeof atom.value === "string") { const value = (_e = PRONUNCIATION[atom.value]) != null ? _e : atom.command ? PRONUNCIATION[atom.command] : void 0; result += value ? value : " " + atom.value; } else if (atom.command) { if (atom.command === "\\mathop") result += atomToSpeakableFragment("math", atom.body); else if (atom.command === "\\operatorname") result += atomsAsText(atom.body); else { result += atom.command.startsWith("\\") ? " " + atom.command.slice(1) : " " + atom.command; } } } break; case "enclose": body = atomToSpeakableFragment("math", atom.body); result += " crossed out " + body + ". End crossed out."; break; case "space": case "spacing": break; } if (!supsubHandled && !atom.hasEmptyBranch("superscript")) { let sup = atomToSpeakableFragment(mode, atom.superscript); sup = sup.trim(); const sup2 = sup.replace(/<[^>]*>/g, ""); if (isAtomic(atom.superscript)) { if (mode === "math") { const id = atomicID(atom.superscript); if (id) result += ''; } if (sup2 === "\u2032") result += " prime "; else if (sup2 === "2") result += " squared "; else if (sup2 === "3") result += " cubed "; else if (Number.isNaN(Number.parseInt(sup2))) result += " to the " + sup + "; "; else { result += ' to the ' + sup2 + " power; "; } } else if (Number.isNaN(Number.parseInt(sup2))) result += " raised to the " + sup + "; "; else { result += ' raised to the ' + sup2 + " power; "; } } if (!supsubHandled && !atom.hasEmptyBranch("subscript")) { let sub = atomToSpeakableFragment("math", atom.subscript); sub = sub.trim(); result += isAtomic(atom.subscript) ? " sub " + sub : " subscript " + sub + ". End subscript. "; } } return result; } function atomToSpeakableText(atoms) { var _a3, _b3; if (window.MathfieldElement.textToSpeechRules === "sre" && ("sre" in window || "SRE" in window)) { const mathML = toMathML(atoms); if (mathML) { if (window.MathfieldElement.textToSpeechMarkup) { window.MathfieldElement.textToSpeechRulesOptions = (_a3 = window.MathfieldElement.textToSpeechRulesOptions) != null ? _a3 : {}; window.MathfieldElement.textToSpeechRulesOptions = __spreadProps(__spreadValues({}, window.MathfieldElement.textToSpeechRulesOptions), { markup: window.MathfieldElement.textToSpeechMarkup }); if (window.MathfieldElement.textToSpeechRulesOptions.markup === "ssml") { window.MathfieldElement.textToSpeechRulesOptions = __spreadProps(__spreadValues({}, window.MathfieldElement.textToSpeechRulesOptions), { markup: "ssml_step" }); } window.MathfieldElement.textToSpeechRulesOptions = __spreadProps(__spreadValues({}, window.MathfieldElement.textToSpeechRulesOptions), { rate: window.MathfieldElement.speechEngineRate }); } const SRE = (_b3 = window["SRE"]) != null ? _b3 : window.sre.System.getInstance(); if (window.MathfieldElement.textToSpeechRulesOptions) SRE.setupEngine(window.MathfieldElement.textToSpeechRulesOptions); let result2 = ""; try { result2 = SRE.toSpeech(mathML); } catch (e) { console.error( `MathLive 0.98.5: \`SRE.toSpeech()\` runtime error`, e ); } return result2; } return ""; } let result = atomToSpeakableFragment("math", atoms); if (window.MathfieldElement.textToSpeechMarkup === "ssml") { let prosody = ""; if (window.MathfieldElement.speechEngineRate) { prosody = ''; } result = `` + prosody + "

    " + result + "

    " + (prosody ? "
    " : "") + ""; } else if (window.MathfieldElement.textToSpeechMarkup === "mac" && osPlatform() === "macos") { result = result.replace(//g, "").replace(//g, "[[emph+]]").replace(/<\/emphasis>/g, "").replace(//g, "[[slc $1]]").replace(/]*>/g, "").replace(/<\/say-as>/g, ""); } else { result = result.replace(/<[^>]*>/g, "").replace(/\s{2,}/g, " "); } return result; } // src/formats/atom-to-ascii-math.ts var SPECIAL_IDENTIFIERS = { "\\ne": "\u2260", "\\neq": "\u2260", "\u2212": "-", // MINUS SIGN "-": "-", "\\alpha": "alpha", "\\beta": "beta", "\\gamma": "gamma", "\\delta": "delta", "\\epsilon": "epsilon", "\\varepsilon": "varepsilon", "\\zeta": "zeta", "\\eta": "eta", "\\theta": "theta", "\\vartheta": "vartheta", "\\iota": "iota", "\\kappa": "kappa", "\\lambda": "lambda", "\\mu": "mu", "\\nu": "nu", "\\xi": "xi", "\\pi": "pi", "\\rho": "rho", "\\sigma": "sigma", "\\tau": "tau", "\\upsilon": "upsilon", "\\phi": "phi", "\\varphi": "varphi", "\\chi": "chi", "\\psi": "psi", "\\omega": "omega", "\\Gamma": "Gamma", "\\Delta": "Delta", "\\Theta": "Theta", "\\Lambda": "Lambda", "\\Xi": "Xi", "\\Pi": "Pi", "\\Sigma": "Sigma", "\\Phi": "Phi", "\\Psi": "Psi", "\\Omega": "Omega", "\\exponentialE": "e", "\\imaginaryI": "i", "\\imaginaryJ": "j", "\\!": " ", "\\,": " ", "\\:": " ", "\\>": " ", "\\;": " ", "\\enskip": " ", "\\enspace": " ", "\\qquad": " ", "\\quad": " ", "\\infty": "oo" }; var SPECIAL_OPERATORS = { "\\pm": "+-", "\\colon": ":", "\\vert": "|", "\\Vert": "||", "\\mid": "|", "\\lbrack": "[", "\\rbrack": "]", "\\lbrace": "{", "\\rbrace": "}", "\\lparen": "(", "\\rparen": ")", "\\langle": "(:", "\\rangle": ":)", "\\sum": " sum ", "\\prod": " prod ", "\\bigcap": " nnn ", "\\bigcup": " uuu ", "\\int": " int ", "\\oint": " oint ", "\\ge": ">=", "\\le": "<=", "\\ne": "!=", "\\neq": "!=", "\\lt": "<", "\\gt": ">", "\\gets": "<-", "\\to": "->", "\\land": " and ", "\\lor": " or ", "\\lnot": " not ", "\\forall": " AA ", "\\exists": " EE ", "\\in": " in ", "\\notin": " !in ", "\\mapsto": "|->", "\\implies": "=>", "\\iff": "<=>", "\\cdot": "*", "\\ast": "**", "\\star": "***", "\\times": "xx", "\\div": "-:", "\\ltimes": "|><", "\\rtimes": "><|", "\\bowtie": "|><|", "\\circ": "@" // '\\lfloor': '\u230a', // '\\rfloor': '\u230b', // '\\lceil': '\u2308', // '\\rceil': '\u2309', // '\\vec': '⃗', // '\\acute': '´', // '\\grave': '`', // '\\dot': '˙', // '\\ddot': '¨', // '\\tilde': '~', // '\\bar': '¯', // '\\breve': '˘', // '\\check': 'ˇ', // '\\hat': '^' }; function joinAsciiMath(xs) { let result = ""; for (const x of xs) { const last = result[result.length - 1]; if (last !== void 0 && /\d/.test(last) && /^\d/.test(x)) result += " "; result += x; } return result; } function atomToAsciiMath(atom) { var _a3, _b3, _c2, _d2, _e, _f, _g, _h, _i, _j, _k, _l, _m; if (!atom) return ""; if (isArray(atom)) { if (atom.length === 0) return ""; if (atom[0].mode === "latex") return atom.map(atomToAsciiMath).join(""); if (atom[0].mode === "text") { let i2 = 0; let text = ""; while (((_a3 = atom[i2]) == null ? void 0 : _a3.mode) === "text") { text += atom[i2].body ? atomToAsciiMath(atom[i2].body) : atom[i2].value; i2++; } return `"${text}" ${atomToAsciiMath(atom.slice(i2))}`; } let i = 0; const result2 = []; while (atom[i] && atom[i].mode === "math") { let digits = ""; while (atom[i] && atom[i].type === "mord" && /\d/.test(atom[i].value)) digits += atom[i++].value; if (digits) result2.push(digits); else result2.push(atomToAsciiMath(atom[i++])); } result2.push(atomToAsciiMath(atom.slice(i))); return joinAsciiMath(result2); } if (atom.mode === "text") return `"${atom.value}"`; let result = ""; const { command } = atom; let m; if (command === "\\placeholder") return `(${atomToAsciiMath(atom.body)})`; switch (atom.type) { case "accent": const accent = { "\\vec": "vec", "\\dot": "dot", "\\ddot": "ddot", "\\bar": "bar", "\\hat": "hat", "\\acute": "acute;", // non-standard "\\grave": "grave", // non-standard "\\tilde": "tilde", // non-standard "\\breve": "breave", // non-standard "\\check": "check" // non-standard }[command]; result = `${accent != null ? accent : ""} ${atomToAsciiMath(atom.body)} `; break; case "first": return ""; case "latexgroup": return atom.body.map((x) => x.value).join(""); case "group": case "root": result = (_b3 = SPECIAL_IDENTIFIERS[command]) != null ? _b3 : atomToAsciiMath(atom.body); break; case "genfrac": { const genfracAtom = atom; if (genfracAtom.leftDelim || genfracAtom.rightDelim) { result = genfracAtom.leftDelim === "." || !genfracAtom.leftDelim ? "{:" : genfracAtom.leftDelim; } if (genfracAtom.hasBarLine) { result += "("; result += atomToAsciiMath(genfracAtom.above); result += ")/("; result += atomToAsciiMath(genfracAtom.below); result += ")"; } else { result += "(" + atomToAsciiMath(genfracAtom.above) + "),"; result += "(" + atomToAsciiMath(genfracAtom.below) + ")"; } if (genfracAtom.leftDelim || genfracAtom.rightDelim) { result += genfracAtom.rightDelim === "." || !genfracAtom.rightDelim ? "{:" : genfracAtom.rightDelim; } } break; case "surd": result += !atom.hasEmptyBranch("above") ? "root(" + atomToAsciiMath(atom.above) + ")(" + atomToAsciiMath(atom.body) + ")" : "sqrt(" + atomToAsciiMath(atom.body) + ")"; break; case "latex": result = atom.value; break; case "leftright": { const leftrightAtom = atom; const lDelim = leftrightAtom.leftDelim; result += lDelim === "." || !lDelim ? "{:" : lDelim; result += atomToAsciiMath(leftrightAtom.body); const rDelim = leftrightAtom.matchingRightDelim(); result += rDelim === "." || !rDelim ? ":}" : rDelim; } break; case "sizeddelim": case "delim": result = atom.value; break; case "overlap": break; case "overunder": break; case "mord": result = (_d2 = (_c2 = SPECIAL_IDENTIFIERS[command]) != null ? _c2 : command) != null ? _d2 : typeof atom.value === "string" ? atom.value : ""; if (result.startsWith("\\")) result += " "; m = command ? command.match(/{?\\char"([\dabcdefABCDEF]+)}?/) : null; if (m) { result = String.fromCodePoint(Number.parseInt("0x" + m[1])); } else if (result.length > 0 && result.startsWith("\\")) { result = typeof atom.value === "string" ? atom.value.charAt(0) : atom.command; } result = asciiStyle(result, atom.style); break; case "mbin": case "mrel": case "minner": result = (_f = (_e = SPECIAL_IDENTIFIERS[command]) != null ? _e : SPECIAL_OPERATORS[command]) != null ? _f : atom.value; break; case "mopen": case "mclose": result = atom.value; break; case "mpunct": result = (_g = SPECIAL_OPERATORS[command]) != null ? _g : command; break; case "mop": case "operator": case "extensible-symbol": if (atom.value !== "\u200B") { if (SPECIAL_OPERATORS[command]) result = SPECIAL_OPERATORS[command]; else { result = command === "\\operatorname" ? atomToAsciiMath(atom.body) : (_h = atom.value) != null ? _h : command; } result += " "; } break; case "array": const array = atom.array; const environment = atom.environmentName; const rowDelim = (_i = { "bmatrix": ["[", "]"], "bmatrix*": ["[", "]"] }[environment]) != null ? _i : ["(", ")"]; const rows = []; for (const row of array) { const cells = []; for (const cell of row) cells.push(rowDelim[0] + atomToAsciiMath(cell) + rowDelim[1]); rows.push(cells.join(",")); } const delim = (_j = { "bmatrix": ["[", "]"], "bmatrix*": ["[", "]"], "cases": ["{", ":}"] }[environment]) != null ? _j : ["(", ")"]; result = delim[0] + rows.join(",") + delim[1]; break; case "box": break; case "spacing": result = (_k = SPECIAL_IDENTIFIERS[command]) != null ? _k : " "; break; case "enclose": result = "(" + atomToAsciiMath(atom.body) + ")"; break; case "space": result = " "; break; case "subsup": result = ""; break; case "macro": result = (_m = (_l = SPECIAL_IDENTIFIERS[command]) != null ? _l : SPECIAL_OPERATORS[command]) != null ? _m : atomToAsciiMath(atom.body); break; } if (!atom.hasEmptyBranch("subscript")) { result += "_"; const arg = atomToAsciiMath(atom.subscript); result += arg.length !== 1 ? `(${arg})` : arg; } if (!atom.hasEmptyBranch("superscript")) { result += "^"; const arg = atomToAsciiMath(atom.superscript); result += arg.length !== 1 ? `(${arg})` : arg; } return result; } function asciiStyle(body, style) { if (!style) return body; let result = body; if (style.variant === "double-struck") result = `bbb "${result}"`; if (style.variant === "script") result = `cc "${result}"`; if (style.variant === "fraktur") result = `fr "${result}"`; if (style.variant === "sans-serif") result = `sf "${result}"`; if (style.variant === "monospace") result = `tt "${result}"`; if (style.variantStyle === "bold") result = `bb "${result}"`; if (style.color) return `color({${style.color}})(${result})`; return result; } // src/public/mathlive-ssr.ts function convertLatexToMarkup(text, options) { var _a3, _b3; options != null ? options : options = {}; options.mathstyle = (_a3 = options.mathstyle) != null ? _a3 : "displaystyle"; const context = new Context({ from: __spreadProps(__spreadValues({}, getDefaultContext()), { renderPlaceholder: () => new Box(160, { maxFontSize: 1 }), letterShapeStyle: (_b3 = options == null ? void 0 : options.letterShapeStyle) != null ? _b3 : "tex" }), mathstyle: options.mathstyle }); const root = new Atom({ mode: "math", type: "root", body: parseLatex(text, { context, parseMode: "math", mathstyle: options.mathstyle }) }); const box = root.render(context); if (!box) return ""; coalesce(applyInterBoxSpacing(box, context)); const struts = makeStruts(box, { classes: "ML__latex" }); return struts.toMarkup(); } function validateLatex2(s) { return validateLatex(s, { context: getDefaultContext() }); } function convertLatexToMathMl(latex, options = {}) { return toMathML( parseLatex(latex, { parseMode: "math", args: () => "", // Prevent #0 arguments to be replaced with placeholder (default behavior) mathstyle: "displaystyle" }), options ); } function convertLatexToSpeakableText(latex) { const atoms = parseLatex(latex, { parseMode: "math", mathstyle: "displaystyle" }); return atomToSpeakableText(atoms); } var gComputeEngine; function convertMathJsonToLatex(json) { var _a3, _b3; if (!gComputeEngine) { const ComputeEngineCtor = (_a3 = globalThis[Symbol.for("io.cortexjs.compute-engine")]) == null ? void 0 : _a3.ComputeEngine; if (ComputeEngineCtor) gComputeEngine = new ComputeEngineCtor(); else { console.error( `MathLive 0.98.5: The CortexJS Compute Engine library is not available. Load the library, for example with: import "https://unpkg.com/@cortex-js/compute-engine?module"` ); } } return (_b3 = gComputeEngine == null ? void 0 : gComputeEngine.box(json).latex) != null ? _b3 : ""; } function convertLatexToAsciiMath(latex, parseMode = "math") { return atomToAsciiMath( new Atom({ type: "root", body: parseLatex(latex, { parseMode }) }) ); } function convertAsciiMathToLatex(ascii) { return parseMathString(ascii, { format: "ascii-math" })[1]; } // src/ui/colors/utils.ts function asRgb(color) { if (typeof color === "string") { const parsed = parseHex2(color); if (!parsed) throw new Error(`Invalid color: ${color}`); return parsed; } if ("C" in color) return oklchToRgb(color); if ("a" in color) return oklabToRgb(color); return color; } function clampByte2(v) { if (v < 0) return 0; if (v > 255) return 255; return Math.round(v); } function parseHex2(hex) { if (!hex) return void 0; if (hex[0] !== "#") return void 0; hex = hex.slice(1); let result; if (hex.length <= 4) { result = { r: parseInt(hex[0] + hex[0], 16), g: parseInt(hex[1] + hex[1], 16), b: parseInt(hex[2] + hex[2], 16) }; if (hex.length === 4) result.a = parseInt(hex[3] + hex[3], 16) / 255; } else { result = { r: parseInt(hex[0] + hex[1], 16), g: parseInt(hex[2] + hex[3], 16), b: parseInt(hex[4] + hex[5], 16) }; if (hex.length === 8) result.a = parseInt(hex[6] + hex[7], 16) / 255; } if (result && typeof result.a === "undefined") result.a = 1; return result; } function oklchToOklab(_) { const [L, C, H] = [_.L, _.C, _.H]; const hRadians = H * Math.PI / 180; const result = { L, a: C * Math.cos(hRadians), b: C * Math.sin(hRadians) }; if (_.alpha !== void 0) result.alpha = _.alpha; return result; } function oklabToOklch(_) { const [L, a, b] = [_.L, _.a, _.b]; const C = Math.sqrt(a * a + b * b); const hRadians = Math.atan2(b, a); const H = hRadians * 180 / Math.PI; const result = { L, C, H }; if (_.alpha !== void 0) result.alpha = _.alpha; return result; } function oklabToUnclippedRgb(_) { const [l, a, b] = [_.L, _.a, _.b]; const L = Math.pow( 0.9999999984505198 * l + 0.39633779217376786 * a + 0.2158037580607588 * b, 3 ); const M = Math.pow( 1.00000000888176 * l - 0.10556134232365635 * a - 0.0638541747717059 * b, 3 ); const S2 = Math.pow( l * 1.000000054672411 - 0.0894841820949657 * a - 1.2914855378640917 * b, 3 ); const r = 4.076741661347994 * L - 3.307711590408193 * M + 0.230969928729428 * S2; const g = -1.2684380040921763 * L + 2.6097574006633715 * M - 0.3413193963102197 * S2; const bl = -0.004196086541837188 * L - 0.7034186144594493 * M + 1.7076147009309444 * S2; const conv = (n) => { const abs = Math.abs(n); if (abs <= 31308e-7) return n * 12.92; return (Math.sign(n) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055); }; return [conv(r), conv(g), conv(bl)]; } function inGamut(rgb) { const [r, g, b] = rgb; return r >= 0 && r <= 1 && g >= 0 && g <= 1 && b >= 0 && b <= 1; } function clampRgb(rgb, alpha) { let [r, g, b] = rgb; r = clampByte2(r * 255); g = clampByte2(g * 255); b = clampByte2(b * 255); return alpha !== void 0 ? { r, g, b, alpha } : { r, g, b }; } function oklabToRgb(color) { let [r, g, b] = oklabToUnclippedRgb(color); if (inGamut([r, g, b])) return clampRgb([r, g, b], color.alpha); const oklch = oklabToOklch(color); oklch.C = 0; [r, g, b] = oklabToUnclippedRgb(oklchToOklab(oklch)); if (!inGamut([r, g, b])) return clampRgb([r, g, b], color.alpha); let low = 0; let high = color.L; let mid = (low + high) / 2; oklch.C = mid; const resolution = 0.36 / Math.pow(2, 12); while (high - low > resolution) { mid = (low + high) / 2; oklch.C = mid; [r, g, b] = oklabToUnclippedRgb(oklchToOklab(oklch)); if (inGamut([r, g, b])) low = mid; else high = mid; } return clampRgb([r, g, b], color.alpha); } function oklchToRgb(_) { return oklabToRgb(oklchToOklab(_)); } // src/ui/colors/contrast.ts function apca(bgColor, fgColor) { const bgRgb = asRgb(bgColor); const fgRgb = asRgb(fgColor); const normBG = 0.56; const normTXT = 0.57; const revTXT = 0.62; const revBG = 0.65; const blkThrs = 0.022; const blkClmp = 1.414; const loClip = 0.1; const deltaYmin = 5e-4; const scaleBoW = 1.14; const loBoWoffset = 0.027; const scaleWoB = 1.14; const loWoBoffset = 0.027; function fclamp(Y) { return Y >= blkThrs ? Y : Y + (blkThrs - Y) ** blkClmp; } function linearize(val) { const sign = val < 0 ? -1 : 1; return sign * Math.pow(Math.abs(val), 2.4); } const Yfg = fclamp( linearize(fgRgb.r / 255) * 0.2126729 + linearize(fgRgb.g / 255) * 0.7151522 + linearize(fgRgb.b / 255) * 0.072175 ); const Ybg = fclamp( linearize(bgRgb.r / 255) * 0.2126729 + linearize(bgRgb.g / 255) * 0.7151522 + linearize(bgRgb.b / 255) * 0.072175 ); let S2, C, Sapc; if (Math.abs(Ybg - Yfg) < deltaYmin) C = 0; else { if (Ybg > Yfg) { S2 = Ybg ** normBG - Yfg ** normTXT; C = S2 * scaleBoW; } else { S2 = Ybg ** revBG - Yfg ** revTXT; C = S2 * scaleWoB; } } if (Math.abs(C) < loClip) Sapc = 0; else if (C > 0) Sapc = C - loWoBoffset; else Sapc = C + loBoWoffset; return Sapc * 100; } function contrast(bgColor, dark, light) { light != null ? light : light = "#fff"; dark != null ? dark : dark = "#000"; const lightContrast = apca(bgColor, light); const darkContrast = apca(bgColor, dark); return Math.abs(lightContrast) > Math.abs(darkContrast) ? light : dark; } // src/ui/colors/css.ts function asHexColor(_) { const rgb = asRgb(_); let hexString = ((1 << 24) + (clampByte2(rgb.r) << 16) + (clampByte2(rgb.g) << 8) + clampByte2(rgb.b)).toString(16).slice(1); if (rgb.alpha !== void 0 && rgb.alpha < 1) hexString += ("00" + Math.round(rgb.alpha * 255).toString(16)).slice(-2); if (hexString[0] === hexString[1] && hexString[2] === hexString[3] && hexString[4] === hexString[5] && hexString[6] === hexString[7]) { hexString = hexString[0] + hexString[2] + hexString[4] + (rgb.alpha !== void 0 && rgb.alpha < 1 ? hexString[6] : ""); } return "#" + hexString; } // src/editor/default-menu.ts function getSelectionPlainString(mf) { const atoms = getSelectionAtoms(mf); let result = ""; for (const atom of atoms) { if (typeof atom.value !== "string") return ""; result += atom.value; } return result; } function getSelectionAtoms(mf) { const model = mf.model; const ranges = model.selection.ranges; if (ranges.length !== 1) return []; return mf.model.getAtoms(ranges[0]); } function validVariantAtom(mf, variant) { const atoms = getSelectionAtoms(mf); if (atoms.length !== 1) return false; const repertoire = VARIANT_REPERTOIRE[variant]; if (!repertoire) return false; if (repertoire.test(atoms[0].value)) return true; return false; } function validVariantStyleSelection(mf, _variantStyle) { return getSelectionPlainString(mf).length > 0; } function getVariantSubmenu(mf) { return [ variantMenuItem(mf, "double-struck", "mathbb", "tooltip.blackboard"), variantMenuItem(mf, "fraktur", "mathfrak", "tooltip.fraktur"), variantMenuItem(mf, "calligraphic", "mathcal", "tooltip.caligraphic"), variantStyleMenuItem(mf, "up", "mathrm", "tooltip.roman-upright"), variantStyleMenuItem(mf, "bold", "mathbf", "tooltip.bold"), variantStyleMenuItem(mf, "italic", "mathit", "tooltip.italic") ]; } function getAccentSubmenu(mf) { return [ { label: () => convertLatexToMarkup(`\\vec{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length === 1, onMenuSelect: () => mf.insert("\\vec{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup( `\\overrightarrow{${getSelectionPlainString(mf)}}` ), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\overrightarrow{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\overleftarrow{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\overleftarrow{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\dot{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length === 1, onMenuSelect: () => mf.insert("\\dot{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\ddot{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length === 1, onMenuSelect: () => mf.insert("\\ddot{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\bar{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length === 1, onMenuSelect: () => mf.insert("\\bar{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\overline{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\overline{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\overgroup{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\overgroup{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\overbrace{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\overbrace{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\underline{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\underline{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\undergroup{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\undergroup{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup(`\\underbrace{${getSelectionPlainString(mf)}}`), visible: () => getSelectionPlainString(mf).length > 0, onMenuSelect: () => mf.insert("\\underbrace{#@}", { selectionMode: "item" }) } ]; } function getDecorationSubmenu(mf) { return [ // { // label: () => convertLatexToMarkup(`\\cancel{${getSelection(mf)}}`), // // visible: () => getSelection(mf).length > 0, // onMenuSelect: () => mf.insert('\\cancel{#@}', { selectionMode: 'item' }), // }, { label: () => convertLatexToMarkup(`\\boxed{${mf.getValue(mf.model.selection)}}}`), // visible: () => getSelection(mf).length > 0, onMenuSelect: () => mf.insert("\\boxed{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup( `\\bbox[5px, border: 2px solid red]{${mf.getValue( mf.model.selection )}}` ), // visible: () => getSelection(mf).length > 0, onMenuSelect: () => mf.insert("\\bbox[5px, border: 2px solid red]{#@}", { selectionMode: "item" }) }, { label: () => convertLatexToMarkup( `\\bbox[5px, border: 2px dashed black]{${mf.getValue( mf.model.selection )}}` ), // visible: () => getSelection(mf).length > 0, onMenuSelect: () => mf.insert("\\bbox[5px, border: 2px dashed black]{#@}", { selectionMode: "item" }) } ]; } function getBackgroundColorSubmenu(mf) { const result = []; for (const color of Object.keys(BACKGROUND_COLORS)) { result.push({ class: (asHexColor(contrast(BACKGROUND_COLORS[color])) === "#000" ? "dark-contrast" : "light-contrast") + " menu-swatch", label: ``, ariaLabel: () => { var _a3; return (_a3 = localize(color)) != null ? _a3 : color; }, checked: () => { var _a3; return { some: "mixed", all: true }[(_a3 = mf.queryStyle({ backgroundColor: color })) != null ? _a3 : false]; }, onMenuSelect: () => { mf.applyStyle({ backgroundColor: color }, { operation: "toggle" }); mf.adoptStyle = "none"; } }); } return result; } function getColorSubmenu(mf) { const result = []; for (const color of Object.keys(FOREGROUND_COLORS)) { result.push({ class: (contrast(FOREGROUND_COLORS[color]) === "#000" ? "dark-contrast" : "light-contrast") + " menu-swatch", label: ``, ariaLabel: () => { var _a3; return (_a3 = localize(color)) != null ? _a3 : color; }, checked: () => { var _a3; return { some: "mixed", all: true }[(_a3 = mf.queryStyle({ color })) != null ? _a3 : false]; }, onMenuSelect: () => { mf.applyStyle({ color }, { operation: "toggle" }); mf.adoptStyle = "none"; } }); } return result; } var InsertMatrixMenuItem = class extends _MenuItemState { constructor(decl, parent, row, col) { super(decl, parent); this.row = row; this.col = col; } set active(value) { const cells = this.parentMenu.children; if (value) { for (const cell of cells) { cell.element.classList.toggle( "active", cell.row <= this.row && cell.col <= this.col ); } } else for (const cell of cells) cell.element.classList.remove("active"); } }; function getInsertMatrixSubmenu(mf) { const result = []; for (let row = 1; row <= 5; row++) { for (let col = 1; col <= 5; col++) { result.push({ onCreate: (decl, parent) => new InsertMatrixMenuItem(decl, parent, row, col), label: `\u2610`, tooltip: () => localize("tooltip.row-by-col", row, col), data: { row, col }, onMenuSelect: () => { mf.insert( `\\begin{pmatrix}${Array(row).fill(Array(col).fill("#?").join(" & ")).join("\\\\")}\\end{pmatrix}`, { selectionMode: "item" } ); } }); } } return result; } function getDefaultMenuItems(mf) { return [ // { // label: 'Show Virtual Keyboard', // onMenuSelect: () => window.mathVirtualKeyboard.show({ animate: true }), // visible: () => window.mathVirtualKeyboard.visible === false, // }, // { // label: 'Hide Virtual Keyboard', // onMenuSelect: () => window.mathVirtualKeyboard.hide({ animate: true }), // visible: () => window.mathVirtualKeyboard.visible === true, // }, { label: () => localize("menu.array.add row above"), id: "add-row-above", onMenuSelect: () => mf.executeCommand("addRowBefore"), visible: () => inMatrix(mf) }, { label: () => localize("menu.array.add row below"), id: "add-row-below", onMenuSelect: () => mf.executeCommand("addRowAfter"), visible: () => inMatrix(mf) }, { label: () => localize("menu.array.add column before"), id: "add-column-before", onMenuSelect: () => mf.executeCommand("addColumnBefore"), visible: () => inMatrix(mf), enabled: () => { const array = mf.model.parentEnvironment; if (!array) return false; const [rows, _cols] = shape(mf); return rows < array.maxColumns; } }, { label: () => localize("menu.array.add column after"), id: "add-column-after", onMenuSelect: () => mf.executeCommand("addColumnAfter"), visible: () => inMatrix(mf) }, { type: "divider" }, { label: () => localize("menu.array.delete row"), id: "delete-row", onMenuSelect: () => mf.executeCommand("removeRow"), visible: () => inMatrix(mf) }, { label: () => localize("menu.array.delete column"), id: "delete-column", onMenuSelect: () => mf.executeCommand("removeColumn"), visible: () => inMatrix(mf) }, { type: "divider" }, { label: () => localize("menu.borders"), visible: () => (isMatrixSelected(mf) || inMatrix(mf)) && mf.isSelectionEditable, submenu: [ { label: " \u22F1 ", id: "environment-no-border", onMenuSelect: () => performSetEnvironment(mf, "matrix") }, { label: "(\u22F1)", id: "environment-parentheses", onMenuSelect: () => performSetEnvironment(mf, "pmatrix") }, { label: "[\u22F1]", id: "environment-brackets", onMenuSelect: () => performSetEnvironment(mf, "bmatrix") }, { label: "|\u22F1|", id: "environment-bar", onMenuSelect: () => performSetEnvironment(mf, "vmatrix") }, { label: "{\u22F1}", id: "environment-braces", onMenuSelect: () => performSetEnvironment(mf, "Bmatrix") } ], submenuClass: "border-submenu" }, { type: "divider" }, { label: () => localize("menu.insert matrix"), id: "insert-matrix", visible: () => mf.isSelectionEditable, submenu: getInsertMatrixSubmenu(mf), submenuClass: "insert-matrix-submenu", columnCount: 5 }, { label: () => localize("menu.mode"), id: "mode", visible: () => mf.isSelectionEditable && mf.model.selectionIsCollapsed, submenu: [ { label: () => localize("menu.mode-math"), id: "mode-math", onMenuSelect: () => { complete(mf, "accept-all"); mf.executeCommand(["switchMode", "math"]); }, checked: () => mf.model.mode === "math" }, { label: () => localize("menu.mode-text"), id: "mode-text", onMenuSelect: () => { complete(mf, "accept-all"); mf.executeCommand(["switchMode", "text"]); }, checked: () => mf.model.mode === "text" }, { label: () => localize("menu.mode-latex"), id: "mode-latex", onMenuSelect: () => mf.executeCommand(["switchMode", "latex"]), checked: () => mf.model.mode === "latex" } ] }, { type: "divider" }, { label: () => localize("menu.font-style"), id: "variant", visible: () => mf.isSelectionEditable, submenu: getVariantSubmenu(mf), submenuClass: "variant-submenu" }, { label: () => localize("menu.color"), id: "color", visible: () => mf.isSelectionEditable, submenu: getColorSubmenu(mf), columnCount: 4, submenuClass: "swatches-submenu" }, { label: () => localize("menu.background-color"), id: "background-color", visible: () => mf.isSelectionEditable, submenu: getBackgroundColorSubmenu(mf), columnCount: 4, submenuClass: "swatches-submenu" }, { label: () => localize("menu.accent"), id: "accent", visible: () => mf.isSelectionEditable, submenu: getAccentSubmenu(mf), submenuClass: "variant-submenu" }, { label: () => localize("menu.decoration"), id: "decoration", visible: () => mf.isSelectionEditable && getSelectionPlainString(mf).length > 0, submenu: getDecorationSubmenu(mf), submenuClass: "variant-submenu" }, { type: "divider" }, { label: () => localize("menu.evaluate"), id: "ce-evaluate", visible: () => mf.isSelectionEditable && window.MathfieldElement.computeEngine !== null, onMenuSelect: () => { const latex = evaluate(mf); if (!latex) { mf.model.announce("plonk"); return; } if (mf.model.selectionIsCollapsed) { mf.model.position = mf.model.lastOffset; mf.insert(`=${latex}`, { insertionMode: "insertAfter", selectionMode: "item" }); } else { mf.insert(latex, { insertionMode: "replaceSelection", selectionMode: "item" }); } } }, { label: () => localize("menu.simplify"), id: "ce-simplify", visible: () => mf.isSelectionEditable && window.MathfieldElement.computeEngine !== null, onMenuSelect: () => { var _a3, _b3; if (mf.model.selectionIsCollapsed) { const result = (_a3 = mf.expression) == null ? void 0 : _a3.simplify(); mf.model.position = mf.model.lastOffset; if (!result) { mf.model.announce("plonk"); return; } mf.insert(`=${result.latex}`, { insertionMode: "insertAfter", selectionMode: "item" }); } else { const result = (_b3 = window.MathfieldElement.computeEngine) == null ? void 0 : _b3.parse(mf.getValue(mf.model.selection)).simplify(); if (!result) { mf.model.announce("plonk"); return; } mf.insert(result.latex, { insertionMode: "replaceSelection", selectionMode: "item" }); } } }, { label: () => { var _a3; if (window.MathfieldElement.computeEngine === null) return ""; const unknown = (_a3 = mf.expression) == null ? void 0 : _a3.unknowns[0]; if (unknown) return localize("menu.solve-for", convertLatexToMarkup(unknown)); return localize("menu.solve"); }, id: "ce-solve", visible: () => { var _a3; return mf.isSelectionEditable && window.MathfieldElement.computeEngine !== null && ((_a3 = mf.expression) == null ? void 0 : _a3.unknowns.length) === 1 && mf.expression.unknowns[0] !== "Nothing"; }, onMenuSelect: () => { var _a3; const expr = mf.expression; const unknown = expr == null ? void 0 : expr.unknowns[0]; const results = (_a3 = expr.solve(unknown)) == null ? void 0 : _a3.map((x) => { var _a4; return (_a4 = x.simplify().latex) != null ? _a4 : ""; }); if (!results) { mf.model.announce("plonk"); return; } mf.insert( `${unknown}=${results.length === 1 ? results[0] : "\\left\\lbrace" + (results == null ? void 0 : results.join(", ")) + "\\right\\rbrace"}`, { insertionMode: "replaceAll", selectionMode: "item" } ); } }, { type: "divider" }, { label: () => localize("menu.cut"), onMenuSelect: () => mf.executeCommand("cutToClipboard"), visible: () => !mf.options.readOnly && mf.isSelectionEditable, keyboardShortcut: "meta+X" }, // { // label: 'Copy', // onMenuSelect: () => mf.executeCommand('copyToClipboard'), // }, { label: () => localize("menu.copy"), id: "copy", submenu: [ { label: () => localize("menu.copy-as-latex"), id: "copy-latex", onMenuSelect: () => ModeEditor.copyToClipboard(mf, "latex"), keyboardShortcut: "meta+C" }, { label: () => localize("menu.copy-as-ascii-math"), id: "copy-ascii-math", onMenuSelect: () => ModeEditor.copyToClipboard(mf, "ascii-math") }, { label: () => localize("menu.copy-as-mathml"), id: "copy-math-ml", onMenuSelect: () => ModeEditor.copyToClipboard(mf, "math-ml") } ] }, { label: () => localize("menu.paste"), id: "paste", onMenuSelect: () => mf.executeCommand("pasteFromClipboard"), visible: () => mf.hasEditableContent, keyboardShortcut: "meta+V" }, { label: () => localize("menu.select-all"), id: "select-all", keyboardShortcut: "meta+A", onMenuSelect: () => mf.executeCommand("selectAll") } ]; } function inMatrix(mf) { var _a3; return !!((_a3 = mf.model.parentEnvironment) == null ? void 0 : _a3.array); } function isMatrixSelected(mf) { return mf.model.at(mf.model.position).type === "array"; } function shape(mf) { var _a3; const array = (_a3 = mf.model.parentEnvironment) == null ? void 0 : _a3.array; if (!array) return [0, 0]; return [ array.length, array.reduce((acc, col) => Math.max(acc, col.length), 0) ]; } function performSetEnvironment(mf, env) { removeSuggestion(mf); mf.flushInlineShortcutBuffer(); setEnvironment(mf.model, env); requestUpdate(mf); } function evaluate(mf) { var _a3, _b3; let expr; if (mf.model.selectionIsCollapsed) { expr = (_a3 = window.MathfieldElement.computeEngine) == null ? void 0 : _a3.parse(mf.getValue(), { canonical: false }); } else { expr = (_b3 = window.MathfieldElement.computeEngine) == null ? void 0 : _b3.parse( mf.getValue(mf.model.selection), { canonical: false } ); } if (!expr) return ""; let result = expr.evaluate(); if (result.isSame(expr)) result = expr.N(); return result.latex; } function variantMenuItem(mf, variant, command, tooltip) { return { label: () => convertLatexToMarkup(`\\${command}{${getSelectionPlainString(mf)}}`), tooltip: () => { var _a3; return (_a3 = localize(tooltip)) != null ? _a3 : tooltip; }, visible: () => validVariantAtom(mf, variant), checked: () => { var _a3; return { some: "mixed", all: true }[(_a3 = mf.queryStyle({ variant })) != null ? _a3 : false]; }, onMenuSelect: () => { mf.applyStyle({ variant }, { operation: "toggle" }); mf.adoptStyle = "none"; } }; } function variantStyleMenuItem(mf, variantStyle, command, tooltip) { return { label: () => convertLatexToMarkup(`\\${command}{${getSelectionPlainString(mf)}}`), tooltip: () => { var _a3; return (_a3 = localize(tooltip)) != null ? _a3 : tooltip; }, visible: () => validVariantStyleSelection(mf, variantStyle), checked: () => { var _a3; return { some: "mixed", all: true }[(_a3 = mf.queryStyle({ variantStyle })) != null ? _a3 : false]; }, onMenuSelect: () => { mf.applyStyle({ variantStyle }, { operation: "toggle" }); mf.adoptStyle = "none"; } }; } // src/editor/speech.ts function speakableText(prefix, atoms) { return prefix + atomToSpeakableText(atoms); } register2( { speak: (mathfield, scope, options) => { return speak(mathfield, scope, options); } }, { target: "mathfield" } ); function speak(mathfield, scope, speakOptions) { var _a3, _b3; speakOptions = speakOptions != null ? speakOptions : { withHighlighting: false }; const { model } = mathfield; function getAtoms(scope2) { let result = null; switch (scope2) { case "all": result = model.root; break; case "selection": result = model.getAtoms(model.selection); break; case "left": { result = model.getAtoms( model.offsetOf(model.at(model.position).leftSibling), model.position ); break; } case "right": { result = model.getAtoms( model.position, model.offsetOf(model.at(model.position).rightSibling) ); break; } case "group": result = model.getAtoms(model.getSiblingsRange(model.position)); break; case "parent": { const { parent } = model.at(model.position); if (parent == null ? void 0 : parent.parent) result = parent; else result = model.root; break; } default: result = model.root; } return result; } function getFailedSpeech(scope2) { let result = ""; switch (scope2) { case "all": console.log("Internal failure: speak all failed"); break; case "selection": result = "no selection"; break; case "left": result = "at start"; break; case "right": result = "at end"; break; case "group": console.log("Internal failure: speak group failed"); break; case "parent": result = "no parent"; break; default: console.log('unknown speak_ param value: "' + scope2 + '"'); break; } return result; } const atoms = getAtoms(scope); if (atoms === null) { (_b3 = (_a3 = window.MathfieldElement).speakHook) == null ? void 0 : _b3.call(_a3, getFailedSpeech(scope)); return false; } if (speakOptions.withHighlighting || window.MathfieldElement.speechEngine === "amazon") { window.MathfieldElement.textToSpeechMarkup = window.sre && window.MathfieldElement.textToSpeechRules === "sre" ? "ssml_step" : "ssml"; } const text = atomToSpeakableText(atoms); if (isBrowser() && speakOptions.withHighlighting) { globalMathLive().readAloudMathfield = mathfield; render(mathfield, { forHighlighting: true }); if (window.MathfieldElement.readAloudHook) window.MathfieldElement.readAloudHook(mathfield.field, text); } else if (window.MathfieldElement.speakHook) window.MathfieldElement.speakHook(text); return false; } function defaultSpeakHook(text) { var _a3, _b3; if (!isBrowser()) { console.log("Speak:", text); return; } if (!window.MathfieldElement.speechEngine || window.MathfieldElement.speechEngine === "local") { const utterance = new SpeechSynthesisUtterance(text); window.speechSynthesis.speak(utterance); } else if (window.MathfieldElement.speechEngine === "amazon") { if (!("AWS" in window)) { console.error( `MathLive 0.98.5: AWS SDK not loaded. See https://www.npmjs.com/package/aws-sdk` ); } else { const polly = new window.AWS.Polly({ apiVersion: "2016-06-10" }); const parameters = { OutputFormat: "mp3", VoiceId: (_a3 = window.MathfieldElement.speechEngineVoice) != null ? _a3 : "Joanna", Engine: [ "Amy", "Emma", "Brian", "Ivy", "Joanna", "Kendra", "Kimberly", "Salli", "Joey", "Justin", "Matthew" ].includes((_b3 = window.MathfieldElement.speechEngineVoice) != null ? _b3 : "Joanna") ? "neural" : "standard", // SampleRate: '24000', Text: text, TextType: "ssml" // SpeechMarkTypes: ['ssml]' }; polly.synthesizeSpeech(parameters, (err, data) => { if (err) { console.trace( `MathLive 0.98.5: \`polly.synthesizeSpeech()\` error: ${err}` ); } else if (data == null ? void 0 : data.AudioStream) { const uInt8Array = new Uint8Array(data.AudioStream); const blob = new Blob([uInt8Array.buffer], { type: "audio/mpeg" }); const url = URL.createObjectURL(blob); const audioElement = new Audio(url); audioElement.play().catch((error) => console.log(error)); } else console.log("polly.synthesizeSpeech():", data); }); } } else if (window.MathfieldElement.speechEngine === "google") { console.error( `MathLive 0.98.5: The Google speech engine is not supported yet. Please come again.` ); } } // src/editor/a11y.ts function relationName(atom) { var _a3; let result = void 0; if (atom.parent.type === "prompt") { if (atom.parentBranch === "body") result = "prompt"; } else if (atom.parentBranch === "body") { result = !atom.type ? "parent" : (_a3 = { enclose: "cross out", leftright: "delimiter", surd: "square root", root: "math field", mop: "operator", // E.g. `\operatorname`, a `mop` with a body first: "first" }[atom.type]) != null ? _a3 : "parent"; } else if (atom.parent.type === "genfrac") { if (atom.parentBranch === "above") return "numerator"; if (atom.parentBranch === "below") return "denominator"; } else if (atom.parent.type === "surd") { if (atom.parentBranch === "above") result = "index"; } else if (atom.parentBranch === "superscript") result = "superscript"; else if (atom.parentBranch === "subscript") result = "subscript"; if (!result) console.log("unknown relationship"); return result != null ? result : "parent"; } function defaultAnnounceHook(mathfield, action, previousPosition, atoms) { let liveText = ""; if (action === "plonk") { window.MathfieldElement.playSound("plonk"); mathfield.flushInlineShortcutBuffer(); } else if (action === "delete") liveText = speakableText("deleted: ", atoms); else if (action === "focus" || action.includes("move")) { liveText = getRelationshipAsSpokenText(mathfield.model, previousPosition) + (mathfield.model.selectionIsCollapsed ? "" : "selected: ") + getNextAtomAsSpokenText(mathfield.model); } else if (action === "replacement") { liveText = speakableText("", mathfield.model.at(mathfield.model.position)); } else if (action === "line") { const label = speakableText("", mathfield.model.root); mathfield.keyboardDelegate.setAriaLabel(label); } else liveText = atoms ? speakableText(action + " ", atoms) : action; if (liveText) { const ariaLiveChangeHack = mathfield.ariaLiveText.textContent.includes( "\xA0" ) ? " \u202F " : " \xA0 "; mathfield.ariaLiveText.textContent = liveText + ariaLiveChangeHack; } } function getRelationshipAsSpokenText(model, previousOffset) { if (Number.isNaN(previousOffset)) return ""; const previous = model.at(previousOffset); if (!previous) return ""; if (previous.treeDepth <= model.at(model.position).treeDepth) return ""; let result = ""; let ancestor = previous.parent; const newParent = model.at(model.position).parent; while (ancestor !== model.root && ancestor !== newParent) { result += `out of ${relationName(ancestor)};`; ancestor = ancestor.parent; } return result; } function getNextAtomAsSpokenText(model) { if (!model.selectionIsCollapsed) return speakableText("", model.getAtoms(model.selection)); let result = ""; const cursor = model.at(model.position); const relation = relationName(cursor); if (cursor.isFirstSibling) result = (relation ? "start of " + relation : "unknown") + ": "; if (cursor.isLastSibling) { if (!cursor.isFirstSibling) result += relation ? "end of " + relation : "unknown"; } else result += speakableText("", cursor); return result; } // src/editor-model/model-private.ts var _Model = class { constructor(target, mode, root) { this.mathfield = target; this.mode = mode; this.silenceNotifications = false; this._selection = { ranges: [[0, 0]], direction: "none" }; this._anchor = 0; this._position = 0; this.root = root; } dispose() { this.mathfield = void 0; } getState() { const selection = { ranges: [...this._selection.ranges] }; if (this.selection.direction && this.selection.direction !== "none") selection.direction = this.selection.direction; return { content: this.root.toJson(), selection, mode: this.mode }; } setState(state, options) { var _a3; const wasSuppressing = this.silenceNotifications; this.silenceNotifications = (_a3 = options == null ? void 0 : options.silenceNotifications) != null ? _a3 : true; let changeOption = {}; if ((options == null ? void 0 : options.type) === "undo") changeOption = { inputType: "historyUndo" }; if ((options == null ? void 0 : options.type) === "redo") changeOption = { inputType: "historyRedo" }; if (this.contentWillChange(changeOption)) { const didSuppress = this.silenceNotifications; this.silenceNotifications = true; this.mode = state.mode; this.root = fromJson(state.content); this.selection = state.selection; this.silenceNotifications = didSuppress; this.contentDidChange(changeOption); } this.silenceNotifications = wasSuppressing; } get atoms() { return this.root.children; } /** * The selection, accounting for the common ancestors */ get selection() { return this._selection; } set selection(value) { this.setSelection(value); } setSelection(arg1, arg2) { if (!this.mathfield.contentEditable && this.mathfield.userSelect === "none") return false; return this.deferNotifications({ selection: true }, () => { var _a3, _b3, _c2; const value = this.normalizeSelection(arg1, arg2); if (value === void 0) throw new TypeError("Invalid selection"); if (value.ranges.length === 1 && value.ranges[0][0] === value.ranges[0][1]) { const pos = value.ranges[0][0]; if (!this.mathfield.dirty && !((_a3 = this.at(pos)) == null ? void 0 : _a3.parentPrompt) && this.mathfield.hasEditablePrompts) { if ((_b3 = this.at(pos - 1)) == null ? void 0 : _b3.parentPrompt) { this._anchor = this.normalizeOffset(pos - 1); this._position = this._anchor; this._selection = this.normalizeSelection(this._anchor); return; } if ((_c2 = this.at(pos + 1)) == null ? void 0 : _c2.parentPrompt) { this._anchor = this.normalizeOffset(pos + 1); this._position = this._anchor; this._selection = this.normalizeSelection(this._anchor); return; } this._anchor = 0; this._position = 0; this._selection = { ranges: [[0, 0]] }; return; } this._anchor = pos; this._position = pos; this._selection = value; return; } const selRange = range(value); if (value.direction === "backward") [this._position, this._anchor] = selRange; else [this._anchor, this._position] = selRange; const first = this.at(selRange[0] + 1); const last = this.at(selRange[1]); const commonAncestor = Atom.commonAncestor(first, last); if ((commonAncestor == null ? void 0 : commonAncestor.type) === "array" && first.parent === commonAncestor && last.parent === commonAncestor) { this._selection = { ranges: [selRange], direction: value.direction }; } else this._selection = { ranges: [selRange], direction: value.direction }; console.assert(this._position >= 0 && this._position <= this.lastOffset); return; }); } setPositionHandlingPlaceholder(pos) { var _a3; const atom = this.at(pos); if ((atom == null ? void 0 : atom.type) === "placeholder") { this.setSelection(pos - 1, pos); } else if (((_a3 = atom == null ? void 0 : atom.rightSibling) == null ? void 0 : _a3.type) === "placeholder") { this.setSelection(pos, pos + 1); } else this.position = pos; if (atom instanceof LatexAtom && atom.isSuggestion) atom.isSuggestion = false; this.mathfield.stopCoalescingUndo(); } /** * The "focus" or "cursor" (i.e. not the anchor) a.k.a the insertion point * or caret: where things are going to be inserted next. * */ get position() { return this._position; } set position(value) { this.setSelection(value, value); } /** * The offset from which the selection is extended */ get anchor() { return this._anchor; } get selectionIsCollapsed() { return this._anchor === this._position; } get selectionIsPlaceholder() { if (Math.abs(this._anchor - this._position) === 1) { return this.at(Math.max(this._anchor, this._position)).type === "placeholder"; } return false; } collapseSelection(direction = "forward") { if (this._anchor === this._position) return false; if (direction === "backward") this.position = Math.min(this._anchor, this._position); else this.position = Math.max(this._anchor, this._position); return true; } get lastOffset() { return this.atoms.length - 1; } at(index) { return this.atoms[index]; } offsetOf(atom) { return this.atoms.indexOf(atom); } getSiblingsRange(offset) { const atom = this.at(offset); const { parent } = atom; if (!parent) return [0, this.lastOffset]; const branch = atom.parent.branch(atom.parentBranch); return [this.offsetOf(branch[0]), this.offsetOf(branch[branch.length - 1])]; } getBranchRange(offset, branchName) { const branch = this.at(offset).branch(branchName); return [this.offsetOf(branch[0]), this.offsetOf(branch[branch.length - 1])]; } getAtoms(arg1, arg2, arg3) { let options = arg3 != null ? arg3 : {}; if (isSelection(arg1)) { options = arg2 != null ? arg2 : {}; if (arg1.ranges.length > 1) { return arg1.ranges.reduce( (acc, range2) => [...acc, ...this.getAtoms(range2, options)], [] ); } arg1 = arg1.ranges[0]; } let start; let end; if (isOffset(arg1)) { start = arg1; if (!isOffset(arg2)) return []; end = arg2; } else { [start, end] = arg1; options = arg2 != null ? arg2 : {}; } if (!Number.isFinite(start)) return []; if (options.includeChildren === void 0) options.includeChildren = false; if (start < 0) start = this.lastOffset - start + 1; if (end < 0) end = this.lastOffset - end + 1; const first = Math.min(start, end) + 1; const last = Math.max(start, end); if (!options.includeChildren && first === 1 && last === this.lastOffset) return [this.root]; let result = []; for (let i = first; i <= last; i++) { const atom = this.atoms[i]; if (atomIsInRange(this, atom, first, last)) result.push(atom); } if (!options.includeChildren) { result = result.filter((atom) => { let ancestorIncluded = false; let { parent } = atom; while (parent && !ancestorIncluded) { ancestorIncluded = atomIsInRange(this, parent, first, last); parent = parent.parent; } return !ancestorIncluded; }); } return result; } /** * Unlike `getAtoms()`, the argument here is an index * Return all the atoms, in order, starting at startingIndex * then looping back at the beginning */ getAllAtoms(startingIndex = 0) { const result = []; const last = this.lastOffset; for (let i = startingIndex; i <= last; i++) result.push(this.atoms[i]); for (let i = 0; i < startingIndex; i++) result.push(this.atoms[i]); return result; } findAtom(filter, startingIndex = 0, direction = "forward") { let atom = void 0; const last = this.lastOffset; if (direction === "forward") { for (let i = startingIndex; i <= last; i++) { atom = this.atoms[i]; if (filter(atom)) return atom; } for (let i = 0; i < startingIndex; i++) { atom = this.atoms[i]; if (filter(atom)) return atom; } return void 0; } for (let i = startingIndex; i >= 0; i--) { atom = this.atoms[i]; if (filter(atom)) return atom; } for (let i = last; i > startingIndex; i--) { atom = this.atoms[i]; if (filter(atom)) return atom; } return void 0; } /** Remove the specified atoms from the tree. * **WARNING** upon return the selection may now be invalid */ extractAtoms(range2) { let result = this.getAtoms(range2); if (result.length === 1 && !result[0].parent) { if (result[0].type === "root") { result = [...result[0].body]; result.shift(); } else { result = this.root.cells.flat(); this.root = new Atom({ type: "root", body: [] }); return result; } } for (const child of result) child.parent.removeChild(child); return result; } deleteAtoms(range2) { this.extractAtoms(range2); this.position = range2[0]; } atomToString(atom, inFormat) { const format = inFormat != null ? inFormat : "latex"; if (format.startsWith("latex")) { return Atom.serialize([atom], { expandMacro: format === "latex-expanded", skipStyles: format === "latex-unstyled", skipPlaceholders: format === "latex-without-placeholders", defaultMode: this.mathfield.options.defaultMode }); } if (format === "math-ml") return toMathML(atom); if (format === "spoken") return atomToSpeakableText(atom); if (format === "spoken-text") { const saveTextToSpeechMarkup = window.MathfieldElement.textToSpeechMarkup; window.MathfieldElement.textToSpeechMarkup = ""; const result = atomToSpeakableText(atom); window.MathfieldElement.textToSpeechMarkup = saveTextToSpeechMarkup; return result; } if (format === "spoken-ssml" || format === "spoken-ssml-with-highlighting") { const saveTextToSpeechMarkup = window.MathfieldElement.textToSpeechMarkup; window.MathfieldElement.textToSpeechMarkup = "ssml"; const result = atomToSpeakableText(atom); window.MathfieldElement.textToSpeechMarkup = saveTextToSpeechMarkup; return result; } if (format === "ascii-math") return atomToAsciiMath(atom); console.error(`MathLive 0.98.5: Unexpected format "${format}`); return ""; } getValue(arg1, arg2, arg3) { if (arg1 === void 0) return this.atomToString(this.root, "latex"); if (typeof arg1 === "string" && arg1 !== "math-json") return this.atomToString(this.root, arg1); let ranges; let format; if (isOffset(arg1) && isOffset(arg2)) { ranges = [this.normalizeRange([arg1, arg2])]; format = arg3; } else if (isRange(arg1)) { ranges = [this.normalizeRange(arg1)]; format = arg2; } else if (isSelection(arg1)) { ranges = arg1.ranges; format = arg2; } else { ranges = [this.normalizeRange([0, -1])]; format = arg1; } format != null ? format : format = "latex"; if (format === "math-json") { if (!window.MathfieldElement.computeEngine) { if (!window[Symbol.for("io.cortexjs.compute-engine")]) { console.error( 'The CortexJS Compute Engine library is not available.\nLoad the library, for example with:\nimport "https://unpkg.com/@cortex-js/compute-engine?module"' ); } return '["Error", "compute-engine-not-available"]'; } const latex = this.getValue({ ranges }, "latex-unstyled"); try { const expr = window.MathfieldElement.computeEngine.parse(latex); return JSON.stringify(expr.json); } catch (e) { return JSON.stringify(["Error", `'${e.toString()}'`]); } } if (format.startsWith("latex")) { const options = { expandMacro: format === "latex-expanded", skipStyles: format === "latex-unstyled", skipPlaceholders: format === "latex-without-placeholders", defaultMode: this.mathfield.options.defaultMode }; return joinLatex( ranges.map((range2) => Atom.serialize(this.getAtoms(range2), options)) ); } return ranges.map( (range2) => this.getAtoms(range2).map((atom) => this.atomToString(atom, format)).join("") ).join(""); } /** * Unlike `setSelection`, this method is intended to be used in response * to a user action, and it performs various adjustments to result * in a more intuitive selection. * For example: * - when all the children of an atom are selected, the atom * become selected. * - this method will *not* change the anchor, but may result * in a selection whose boundary is outside the anchor */ extendSelectionTo(anchor, position) { if (!this.mathfield.contentEditable && this.mathfield.userSelect === "none") return false; return this.deferNotifications({ selection: true }, () => { const range2 = this.normalizeRange([anchor, position]); let [start, end] = range2; let { parent } = this.at(end); if (parent) { if (parent.type === "genfrac" || parent.type === "subsup") { while (parent !== this.root && childrenInRange(this, parent, [start, end])) { end = this.offsetOf(parent); parent = parent.parent; } } } parent = this.at(start).parent; while (parent !== this.root && childrenInRange(this, parent, [start, end])) { start = this.offsetOf(parent.leftSibling); parent = parent.parent; } parent = this.at(end).parent; if ((parent == null ? void 0 : parent.type) === "genfrac") { while (parent !== this.root && childrenInRange(this, parent, [start, end])) { end = this.offsetOf(parent); console.assert(end >= 0); parent = parent.parent; } } this._position = this.normalizeOffset(position); this._selection = { ranges: [[start, end]], direction: "none" }; }); } /** * This method is called to provide feedback when using a screen reader * or other assistive device, for example when changing the selection or * moving the insertion point. * * It can also be used with the 'plonk' command to provide an audible * feedback when a command is not possible. * * This method should not be called from other methods of the model * (such as `setSelection`) as these methods can also be called * programmatically and a feedback in these case would be innapropriate, * however they should be called from functions called as a result of a user * action, such as the functions in `commands.ts` */ announce(command, previousPosition, atoms = []) { var _a3, _b3; const result = (_b3 = (_a3 = this.mathfield.host) == null ? void 0 : _a3.dispatchEvent( new CustomEvent("announce", { detail: { command, previousPosition, atoms }, cancelable: true, bubbles: true, composed: true }) )) != null ? _b3 : true; if (result) defaultAnnounceHook(this.mathfield, command, previousPosition, atoms); } // Suppress notification while scope is executed, // then notify of content change, and selection change (if actual change) deferNotifications(options, f) { const oldSelection = this._selection; const oldAnchor = this._anchor; const oldPosition = this._position; const saved = this.silenceNotifications; this.silenceNotifications = true; const previousCounter = this.root.changeCounter; f(); const contentChanged = this.root.changeCounter !== previousCounter; const selectionChanged = oldAnchor !== this._anchor || oldPosition !== this._position || compareSelection(this._selection, oldSelection) === "different"; this.silenceNotifications = saved; if (options.content && contentChanged) this.contentDidChange({ inputType: options.type }); if (options.selection && selectionChanged) this.selectionDidChange(); return contentChanged || selectionChanged; } normalizeOffset(value) { if (value > 0) value = Math.min(value, this.lastOffset); else if (value < 0) value = this.lastOffset + value + 1; return value; } /** * Ensure that the range is valid and canonical, i.e. * - start <= end * - collapsed = start === end * - start >= 0, end >=0 */ normalizeRange(range2) { let [start, end] = range2; start = this.normalizeOffset(start); end = this.normalizeOffset(end); return start < end ? [start, end] : [end, start]; } normalizeSelection(value, value2) { var _a3; let result = void 0; if (isOffset(value)) { const offset = this.normalizeOffset(value); if (isOffset(value2)) { const offset2 = this.normalizeOffset(value2); result = offset <= offset2 ? { ranges: [[offset, offset2]], direction: "none" } : { ranges: [[offset2, offset]], direction: "backward" }; } else result = { ranges: [[offset, offset]], direction: "none" }; } else if (isRange(value)) { const start = this.normalizeOffset(value[0]); const end = this.normalizeOffset(value[1]); result = start <= end ? { ranges: [[start, end]], direction: "none" } : { ranges: [[end, start]], direction: "backward" }; } else if (isSelection(value)) { result = { ranges: value.ranges.map((x) => this.normalizeRange(x)), direction: (_a3 = value.direction) != null ? _a3 : "none" }; } console.assert(result !== void 0); return result; } /** Returns the first ArrayAtom in ancestry of current position */ get parentEnvironment() { let parent = this.at(this.position).parent; if (!parent) return void 0; while (parent.parent && parent.type !== "array") parent = parent.parent; if (parent.type !== "array") return void 0; return parent; } /** Return the cell (row, col) that the current selection is in */ get cell() { var _a3; let atom = this.at(this.position); if (!atom) return void 0; while (atom && ((_a3 = atom.parent) == null ? void 0 : _a3.type) !== "array") atom = atom.parent; if (!(atom == null ? void 0 : atom.parent) || atom.parent.type !== "array") return void 0; return atom.parentBranch; } contentWillChange(options = {}) { if (this.silenceNotifications || !this.mathfield) return true; const save = this.silenceNotifications; this.silenceNotifications = true; const result = this.mathfield.onContentWillChange(options); this.silenceNotifications = save; return result; } contentDidChange(options) { var _a3; if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this.mathfield)); if (this.silenceNotifications || !this.mathfield.host || !this.mathfield) return; const save = this.silenceNotifications; this.silenceNotifications = true; this.mathfield.host.dispatchEvent( new InputEvent("input", __spreadProps(__spreadValues({}, options), { // To work around a bug in WebKit/Safari (the inputType property gets stripped), include the inputType as the 'data' property. (see #1843) data: options.data ? options.data : (_a3 = options.inputType) != null ? _a3 : "", bubbles: true, composed: true })) ); this.silenceNotifications = save; } selectionDidChange() { if (!this.mathfield) return; if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this.mathfield)); if (this.silenceNotifications) return; const save = this.silenceNotifications; this.silenceNotifications = true; this.mathfield.onSelectionDidChange(); this.silenceNotifications = save; } }; function atomIsInRange(model, atom, first, last) { const offset = model.offsetOf(atom); if (offset < first || offset > last) return false; if (!atom.hasChildren) return true; const firstOffset = model.offsetOf(atom.firstChild); if (firstOffset >= first && firstOffset <= last) { const lastOffset = model.offsetOf(atom.lastChild); if (lastOffset >= first && lastOffset <= last) return true; } return false; } function childrenInRange(model, atom, range2) { if (!(atom == null ? void 0 : atom.hasChildren)) return false; const [start, end] = range2; const first = model.offsetOf(atom.firstChild); const last = model.offsetOf(atom.lastChild); if (first >= start && first <= end && last >= first && last <= end) return true; return false; } // src/editor-model/delete.ts function onDelete(model, direction, atom, branch) { var _a3, _b3, _c2, _d2, _e, _f; const parent = atom.parent; if (parent && atom instanceof LeftRightAtom) { const atStart = !branch && direction === "forward" || branch === "body" && direction === "backward"; let pos = atStart ? model.offsetOf(atom.firstChild) : model.offsetOf(atom.lastChild); if (atStart) { if (atom.rightDelim !== "?" && atom.rightDelim !== ".") { atom.leftDelim = "."; atom.isDirty = true; } else { parent.addChildrenAfter(atom.removeBranch("body"), atom); parent.removeChild(atom); pos--; } } else { if (atom.leftDelim !== "?" && atom.leftDelim !== ".") { atom.rightDelim = "."; atom.isDirty = true; } else { parent.addChildrenAfter(atom.removeBranch("body"), atom); parent.removeChild(atom); pos--; } } model.position = pos; return true; } if (parent && atom.type === "surd") { if (direction === "forward" && !branch || direction === "backward" && branch === "body") { const pos = atom.leftSibling; if (atom.hasChildren) parent.addChildrenAfter(atom.removeBranch("body"), atom); parent.removeChild(atom); model.position = model.offsetOf(pos); } else if (direction === "forward" && branch === "body") { model.position = model.offsetOf(atom); } else if (!branch && direction === "backward") { if (atom.hasChildren) model.position = model.offsetOf(atom.lastChild); else { model.position = Math.max(0, model.offsetOf(atom) - 1); parent.removeChild(atom); } } else if (branch === "above") { if (atom.hasEmptyBranch("above")) atom.removeBranch("above"); if (direction === "backward") { model.position = model.offsetOf(atom.leftSibling); } else { model.position = model.offsetOf(atom.body[0]); } } return true; } if (parent && (atom.type === "box" || atom.type === "enclose")) { const pos = branch && direction === "backward" || !branch && direction === "forward" ? atom.leftSibling : atom.lastChild; parent.addChildrenAfter(atom.removeBranch("body"), atom); parent.removeChild(atom); model.position = model.offsetOf(pos); return true; } if (atom.type === "genfrac" || atom.type === "overunder") { if (!branch) { if (atom.type === "overunder" && atom.hasEmptyBranch("body")) return false; if (atom.type === "genfrac" && atom.hasEmptyBranch("below") && atom.hasEmptyBranch("above")) return false; model.position = model.offsetOf( direction === "forward" ? atom.firstChild : atom.lastChild ); return true; } const firstBranch = MathfieldElement.fractionNavigationOrder === "numerator-denominator" ? "above" : "below"; const secondBranch = firstBranch === "above" ? "below" : "above"; if (parent && (direction === "forward" && branch === firstBranch || direction === "backward" && branch === secondBranch)) { const first = atom.removeBranch(firstBranch); const second = atom.removeBranch(secondBranch); parent.addChildrenAfter([...first, ...second], atom); parent.removeChild(atom); model.position = model.offsetOf( first.length > 0 ? first[first.length - 1] : second[0] ); return true; } if (direction === "backward") model.position = model.offsetOf(atom.leftSibling); else model.position = model.offsetOf(atom); return true; } if (atom.isExtensibleSymbol || atom.type === "subsup") { if (!branch && direction === "forward") return false; if (!branch) { if (atom.subscript || atom.superscript) { const pos = direction === "forward" ? (_c2 = (_a3 = atom.superscript) == null ? void 0 : _a3[0]) != null ? _c2 : (_b3 = atom.subscript) == null ? void 0 : _b3[0] : (_f = (_d2 = atom.subscript) == null ? void 0 : _d2[0].lastSibling) != null ? _f : (_e = atom.superscript) == null ? void 0 : _e[0].lastSibling; if (pos) model.position = model.offsetOf(pos); return true; } return false; } if (!atom.hasChildren && atom.type === "subsup") { const pos = direction === "forward" ? model.offsetOf(atom) : Math.max(0, model.offsetOf(atom) - 1); atom.parent.removeChild(atom); model.position = pos; return true; } if (branch === "superscript") { if (direction === "backward") { const pos = model.offsetOf(atom.firstChild) - 1; console.assert(pos >= 0); model.position = pos; } else if (atom.subscript) model.position = model.offsetOf(atom.subscript[0]); else model.position = model.offsetOf(atom); } else if (branch === "subscript") { if (direction === "backward" && atom.superscript) { model.position = model.offsetOf(atom.superscript[0].lastSibling); } else if (direction === "backward") { model.position = model.offsetOf(atom.firstChild) - 1; } else { model.position = model.offsetOf(atom); } } if (branch && atom.hasEmptyBranch(branch)) { atom.removeBranch(branch); if (atom.type === "subsup" && !atom.subscript && !atom.superscript) { const pos = direction === "forward" ? model.offsetOf(atom) : Math.max(0, model.offsetOf(atom) - 1); atom.parent.removeChild(atom); model.position = pos; } } return true; } if ((parent == null ? void 0 : parent.type) === "genfrac" && !branch && atom.type !== "first") { let pos = model.offsetOf(atom.leftSibling); parent.removeChild(atom); if (parent.hasEmptyBranch("above") && parent.hasEmptyBranch("below")) { pos = model.offsetOf(parent.leftSibling); parent.parent.removeChild(parent); model.announce("delete", void 0, [parent]); model.position = pos; return true; } model.announce("delete", void 0, [atom]); model.position = pos; return true; } if (direction === "backward" && ((parent == null ? void 0 : parent.command) === "\\ln" || (parent == null ? void 0 : parent.command) === "\\log") && atom.parentBranch !== "body") { const pos = model.offsetOf(parent.leftSibling); parent.parent.removeChild(parent); model.announce("delete", void 0, [parent]); model.position = pos; return true; } return false; } function deleteBackward(model) { if (!model.mathfield.isSelectionEditable) return false; if (!model.contentWillChange({ inputType: "deleteContentBackward" })) return false; if (!model.selectionIsCollapsed) return deleteRange(model, range(model.selection), "deleteContentBackward"); return model.deferNotifications( { content: true, selection: true, type: "deleteContentBackward" }, () => { let target = model.at(model.position); if (target && onDelete(model, "backward", target)) return; if (target == null ? void 0 : target.isFirstSibling) { if (onDelete(model, "backward", target.parent, target.parentBranch)) return; target = null; } if (!target) { model.announce("plonk"); return; } model.position = model.offsetOf(target.leftSibling); target.parent.removeChild(target); model.announce("delete", void 0, [target]); } ); } function deleteForward(model) { if (!model.mathfield.isSelectionEditable) return false; if (!model.contentWillChange({ inputType: "deleteContentForward" })) return false; if (!model.selectionIsCollapsed) return deleteRange(model, range(model.selection), "deleteContentForward"); return model.deferNotifications( { content: true, selection: true, type: "deleteContentForward" }, () => { var _a3, _b3; let target = model.at(model.position).rightSibling; if (target && onDelete(model, "forward", target)) return; if (!target) { target = model.at(model.position); if (target.isLastSibling && onDelete(model, "forward", target.parent, target.parentBranch)) return; target = void 0; } else if (model.at(model.position).isLastSibling && onDelete(model, "forward", target.parent, target.parentBranch)) return; if (model.position === model.lastOffset || !target) { model.announce("plonk"); return; } target.parent.removeChild(target); let sibling = (_a3 = model.at(model.position)) == null ? void 0 : _a3.rightSibling; while ((sibling == null ? void 0 : sibling.type) === "subsup") { sibling.parent.removeChild(sibling); sibling = (_b3 = model.at(model.position)) == null ? void 0 : _b3.rightSibling; } model.announce("delete", void 0, [target]); } ); } function deleteRange(model, range2, type) { const result = model.getAtoms(range2); if (result.length > 0 && result[0].parent) { let firstChild = result[0].parent.firstChild; if (firstChild.type === "first") firstChild = firstChild.rightSibling; const lastChild = result[result.length - 1].parent.lastChild; let firstSelected = result[0]; if (firstSelected.type === "first") firstSelected = firstSelected.rightSibling; const lastSelected = result[result.length - 1]; if (firstSelected === firstChild && lastSelected === lastChild) { const parent = result[0].parent; if (parent.parent && parent.type !== "prompt") range2 = [model.offsetOf(parent.leftSibling), model.offsetOf(parent)]; } if (result.length === 1 && result[0].type === "placeholder" && result[0].parent.type === "genfrac") { const genfrac = result[0].parent; const branch = result[0].parentBranch === "below" ? "above" : "below"; const pos = model.offsetOf(genfrac.leftSibling); return model.deferNotifications( { content: true, selection: true, type }, () => { var _a3, _b3; const numer = genfrac.removeBranch(branch); if (!(numer.length === 1 && numer[0].type === "placeholder")) { const lastAtom = genfrac.parent.addChildrenAfter(numer, genfrac); (_a3 = genfrac.parent) == null ? void 0 : _a3.removeChild(genfrac); model.position = model.offsetOf(lastAtom); } else { (_b3 = genfrac.parent) == null ? void 0 : _b3.removeChild(genfrac); model.position = Math.max(0, pos); } } ); } } return model.deferNotifications( { content: true, selection: true, type }, () => model.deleteAtoms(range2) ); } // src/editor-model/commands-delete.ts register2( { deleteAll: (model) => model.contentWillChange({ inputType: "deleteContent" }) && deleteRange(model, [0, -1], "deleteContent"), deleteForward: (model) => deleteForward(model), deleteBackward: (model) => deleteBackward(model), deleteNextWord: (model) => model.contentWillChange({ inputType: "deleteWordForward" }) && deleteRange( model, [model.anchor, wordBoundaryOffset(model, model.position, "forward")], "deleteWordForward" ), deletePreviousWord: (model) => model.contentWillChange({ inputType: "deleteWordBackward" }) && deleteRange( model, [model.anchor, wordBoundaryOffset(model, model.position, "backward")], "deleteWordBackward" ), deleteToGroupStart: (model) => model.contentWillChange({ inputType: "deleteSoftLineBackward" }) && deleteRange( model, [model.anchor, model.offsetOf(model.at(model.position).firstSibling)], "deleteSoftLineBackward" ), deleteToGroupEnd: (model) => model.contentWillChange({ inputType: "deleteSoftLineForward" }) && deleteRange( model, [model.anchor, model.offsetOf(model.at(model.position).lastSibling)], "deleteSoftLineForward" ), deleteToMathFieldStart: (model) => model.contentWillChange({ inputType: "deleteHardLineBackward" }) && deleteRange(model, [model.anchor, 0], "deleteHardLineBackward"), deleteToMathFieldEnd: (model) => model.contentWillChange({ inputType: "deleteHardLineForward" }) && deleteRange(model, [model.anchor, -1], "deleteHardLineForward") }, { target: "model", audioFeedback: "delete", canUndo: true, changeContent: true, changeSelection: true } ); // src/editor-mathfield/mathfield-private.ts var DEFAULT_KEYBOARD_TOGGLE_GLYPH = ``; var MENU_GLYPH = ``; var _Mathfield = class { /** * * - `options.computeEngine`: An instance of a `ComputeEngine`. It is used to parse and serialize * LaTeX strings, using the information contained in the dictionaries * of the Compute Engine to determine, for example, which symbols are * numbers or which are functions, and therefore correctly interpret * `bf(x)` as `b \\times f(x)`. * * If no instance is provided, a new default one is created. * * @param element - The DOM element that this mathfield is attached to. * Note that `element.mathfield` is this object. */ constructor(element, options) { this.focusBlurInProgress = false; var _a3, _b3, _c2; this.options = __spreadValues(__spreadProps(__spreadValues({}, getDefault()), { macros: getMacros(), registers: getDefaultRegisters() }), update(options)); this.eventController = new AbortController(); const signal = this.eventController.signal; if (options.eventSink) this.host = options.eventSink; this.element = element; element.mathfield = this; this.blurred = true; this.keystrokeCaptionVisible = false; this.suggestionIndex = 0; this.inlineShortcutBuffer = []; this.inlineShortcutBufferFlushTimer = 0; this.defaultStyle = {}; this.adoptStyle = "left"; if (this.options.defaultMode === "inline-math") this.element.classList.add("ML__is-inline"); else this.element.classList.remove("ML__is-inline"); this.dirty = false; let elementText = (_b3 = (_a3 = options.value) != null ? _a3 : this.element.textContent) != null ? _b3 : ""; elementText = elementText.trim(); const mode = effectiveMode(this.options); const root = new Atom({ type: "root", mode, body: parseLatex(elementText, { context: this.context }) }); this.model = new _Model(this, mode, root); this.undoManager = new UndoManager(this.model); const markup = []; markup.push( `` ); markup.push( '"); markup.push(""); markup.push( "" ); markup.push(""); this.element.innerHTML = window.MathfieldElement.createHTML( markup.join("") ); if (!this.element.children) { console.error( `%cMathLive 0.98.5: Something went wrong and the mathfield could not be created.%c If you are using Vue, this may be because you are using the runtime-only build of Vue. Make sure to include \`runtimeCompiler: true\` in your Vue configuration. There may a warning from Vue in the log above.`, "color:red;font-family:system-ui;font-size:1.2rem;font-weight:bold", "color:inherit;font-family:system-ui;font-size:inherit;font-weight:inherit" ); return; } this._l10Subscription = l10n.subscribe(() => l10n.update(this.element)); l10n.update(this.element); this.field = this.element.querySelector("[part=content]"); this.field.addEventListener( "click", (evt) => evt.stopImmediatePropagation(), { capture: false, signal } ); this.field.addEventListener("wheel", this, { passive: false, signal }); if ("PointerEvent" in window) this.field.addEventListener("pointerdown", this, { signal }); else this.field.addEventListener("mousedown", this, { signal }); (_c2 = this.element.querySelector("[part=virtual-keyboard-toggle]")) == null ? void 0 : _c2.addEventListener( "click", () => { if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.hide(); else { window.mathVirtualKeyboard.show({ animate: true }); window.mathVirtualKeyboard.update(makeProxy(this)); } }, { signal } ); this._menu = new Menu(getDefaultMenuItems(this), { host: this.host }); this.field.addEventListener("contextmenu", this, { signal }); const menuToggle = this.element.querySelector("[part=menu-toggle]"); menuToggle == null ? void 0 : menuToggle.addEventListener( "pointerdown", (ev) => { if (ev.currentTarget !== menuToggle) return; if (this._menu.state !== "closed") return; this.element.classList.add("tracking"); const bounds = menuToggle.getBoundingClientRect(); this._menu.modifiers = keyboardModifiersFromEvent(ev); this._menu.show({ target: menuToggle, location: { x: bounds.left, y: bounds.bottom }, onDismiss: () => this.element.classList.remove("tracking") }); ev.preventDefault(); ev.stopPropagation(); }, { signal } ); if (this.model.atoms.length <= 1 || this.disabled || this.readOnly && !this.hasEditableContent || this.userSelect === "none") menuToggle.style.display = "none"; this.ariaLiveText = this.element.querySelector("[role=status]"); this.keyboardDelegate = delegateKeyboardEvents( this.element.querySelector(".ML__keyboard-sink"), this.element, this ); window.addEventListener("resize", this, { signal }); document.addEventListener("scroll", this, { signal }); this.resizeObserver = new ResizeObserver(() => requestUpdate(this)); this.resizeObserver.observe(this.field); window.mathVirtualKeyboard.addEventListener( "virtual-keyboard-toggle", this, { signal } ); if (gKeyboardLayout && !l10n.locale.startsWith(gKeyboardLayout.locale)) setKeyboardLayoutLocale(l10n.locale); if (gFontsState !== "ready") document.fonts.ready.then(() => renderSelection(this)); element.querySelector("[part=container]").style.removeProperty("visibility"); this.undoManager.startRecording(); this.undoManager.snapshot("set-value"); } get defaultStyle() { return this._defaultStyle; } set defaultStyle(value) { this._defaultStyle = value; } /** Depending on the value of `adoptStyle` return the style of the * sibling or the default style. * * This style is the one that will be applied to the next inserted atom. * */ get effectiveStyle() { if (this.adoptStyle === "none") return this.defaultStyle; const atom = this.model.at(this.model.position); const sibling = this.adoptStyle === "right" ? atom.rightSibling : atom; if (!sibling) return this.defaultStyle; if (sibling.type === "group") { const branch = sibling.branch("body"); if (!branch || branch.length < 2) return {}; if (this.adoptStyle === "right") return branch[1].computedStyle; return branch[branch.length - 1].computedStyle; } return sibling.computedStyle; } connectToVirtualKeyboard() { if (this.connectedToVirtualKeyboard) return; this.connectedToVirtualKeyboard = true; window.addEventListener("message", this, { signal: this.eventController.signal }); window.mathVirtualKeyboard.connect(); if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this)); updateEnvironmentPopover(this); } disconnectFromVirtualKeyboard() { if (!this.connectedToVirtualKeyboard) return; window.removeEventListener("message", this); window.mathVirtualKeyboard.disconnect(); this.connectedToVirtualKeyboard = false; hideEnvironmentPopover(); } showMenu(_) { var _a3, _b3; const location = (_b3 = (_a3 = _ == null ? void 0 : _.location) != null ? _a3 : getCaretPoint(this.field)) != null ? _b3 : void 0; const modifiers = _ == null ? void 0 : _.modifiers; const target = this.element.querySelector("[part=container]"); return this._menu.show({ target, location, modifiers }); } get colorMap() { return (name) => { var _a3, _b3, _c2; return (_c2 = (_b3 = (_a3 = this.options).colorMap) == null ? void 0 : _b3.call(_a3, name)) != null ? _c2 : defaultColorMap(name); }; } get backgroundColorMap() { return (name) => { var _a3, _b3, _c2, _d2, _e, _f; return (_f = (_e = (_b3 = (_a3 = this.options).backgroundColorMap) == null ? void 0 : _b3.call(_a3, name)) != null ? _e : (_d2 = (_c2 = this.options).colorMap) == null ? void 0 : _d2.call(_c2, name)) != null ? _f : defaultBackgroundColorMap(name); }; } get smartFence() { var _a3; return (_a3 = this.options.smartFence) != null ? _a3 : false; } get readOnly() { var _a3; return (_a3 = this.options.readOnly) != null ? _a3 : false; } get disabled() { var _a3, _b3; return (_b3 = (_a3 = this.host) == null ? void 0 : _a3["disabled"]) != null ? _b3 : false; } // This reflects the contenteditable attribute. // Use hasEditableContent instead to take into account readonly and disabled // states. get contentEditable() { if (!this.host) return false; return this.host.getAttribute("contenteditable") !== "false"; } // This reflect the `user-select` CSS property get userSelect() { if (!this.host) return ""; const style = getComputedStyle(this.host); return style.getPropertyValue("user-select") || style.getPropertyValue("-webkit-user-select"); } // Use to hide/show the virtual keyboard toggle. If false, no point in // showing the toggle. get hasEditableContent() { if (this.disabled || !this.contentEditable) return false; return !this.readOnly || this.hasEditablePrompts; } get hasEditablePrompts() { return this.readOnly && !this.disabled && this.contentEditable && this.model.findAtom( (a) => a.type === "prompt" && !a.locked ) !== void 0; } /** Returns true if the selection is editable: * - mathfield is not disabled, and has contentEditable * - if mathfield is readonly, the current selection is in a prompt which is editable (not locked) */ get isSelectionEditable() { if (this.disabled || !this.contentEditable) return false; if (!this.readOnly) return true; const anchor = this.model.at(this.model.anchor); const cursor = this.model.at(this.model.position); const ancestor = Atom.commonAncestor(anchor, cursor); if ((ancestor == null ? void 0 : ancestor.type) === "prompt" || (ancestor == null ? void 0 : ancestor.parentPrompt)) return true; return false; } get letterShapeStyle() { var _a3; return (_a3 = this.options.letterShapeStyle) != null ? _a3 : "tex"; } get minFontScale() { return this.options.minFontScale; } /** Returns styles shared by all selected atoms */ get selectionStyle() { if (this.model.selectionIsCollapsed) return this.effectiveStyle; const selectedAtoms = this.model.getAtoms(this.model.selection); if (selectedAtoms.length === 0) return {}; const style = __spreadValues({}, selectedAtoms[0].style); for (const atom of selectedAtoms) { for (const [key, value] of Object.entries(atom.style)) if (style[key] !== value) delete style[key]; } return style; } /** * * If there is a selection, return if all the atoms in the selection, * some of them or none of them match the `style` argument. * * If there is no selection, return 'all' if the current implicit style * (determined by a combination of the style of the previous atom and * the current style) matches the `style` argument, 'none' if it does not. */ queryStyle(inStyle) { const style = validateStyle(this, inStyle); if ("verbatimColor" in style) delete style.verbatimColor; if ("verbatimBackgroundColor" in style) delete style.verbatimBackgroundColor; const keyCount = Object.keys(style).length; if (keyCount === 0) return "all"; if (keyCount > 1) { for (const prop2 of Object.keys(style)) { const result = this.queryStyle({ [prop2]: style[prop2] }); if (result === "none") return "none"; if (result === "some") return "some"; } return "all"; } const prop = Object.keys(style)[0]; const value = style[prop]; if (this.model.selectionIsCollapsed) { if (this.effectiveStyle[prop] === value) return "all"; return "none"; } const atoms = this.model.getAtoms(this.model.selection, { includeChildren: true }); let length = atoms.length; if (length === 0) return "none"; let count = 0; for (const atom of atoms) { if (atom.type === "first") { length -= 1; continue; } if (atom.style[prop] === value) count += 1; } if (count === 0) return "none"; if (count === length) return "all"; return "some"; } get keybindings() { var _a3, _b3; if (this._keybindings) return this._keybindings; const [keybindings, errors] = normalizeKeybindings( this.options.keybindings, (_a3 = getActiveKeyboardLayout()) != null ? _a3 : getDefaultKeyboardLayout() ); if (((_b3 = getActiveKeyboardLayout()) == null ? void 0 : _b3.score) > 0) { this._keybindings = keybindings; if (errors.length > 0) { console.error( `MathLive 0.98.5: Invalid keybindings for current keyboard layout`, errors ); } } return keybindings; } get menu() { return this._menu; } setOptions(config) { var _a3; this.options = __spreadValues(__spreadValues({}, this.options), update(config)); this._keybindings = void 0; if (this.options.defaultMode === "inline-math") this.element.classList.add("ML__is-inline"); else this.element.classList.remove("ML__is-inline"); let mode = this.options.defaultMode; if (mode === "inline-math") mode = "math"; if (((_a3 = this.model.root.firstChild) == null ? void 0 : _a3.mode) !== mode) this.model.root.firstChild.mode = mode; if (this.options.readOnly) { if (this.hasFocus() && window.mathVirtualKeyboard.visible) this.executeCommand("hideVirtualKeyboard"); } const content = Atom.serialize([this.model.root], { expandMacro: false, defaultMode: this.options.defaultMode }); if ("macros" in config || this.model.getValue() !== content) { ModeEditor.insert(this.model, content, { insertionMode: "replaceAll", selectionMode: "after", format: "latex", silenceNotifications: true, mode: "math" }); } if ("value" in config || "macros" in config || "registers" in config || "colorMap" in config || "backgroundColorMap" in config || "letterShapeStyle" in config || "minFontScale" in config || "readOnly" in config || "placeholderSymbol" in config) requestUpdate(this); } getOptions(keys) { return get(this.options, keys); } getOption(key) { return get(this.options, key); } /* * handleEvent is a function invoked when an event is registered with an * object. * The name is defined by `addEventListener()` and cannot be changed. * This pattern is used to be able to release bound event handlers, * (event handlers that need access to `this`) as the `bind()` function * would create a new function that would have to be kept track of * to be able to properly remove the event handler later. */ async handleEvent(evt) { var _a3; if (!isValidMathfield(this)) return; if (isVirtualKeyboardMessage(evt)) { if (!validateOrigin(evt.origin, (_a3 = this.options.originValidator) != null ? _a3 : "none")) { throw new DOMException( `Message from unknown origin (${evt.origin}) cannot be handled`, "SecurityError" ); } const { action } = evt.data; if (action === "execute-command") { const command = evt.data.command; if (getCommandTarget(command) === "virtual-keyboard") return; this.executeCommand(command); } else if (action === "update-state") { } else if (action === "focus") this.focus({ preventScroll: true }); else if (action === "blur") this.blur(); return; } switch (evt.type) { case "focus": this.onFocus(); break; case "blur": this.onBlur(); break; case "mousedown": if (this.userSelect !== "none") onPointerDown(this, evt); break; case "pointerdown": if (this.userSelect !== "none") { onPointerDown(this, evt); if (evt.shiftKey === false) { if (await onContextMenu( evt, this.element.querySelector("[part=container]"), this._menu )) PointerTracker.stop(); } } break; case "contextmenu": if (this.userSelect !== "none" && evt.shiftKey === false) { if (await onContextMenu( evt, this.element.querySelector("[part=container]"), this._menu )) PointerTracker.stop(); } break; case "virtual-keyboard-toggle": if (this.hasFocus()) updateEnvironmentPopover(this); break; case "resize": if (this.geometryChangeTimer) cancelAnimationFrame(this.geometryChangeTimer); this.geometryChangeTimer = requestAnimationFrame( () => isValidMathfield(this) && this.onGeometryChange() ); break; case "scroll": if (this.geometryChangeTimer) cancelAnimationFrame(this.geometryChangeTimer); this.geometryChangeTimer = requestAnimationFrame( () => isValidMathfield(this) && this.onGeometryChange() ); break; case "wheel": this.onWheel(evt); break; default: console.warn("Unexpected event type", evt.type); } } dispose() { if (!isValidMathfield(this)) return; l10n.unsubscribe(this._l10Subscription); this.keyboardDelegate.dispose(); this.keyboardDelegate = void 0; this.eventController.abort(); this.eventController = void 0; this.resizeObserver.disconnect(); window.mathVirtualKeyboard.removeEventListener( "virtual-keyboard-toggle", this ); this.disconnectFromVirtualKeyboard(); this.model.dispose(); const element = this.element; delete element.mathfield; this.element = void 0; this.host = void 0; this.field = void 0; this.ariaLiveText = void 0; disposeKeystrokeCaption(); disposeSuggestionPopover(); disposeEnvironmentPopover(); } flushInlineShortcutBuffer(options) { options != null ? options : options = { defer: false }; if (!options.defer) { this.inlineShortcutBuffer = []; clearTimeout(this.inlineShortcutBufferFlushTimer); this.inlineShortcutBufferFlushTimer = 0; return; } if (this.options.inlineShortcutTimeout > 0) { clearTimeout(this.inlineShortcutBufferFlushTimer); this.inlineShortcutBufferFlushTimer = setTimeout( () => this.flushInlineShortcutBuffer(), this.options.inlineShortcutTimeout ); } } executeCommand(command) { if (getCommandTarget(command) === "virtual-keyboard") { this.focus({ preventScroll: true }); window.mathVirtualKeyboard.executeCommand(command); requestAnimationFrame( () => window.mathVirtualKeyboard.update(makeProxy(this)) ); return false; } return perform(this, command); } get errors() { return validateLatex(this.model.getValue(), { context: this.context }); } getValue(arg1, arg2, arg3) { return this.model.getValue(arg1, arg2, arg3); } setValue(value, options) { var _a3; options = options != null ? options : { mode: "math" }; if (options.insertionMode === void 0) options.insertionMode = "replaceAll"; if (options.format === void 0 || options.format === "auto") options.format = "latex"; if (options.mode === void 0 || options.mode === "auto") options.mode = (_a3 = getMode(this.model, this.model.position)) != null ? _a3 : "math"; const couldUndo = this.undoManager.canUndo(); if (ModeEditor.insert(this.model, value, options)) { requestUpdate(this); if (!couldUndo) this.undoManager.reset(); this.undoManager.snapshot("set-value"); } } get expression() { const ce = window.MathfieldElement.computeEngine; if (!ce) { console.error( `MathLive 0.98.5: no compute engine available. Make sure the Compute Engine library is loaded.` ); return null; } return ce.box(ce.parse(this.model.getValue("latex-unstyled"))); } /** Make sure the caret is visible within the matfield. * If using mathfield element, make sure the mathfield element is visible in * the page */ scrollIntoView() { var _a3; if (!this.element) return; if (this.host) { if (this.options.onScrollIntoView) this.options.onScrollIntoView(this); else { this.host.scrollIntoView({ block: "nearest", inline: "nearest" }); if (window.mathVirtualKeyboard.visible && window.mathVirtualKeyboard.container === window.document.body) { const kbdBounds = window.mathVirtualKeyboard.boundingRect; const mathfieldBounds = this.host.getBoundingClientRect(); if (mathfieldBounds.bottom > kbdBounds.top) { (_a3 = window.document.scrollingElement) == null ? void 0 : _a3.scrollBy( 0, mathfieldBounds.bottom - kbdBounds.top + 8 ); } } } } if (this.dirty) render(this, { interactive: true }); const fieldBounds = this.field.getBoundingClientRect(); let caretPoint = null; if (this.model.selectionIsCollapsed) caretPoint = getCaretPoint(this.field); else { const selectionBounds = getSelectionBounds(this); if (selectionBounds.length > 0) { let maxRight = -Infinity; let minTop = -Infinity; for (const r of selectionBounds) { if (r.right > maxRight) maxRight = r.right; if (r.top < minTop) minTop = r.top; } caretPoint = { x: maxRight + fieldBounds.left - this.field.scrollLeft, y: minTop + fieldBounds.top - this.field.scrollTop, height: 0 }; } } if (this.host && caretPoint) { const hostBounds = this.host.getBoundingClientRect(); const y = caretPoint.y; let top = this.host.scrollTop; if (y < hostBounds.top) top = y - hostBounds.top + this.host.scrollTop; else if (y > hostBounds.bottom) top = y - hostBounds.bottom + this.host.scrollTop + caretPoint.height; this.host.scroll({ top, left: 0 }); } if (caretPoint) { const x = caretPoint.x - window.scrollX; let left = this.field.scrollLeft; if (x < fieldBounds.left) left = x - fieldBounds.left + this.field.scrollLeft - 20; else if (x > fieldBounds.right) left = x - fieldBounds.right + this.field.scrollLeft + 20; this.field.scroll({ top: this.field.scrollTop, // should always be 0 left }); } } insert(s, options) { if (typeof s !== "string") return false; if (s.length === 0 && ((options == null ? void 0 : options.insertionMode) === "insertBefore" || (options == null ? void 0 : options.insertionMode) === "insertAfter")) return false; if (s.length === 0 && this.model.selectionIsCollapsed) return false; this.flushInlineShortcutBuffer(); options = options != null ? options : { mode: "math" }; if (options.focus) this.focus(); if (options.feedback) { if (window.MathfieldElement.keypressVibration && canVibrate()) navigator.vibrate(HAPTIC_FEEDBACK_DURATION); window.MathfieldElement.playSound("keypress"); } if (s === "\\\\") { addRowAfter(this.model); } else if (s === "&") addColumnAfter(this.model); else { if (this.model.selectionIsCollapsed) { ModeEditor.insert(this.model, s, __spreadValues({ style: this.model.at(this.model.position).computedStyle }, options)); } else ModeEditor.insert(this.model, s, options); } this.snapshot(`insert-${this.model.at(this.model.position).type}`); requestUpdate(this); if (options.scrollIntoView) this.scrollIntoView(); return true; } switchMode(mode, prefix = "", suffix = "") { var _a3; if (this.model.mode === mode || !this.hasEditableContent || !this.contentEditable || this.disabled) return; const previousMode = this.model.mode; this.model.mode = mode; if (!((_a3 = this.host) == null ? void 0 : _a3.dispatchEvent( new Event("mode-change", { bubbles: true, composed: true, cancelable: true }) ))) { this.model.mode = previousMode; return; } const currentMode = this.model.mode; const { model } = this; model.deferNotifications( { content: Boolean(suffix) || Boolean(prefix), selection: true, type: "insertText" }, () => { let contentChanged = false; this.flushInlineShortcutBuffer(); this.stopCoalescingUndo(); if (prefix && mode !== "latex") { const atoms = parseLatex(prefix, { context: this.context, parseMode: mode }); model.collapseSelection("forward"); const cursor = model.at(model.position); model.position = model.offsetOf( cursor.parent.addChildrenAfter(atoms, cursor) ); contentChanged = true; } this.model.mode = mode; if (mode === "latex") { let wasCollapsed = model.selectionIsCollapsed; complete(this, "accept"); let latex; let cursor = model.at(model.position); if (wasCollapsed) latex = "\\"; else { const selRange = range(model.selection); latex = this.model.getValue(selRange, "latex"); const extractedAtoms = this.model.extractAtoms(selRange); if (extractedAtoms.length === 1 && extractedAtoms[0].type === "placeholder") { latex = prefix; wasCollapsed = true; } cursor = model.at(selRange[0]); } const atom = new LatexGroupAtom(latex); cursor.parent.addChildAfter(atom, cursor); if (wasCollapsed) model.position = model.offsetOf(atom.lastChild); else { model.setSelection( model.offsetOf(atom.firstChild), model.offsetOf(atom.lastChild) ); } } else { getLatexGroupBody(model).forEach((x) => { x.isError = false; }); } if (suffix) { const atoms = parseLatex(suffix, { context: this.context, parseMode: currentMode }); model.collapseSelection("forward"); const cursor = model.at(model.position); model.position = model.offsetOf( cursor.parent.addChildrenAfter(atoms, cursor) ); contentChanged = true; } requestUpdate(this); this.undoManager.snapshot(mode === "latex" ? "insert-latex" : "insert"); return contentChanged; } ); this.model.mode = mode; window.mathVirtualKeyboard.update(makeProxy(this)); } hasFocus() { return !this.blurred; } focus(options) { var _a3; if (!this.hasFocus()) { this.keyboardDelegate.focus(); this.connectToVirtualKeyboard(); this.onFocus(); this.model.announce("line"); } if (!((_a3 = options == null ? void 0 : options.preventScroll) != null ? _a3 : false)) this.scrollIntoView(); } blur() { this.disconnectFromVirtualKeyboard(); if (!this.hasFocus()) return; this.keyboardDelegate.blur(); } select() { this.model.selection = { ranges: [[0, this.model.lastOffset]] }; this.focus(); } applyStyle(inStyle, inOptions = {}) { var _a3, _b3; const options = { operation: "set", silenceNotifications: false }; if (isRange(inOptions)) options.range = inOptions; else { if (inOptions.operation === "toggle") options.operation = "toggle"; options.range = inOptions.range; options.silenceNotifications = (_a3 = inOptions.silenceNotifications) != null ? _a3 : false; } const style = validateStyle(this, inStyle); const operation = (_b3 = options.operation) != null ? _b3 : "set"; if (options.range === void 0 && this.model.selectionIsCollapsed) { if (operation === "set") { this.defaultStyle = __spreadValues(__spreadValues({}, this.defaultStyle), style); return; } const newStyle = __spreadValues({}, this.defaultStyle); for (const prop of Object.keys(style)) { if (newStyle[prop] === style[prop]) { if (prop === "color") delete newStyle.verbatimColor; if (prop === "backgroundColor") delete newStyle.verbatimBackgroundColor; delete newStyle[prop]; } else newStyle[prop] = style[prop]; } this.defaultStyle = newStyle; return; } this.model.deferNotifications( { content: !options.silenceNotifications, type: "insertText" }, () => { if (options.range === void 0) { for (const range2 of this.model.selection.ranges) applyStyle(this.model, range2, style, { operation }); } else applyStyle(this.model, options.range, style, { operation }); } ); requestUpdate(this); } toggleContextMenu() { var _a3; if (!this._menu.visible) return false; if (this._menu.state === "open") { this._menu.hide(); return true; } this._menu.show({ target: this.element.querySelector("[part=container]"), location: (_a3 = this.getCaretPoint()) != null ? _a3 : void 0, onDismiss: () => { var _a4; return (_a4 = this.element) == null ? void 0 : _a4.focus(); } }); return true; } getCaretPoint() { const caretOffset = getCaretPoint(this.field); return caretOffset ? { x: caretOffset.x, y: caretOffset.y } : null; } setCaretPoint(x, y) { const newPosition = offsetFromPoint(this, x, y, { bias: 0 }); if (newPosition < 0) return false; const previousPosition = this.model.position; this.model.position = newPosition; this.model.announce("move", previousPosition); requestUpdate(this); return true; } getPrompt(id) { const prompt = this.model.findAtom( (a) => a.type === "prompt" && a.placeholderId === id ); console.assert( prompt !== void 0, `MathLive 0.98.5: no prompts with matching ID found` ); return prompt; } getPromptValue(id, format) { const prompt = this.getPrompt(id); if (!prompt) return ""; const first = this.model.offsetOf(prompt.firstChild); const last = this.model.offsetOf(prompt.lastChild); return this.model.getValue(first, last, format); } getPrompts(filter) { return this.model.getAllAtoms().filter((a) => { if (a.type !== "prompt") return false; if (!filter) return true; if (filter.id && a.placeholderId !== filter.id) return false; if (filter.locked && a.locked !== filter.locked) return false; if (filter.correctness === "undefined" && a.correctness) return false; if (filter.correctness && a.correctness !== filter.correctness) return false; return true; }).map((a) => a.placeholderId); } setPromptValue(id, value, insertOptions) { if (value !== void 0) { const prompt = this.getPrompt(id); if (!prompt) { console.error(`MathLive 0.98.5: unknown prompt ${id}`); return; } const branchRange = this.model.getBranchRange( this.model.offsetOf(prompt), "body" ); this.model.setSelection(branchRange); this.insert(value, __spreadProps(__spreadValues({}, insertOptions), { insertionMode: "replaceSelection" })); } if (insertOptions == null ? void 0 : insertOptions.silenceNotifications) this.valueOnFocus = this.getValue(); requestUpdate(this); } setPromptState(id, state, locked) { const prompt = this.getPrompt(id); if (!prompt) { console.error(`MathLive 0.98.5: unknown prompt ${id}`); return; } if (state === "undefined") prompt.correctness = void 0; else if (typeof state === "string") prompt.correctness = state; if (typeof locked === "boolean") { prompt.locked = locked; prompt.captureSelection = locked; } requestUpdate(this); } getPromptState(id) { const prompt = this.getPrompt(id); if (!prompt) { console.error(`MathLive 0.98.5: unknown prompt ${id}`); return [void 0, true]; } return [prompt.correctness, prompt.locked]; } getPromptRange(id) { const prompt = this.getPrompt(id); if (!prompt) { console.error(`MathLive 0.98.5: unknown prompt ${id}`); return [0, 0]; } return this.model.getBranchRange(this.model.offsetOf(prompt), "body"); } canUndo() { return this.undoManager.canUndo(); } canRedo() { return this.undoManager.canRedo(); } popUndoStack() { this.undoManager.pop(); } snapshot(op) { var _a3; if (this.undoManager.snapshot(op)) { if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this)); (_a3 = this.host) == null ? void 0 : _a3.dispatchEvent( new CustomEvent("undo-state-change", { bubbles: true, composed: true, detail: { type: "snapshot" } }) ); } } stopCoalescingUndo() { this.undoManager.stopCoalescing(this.model.selection); } stopRecording() { this.undoManager.stopRecording(); } startRecording() { this.undoManager.startRecording(); } undo() { var _a3; if (!this.undoManager.undo()) return; if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this)); (_a3 = this.host) == null ? void 0 : _a3.dispatchEvent( new CustomEvent("undo-state-change", { bubbles: true, composed: true, detail: { type: "undo" } }) ); } redo() { var _a3; if (!this.undoManager.redo()) return; if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this)); (_a3 = this.host) == null ? void 0 : _a3.dispatchEvent( new CustomEvent("undo-state-change", { bubbles: true, composed: true, detail: { type: "undo" } }) ); } resetUndo() { var _a3; (_a3 = this.undoManager) == null ? void 0 : _a3.reset(); } onSelectionDidChange() { var _a3, _b3; const model = this.model; this.keyboardDelegate.setValue( model.getValue(this.model.selection, "latex-expanded") ); { const cursor = model.at(model.position); const newMode = (_a3 = cursor.mode) != null ? _a3 : effectiveMode(this.options); if (this.model.mode !== newMode) { if (this.model.mode === "latex") { complete(this, "accept", { mode: newMode }); model.position = model.offsetOf(cursor); } else this.switchMode(newMode); } } (_b3 = this.host) == null ? void 0 : _b3.dispatchEvent( new Event("selection-change", { bubbles: true, composed: true }) ); if (window.mathVirtualKeyboard.visible) window.mathVirtualKeyboard.update(makeProxy(this)); updateEnvironmentPopover(this); } onContentWillChange(options) { var _a3, _b3, _c2; return (_c2 = (_b3 = this.host) == null ? void 0 : _b3.dispatchEvent( new InputEvent("beforeinput", __spreadProps(__spreadValues({}, options), { // To work around a bug in WebKit/Safari (the inputType property gets stripped), include the inputType as the 'data' property. (see #1843) data: options.data ? options.data : (_a3 = options.inputType) != null ? _a3 : "", cancelable: true, bubbles: true, composed: true })) )) != null ? _c2 : true; } onFocus() { if (this.focusBlurInProgress || !this.blurred) return; this.focusBlurInProgress = true; this.blurred = false; this.keyboardDelegate.focus(); this.stopCoalescingUndo(); render(this, { interactive: true }); this.valueOnFocus = this.model.getValue(); if (this.hasEditablePrompts && !this.model.at(this.model.anchor).parentPrompt) this.executeCommand("moveToNextPlaceholder"); this.focusBlurInProgress = false; } onBlur() { var _a3, _b3, _c2; if (this.focusBlurInProgress || this.blurred) return; this.focusBlurInProgress = true; this.stopCoalescingUndo(); this.blurred = true; this.ariaLiveText.textContent = ""; hideSuggestionPopover(this); if (this.model.getValue() !== this.valueOnFocus) { (_a3 = this.host) == null ? void 0 : _a3.dispatchEvent( new Event("change", { bubbles: true, composed: true }) ); } this.disconnectFromVirtualKeyboard(); (_b3 = this.host) == null ? void 0 : _b3.dispatchEvent( new Event("blur", { bubbles: false, // DOM 'focus' and 'blur' don't bubble composed: true }) ); (_c2 = this.host) == null ? void 0 : _c2.dispatchEvent( new UIEvent("focusout", { bubbles: true, // unlike 'blur', focusout does bubble composed: true }) ); requestUpdate(this); this.focusBlurInProgress = false; hideEnvironmentPopover(); const controller = new AbortController(); const signal = controller.signal; document.addEventListener( "visibilitychange", () => { if (document.visibilityState === "hidden") { document.addEventListener( "visibilitychange", () => { if (isValidMathfield(this) && document.visibilityState === "visible") this.focus({ preventScroll: true }); }, { once: true, signal } ); } }, { once: true, signal } ); setTimeout(() => controller.abort(), 100); } onInput(text) { onInput(this, text); } onKeystroke(evt) { return onKeystroke(this, evt); } onCompositionStart(_composition) { this.model.deleteAtoms(range(this.model.selection)); const caretPoint = getCaretPoint(this.field); if (!caretPoint) return; requestAnimationFrame(() => { render(this); this.keyboardDelegate.moveTo( caretPoint.x, caretPoint.y - caretPoint.height ); }); } onCompositionUpdate(composition) { updateComposition(this.model, composition); requestUpdate(this); } onCompositionEnd(composition) { removeComposition(this.model); onInput(this, composition, { simulateKeystroke: true }); } onCut(ev) { if (!this.isSelectionEditable) { this.model.announce("plonk"); return; } if (this.model.contentWillChange({ inputType: "deleteByCut" })) { this.stopCoalescingUndo(); ModeEditor.onCopy(this, ev); deleteRange(this.model, range(this.model.selection), "deleteByCut"); this.snapshot("cut"); requestUpdate(this); } } onCopy(ev) { ModeEditor.onCopy(this, ev); } onPaste(ev) { let result = this.isSelectionEditable; if (result) { result = ModeEditor.onPaste( this.model.at(this.model.position).mode, this, ev.clipboardData ); } if (!result) this.model.announce("plonk"); ev.preventDefault(); ev.stopPropagation(); return result; } onGeometryChange() { this._menu.hide(); updateSuggestionPopoverPosition(this); updateEnvironmentPopover(this); } onWheel(ev) { const wheelDelta = 5 * ev.deltaX; if (!Number.isFinite(wheelDelta) || wheelDelta === 0) return; const field = this.field; if (wheelDelta < 0 && field.scrollLeft === 0) return; if (wheelDelta > 0 && field.offsetWidth + field.scrollLeft >= field.scrollWidth) return; field.scrollBy({ top: 0, left: wheelDelta }); ev.preventDefault(); ev.stopPropagation(); } getHTMLElement(atom) { let target = atom; while (!target.id && target.hasChildren) target = atom.children[0]; return this.field.querySelector( `[data-atom-id="${target.id}"]` ); } get context() { var _a3, _b3; return { registers: (_a3 = this.options.registers) != null ? _a3 : {}, smartFence: this.smartFence, letterShapeStyle: this.letterShapeStyle, minFontScale: this.minFontScale, placeholderSymbol: (_b3 = this.options.placeholderSymbol) != null ? _b3 : "\u25A2", colorMap: (name) => this.colorMap(name), backgroundColorMap: (name) => this.backgroundColorMap(name), getMacro: (token) => getMacroDefinition( token, this.options.macros ), atomIdsSettings: { seed: "random", groupNumbers: false } }; } }; // src/editor/speech-read-aloud.ts function removeHighlight(element) { if (!element) return; element.classList.remove("ML__highlight"); if (element.children) for (const child of element.children) removeHighlight(child); } function highlightAtomID(element, atomID) { var _a3; if (!element) return; if (!atomID || ((_a3 = element.dataset) == null ? void 0 : _a3.atomId) === atomID) { element.classList.add("ML__highlight"); if (element.children && element.children.length > 0) { [...element.children].forEach((x) => { if (x instanceof HTMLElement) highlightAtomID(x); }); } } else { element.classList.remove("ML__highlight"); if (element.children && element.children.length > 0) { [...element.children].forEach((x) => { if (x instanceof HTMLElement) highlightAtomID(x, atomID); }); } } } function defaultReadAloudHook(element, text) { var _a3; if (!isBrowser()) return; if (window.MathfieldElement.speechEngine !== "amazon") { console.error( `MathLive 0.98.5: Use Amazon TTS Engine for synchronized highlighting` ); if (typeof window.MathfieldElement.speakHook === "function") window.MathfieldElement.speakHook(text); return; } if (!window.AWS) { console.error( `MathLive 0.98.5: AWS SDK not loaded. See https://www.npmjs.com/package/aws-sdk` ); return; } const polly = new window.AWS.Polly({ apiVersion: "2016-06-10" }); const parameters = { OutputFormat: "json", VoiceId: (_a3 = window.MathfieldElement.speechEngineVoice) != null ? _a3 : "Joanna", Engine: "standard", // The neural engine does not appear to support ssml marks Text: text, TextType: "ssml", SpeechMarkTypes: ["ssml"] }; globalMathLive().readAloudElement = element; polly.synthesizeSpeech(parameters, (err, data) => { if (err) { console.trace( `MathLive 0.98.5: \`polly.synthesizeSpeech()\` error: ${err}` ); return; } if (!(data == null ? void 0 : data.AudioStream)) { console.log("polly.synthesizeSpeech():", data); return; } const response = new TextDecoder("utf-8").decode( new Uint8Array(data.AudioStream) ); globalMathLive().readAloudMarks = response.split("\n").map((x) => x ? JSON.parse(x) : {}); globalMathLive().readAloudTokens = []; for (const mark of globalMathLive().readAloudMarks) if (mark.value) globalMathLive().readAloudTokens.push(mark.value); globalMathLive().readAloudCurrentMark = ""; parameters.OutputFormat = "mp3"; parameters.SpeechMarkTypes = []; polly.synthesizeSpeech(parameters, (err2, data2) => { if (err2) { console.trace( `MathLive 0.98.5: \`polly.synthesizeSpeech("${text}") error:${err2}` ); return; } if (!(data2 == null ? void 0 : data2.AudioStream)) return; const uInt8Array = new Uint8Array(data2.AudioStream); const blob = new Blob([uInt8Array.buffer], { type: "audio/mpeg" }); const url = URL.createObjectURL(blob); const global = globalMathLive(); if (!global.readAloudAudio) { global.readAloudAudio = new Audio(); global.readAloudAudio.addEventListener("ended", () => { const mathfield = global.readAloudMathfield; global.readAloudStatus = "ended"; document.body.dispatchEvent( new Event("read-aloud-status-change", { bubbles: true, composed: true }) ); if (mathfield) { render(mathfield); global.readAloudElement = null; global.readAloudMathfield = null; global.readAloudTokens = []; global.readAloudMarks = []; global.readAloudCurrentMark = ""; } else removeHighlight(global.readAloudElement); }); global.readAloudAudio.addEventListener("timeupdate", () => { let value = ""; const target = global.readAloudAudio.currentTime * 1e3 + 100; for (const mark of global.readAloudMarks) if (mark.time < target) value = mark.value; if (global.readAloudCurrentMark !== value) { global.readAloudCurrentToken = value; if (value && value === global.readAloudFinalToken) global.readAloudAudio.pause(); else { global.readAloudCurrentMark = value; highlightAtomID( global.readAloudElement, global.readAloudCurrentMark ); } } }); } else global.readAloudAudio.pause(); global.readAloudAudio.src = url; global.readAloudStatus = "playing"; document.body.dispatchEvent( new Event("read-aloud-status-change", { bubbles: true, composed: true }) ); global.readAloudAudio.play(); }); }); } // src/public/mathfield-element.ts if (!isBrowser()) { console.error( `MathLive 0.98.5: this version of the MathLive library is for use in the browser. A subset of the API is available on the server side in the "mathlive-ssr" library. If using server side rendering (with React for example) you may want to do a dynamic import of the MathLive library inside a \`useEffect()\` call.` ); } var gDeferredState = /* @__PURE__ */ new WeakMap(); var AUDIO_FEEDBACK_VOLUME = 0.5; var DEPRECATED_OPTIONS = { letterShapeStyle: "mf.letterShapeStyle = ...", horizontalSpacingScale: 'Removed. Use `"thinmuskip"`, `"medmuskip"`, and `"thickmuskip"` registers ', macros: "mf.macros = ...", registers: "mf.registers = ...", backgroundColorMap: "mf.backgroundColorMap = ...", colorMap: "mf.colorMap = ...", enablePopover: "mf.popoverPolicy = ...", mathModeSpace: "mf.mathModeSpace = ...", placeholderSymbol: "mf.placeholderSymbol = ...", readOnly: "mf.readOnly = ...", removeExtraneousParentheses: "mf.removeExtraneousParentheses = ...", scriptDepth: "mf.scriptDepth = ...", smartFence: "mf.smartFence = ...", smartMode: "mf.smartMode = ...", smartSuperscript: "mf.smartSuperscript = ...", inlineShortcutTimeout: "mf.inlineShortcutTimeout = ...", inlineShortcuts: "mf.inlineShortcuts = ...", keybindings: "mf.keybindings = ...", virtualKeyboardMode: "mf.mathVirtualKeyboardPolicy = ...", customVirtualKeyboardLayers: "mathVirtualKeyboard.layers = ...", customVirtualKeyboards: "mathVirtualKeyboard.layouts = ...", keypressSound: "mathVirtualKeyboard.keypressSound = ...", keypressVibration: "mathVirtualKeyboard.keypressVibration = ...", plonkSound: "mathVirtualKeyboard.plonkSound = ...", virtualKeyboardContainer: "mathVirtualKeyboard.container = ...", virtualKeyboardLayout: "mathVirtualKeyboard.alphabeticLayout = ...", virtualKeyboardTheme: "No longer supported", virtualKeyboardToggleGlyph: "No longer supported", virtualKeyboardToolbar: "mathVirtualKeyboard.editToolbar = ...", virtualKeyboards: "Use `mathVirtualKeyboard.layouts`", speechEngine: "`MathfieldElement.speechEngine`", speechEngineRate: "`MathfieldElement.speechEngineRate`", speechEngineVoice: "`MathfieldElement.speechEngineVoice`", textToSpeechMarkup: "`MathfieldElement.textToSpeechMarkup`", textToSpeechRules: "`MathfieldElement.textToSpeechRules`", textToSpeechRulesOptions: "`MathfieldElement.textToSpeechRulesOptions`", readAloudHook: "`MathfieldElement.readAloudHook`", speakHook: "`MathfieldElement.speakHook`", computeEngine: "`MathfieldElement.computeEngine`", fontsDirectory: "`MathfieldElement.fontsDirectory`", soundsDirectory: "`MathfieldElement.soundsDirectory`", createHTML: "`MathfieldElement.createHTML`", onExport: "`MathfieldElement.onExport`", onInlineShortcut: "`MathfieldElement.onInlineShortcut`", onScrollIntoView: "`MathfieldElement.onScrollIntoView`", locale: "MathfieldElement.locale = ...", strings: "MathfieldElement.strings = ...", decimalSeparator: "MathfieldElement.decimalSeparator = ...", fractionNavigationOrder: "MathfieldElement.fractionNavigationOrder = ..." }; var _MathfieldElement = class _MathfieldElement extends HTMLElement { static get formAssociated() { return isElementInternalsSupported(); } /** * Private lifecycle hooks. * If adding a 'boolean' attribute, add its default value to getOptionsFromAttributes * @internal */ static get optionsAttributes() { return { "default-mode": "string", "letter-shape-style": "string", "min-font-scale": "number", "popover-policy": "string", "math-mode-space": "string", "read-only": "boolean", "remove-extraneous-parentheses": "on/off", "smart-fence": "on/off", "smart-mode": "on/off", "smart-superscript": "on/off", "inline-shortcut-timeout": "string", "script-depth": "string", "placeholder": "string", "virtual-keyboard-target-origin": "string", "math-virtual-keyboard-policy": "string" }; } /** * Custom elements lifecycle hooks * @internal */ static get observedAttributes() { return [ ...Object.keys(this.optionsAttributes), "contenteditable", // Global attribute "disabled", // Global attribute "readonly", // A semi-global attribute (not all standard elements support it, but some do) "read-only" // Alternate spelling for `readonly` ]; } /** * A URL fragment pointing to the directory containing the fonts * necessary to render a formula. * * These fonts are available in the `/dist/fonts` directory of the SDK. * * Customize this value to reflect where you have copied these fonts, * or to use the CDN version. * * The default value is `"./fonts"`. Use `null` to prevent * any fonts from being loaded. * * Changing this setting after the mathfield has been created will have * no effect. * * ```javascript * { * // Use the CDN version * fontsDirectory: '' * } * ``` * * ```javascript * { * // Use a directory called "fonts", located next to the * // `mathlive.js` (or `mathlive.mjs`) file. * fontsDirectory: './fonts' * } * ``` * * ```javascript * { * // Use a directory located at the root of your website * fontsDirectory: 'https://example.com/fonts' * } * ``` * */ static get fontsDirectory() { return this._fontsDirectory; } static set fontsDirectory(value) { if (value !== this._fontsDirectory) { this._fontsDirectory = value; reloadFonts(); } } /** @internal */ get fontsDirectory() { throw new Error("Use MathfieldElement.fontsDirectory instead"); } /** @internal */ set fontsDirectory(_value) { throw new Error("Use MathfieldElement.fontsDirectory instead"); } /** * A URL fragment pointing to the directory containing the optional * sounds used to provide feedback while typing. * * Some default sounds are available in the `/dist/sounds` directory of the SDK. * * Use `null` to prevent any sound from being loaded. * @category Virtual Keyboard */ static get soundsDirectory() { return this._soundsDirectory; } static set soundsDirectory(value) { this._soundsDirectory = value; this.audioBuffers = {}; } /** @internal */ get soundsDirectory() { throw new Error("Use MathfieldElement.soundsDirectory instead"); } /** @internal */ set soundsDirectory(_value) { throw new Error("Use MathfieldElement.soundsDirectory instead"); } /** * When a key on the virtual keyboard is pressed, produce a short audio * feedback. * * If the property is set to a `string`, the same sound is played in all * cases. Otherwise, a distinct sound is played: * * - `delete` a sound played when the delete key is pressed * - `return` ... when the return/tab key is pressed * - `spacebar` ... when the spacebar is pressed * - `default` ... when any other key is pressed. This property is required, * the others are optional. If they are missing, this sound is played as * well. * * The value of the properties should be either a string, the name of an * audio file in the `soundsDirectory` directory or `null` to suppress the sound. * @category Virtual Keyboard */ static get keypressSound() { return this._keypressSound; } static set keypressSound(value) { var _a3, _b3, _c2; this.audioBuffers = {}; if (value === null) { this._keypressSound = { spacebar: null, return: null, delete: null, default: null }; } else if (typeof value === "string") { this._keypressSound = { spacebar: value, return: value, delete: value, default: value }; } else if (typeof value === "object" && "default" in value) { this._keypressSound = { spacebar: (_a3 = value.spacebar) != null ? _a3 : value.default, return: (_b3 = value.return) != null ? _b3 : value.default, delete: (_c2 = value.delete) != null ? _c2 : value.default, default: value.default }; } } /** * Sound played to provide feedback when a command has no effect, for example * when pressing the spacebar at the root level. * * The property is either: * - a string, the name of an audio file in the `soundsDirectory` directory * - null to turn off the sound */ static get plonkSound() { return this._plonkSound; } static set plonkSound(value) { this.audioBuffers = {}; this._plonkSound = value; } /** @internal */ static get audioContext() { if (!this._audioContext) this._audioContext = new AudioContext(); return this._audioContext; } // @todo https://github.com/microsoft/TypeScript/issues/30024 /** * Indicates which speech engine to use for speech output. * * Use `local` to use the OS-specific TTS engine. * * Use `amazon` for Amazon Text-to-Speech cloud API. You must include the * AWS API library and configure it with your API key before use. * * **See** * {@link https://cortexjs.io/mathlive/guides/speech/ | Guide: Speech} */ static get speechEngine() { return this._speechEngine; } static set speechEngine(value) { this._speechEngine = value; } /** * Sets the speed of the selected voice. * * One of `x-slow`, `slow`, `medium`, `fast`, `x-fast` or a value as a * percentage. * * Range is `20%` to `200%` For example `200%` to indicate a speaking rate * twice the default rate. */ static get speechEngineRate() { return this._speechEngineRate; } static set speechEngineRate(value) { this._speechEngineRate = value; } /** * Indicates the voice to use with the speech engine. * * This is dependent on the speech engine. For Amazon Polly, see here: * https://docs.aws.amazon.com/polly/latest/dg/voicelist.html * */ static get speechEngineVoice() { return this._speechEngineVoice; } static set speechEngineVoice(value) { this._speechEngineVoice = value; } /** * The markup syntax to use for the output of conversion to spoken text. * * Possible values are `ssml` for the SSML markup or `mac` for the macOS * markup, i.e. `[[ltr]]`. * */ static get textToSpeechMarkup() { return this._textToSpeechMarkup; } static set textToSpeechMarkup(value) { this._textToSpeechMarkup = value; } /** * Specify which set of text to speech rules to use. * * A value of `mathlive` indicates that the simple rules built into MathLive * should be used. * * A value of `sre` indicates that the Speech Rule Engine from Volker Sorge * should be used. * * **(Caution)** SRE is not included or loaded by MathLive. For this option to * work SRE should be loaded separately. * * **See** * {@link https://cortexjs.io/mathlive/guides/speech/ | Guide: Speech} */ static get textToSpeechRules() { return this._textToSpeechRules; } static set textToSpeechRules(value) { this._textToSpeechRules = value; } /** * A set of key/value pairs that can be used to configure the speech rule * engine. * * Which options are available depends on the speech rule engine in use. * There are no options available with MathLive's built-in engine. The * options for the SRE engine are documented * {@link https://github.com/zorkow/speech-rule-engine | here} */ static get textToSpeechRulesOptions() { return this._textToSpeechRulesOptions; } static set textToSpeechRulesOptions(value) { this._textToSpeechRulesOptions = value; } /** * The locale (language + region) to use for string localization. * * If none is provided, the locale of the browser is used. * @category Localization * */ static get locale() { return l10n.locale; } static set locale(value) { if (value === "auto") value = navigator.language.slice(0, 5); l10n.locale = value; } /** @internal */ get locale() { throw new Error("Use MathfieldElement.locale instead"); } /** @internal */ set locale(_value) { throw new Error("Use MathfieldElement.locale instead"); } /** * An object whose keys are a locale string, and whose values are an object of * string identifier to localized string. * * **Example** * ```js example mf.strings = { "fr-CA": { "tooltip.undo": "Annuler", "tooltip.redo": "Refaire", } } ``` * * If the locale is already supported, this will override the existing * strings. If the locale is not supported, it will be added. * * @category Localization */ static get strings() { return l10n.strings; } static set strings(value) { l10n.merge(value); } /** @internal */ get strings() { throw new Error("Use MathfieldElement.strings instead"); } /** @internal */ set strings(_val) { throw new Error("Use MathfieldElement.strings instead"); } /** * The symbol used to separate the integer part from the fractional part of a * number. * * When `","` is used, the corresponding LaTeX string is `{,}`, in order * to ensure proper spacing (otherwise an extra gap is displayed after the * comma). * * This affects: * - what happens when the `,` key is pressed (if `decimalSeparator` is * `","`, the `{,}` LaTeX string is inserted when following some digits) * - the label and behavior of the "." key in the default virtual keyboard * * **Default**: `"."` * @category Localization */ static get decimalSeparator() { return this._decimalSeparator; } static set decimalSeparator(value) { this._decimalSeparator = value; if (this._computeEngine) { this._computeEngine.latexOptions.decimalMarker = this.decimalSeparator === "," ? "{,}" : "."; } } /** @internal */ get decimalSeparator() { throw new Error("Use MathfieldElement.decimalSeparator instead"); } /** @internal */ set decimalSeparator(_val) { throw new Error("Use MathfieldElement.decimalSeparator instead"); } /** * A custom compute engine instance. If none is provided, a default one is * used. If `null` is specified, no compute engine is used. */ static get computeEngine() { var _a3, _b3; if (this._computeEngine === void 0) { const ComputeEngineCtor = (_a3 = window[Symbol.for("io.cortexjs.compute-engine")]) == null ? void 0 : _a3.ComputeEngine; if (!ComputeEngineCtor) return null; this._computeEngine = new ComputeEngineCtor(); if (this._computeEngine && this.decimalSeparator === ",") this._computeEngine.latexOptions.decimalMarker = "{,}"; } return (_b3 = this._computeEngine) != null ? _b3 : null; } static set computeEngine(value) { this._computeEngine = value; } /** @internal */ get computeEngine() { throw new Error("Use MathfieldElement.computeEngine instead"); } /** @internal */ set computeEngine(_val) { throw new Error("Use MathfieldElement.computeEngine instead"); } static get isFunction() { if (typeof this._isFunction !== "function") return () => false; return this._isFunction; } static set isFunction(value) { this._isFunction = value; } static async loadSound(sound) { delete this.audioBuffers[sound]; let soundFile = ""; switch (sound) { case "keypress": soundFile = this._keypressSound.default; break; case "return": soundFile = this._keypressSound.return; break; case "spacebar": soundFile = this._keypressSound.spacebar; break; case "delete": soundFile = this._keypressSound.delete; break; case "plonk": soundFile = this.plonkSound; break; } if (typeof soundFile !== "string") return; soundFile = soundFile.trim(); const soundsDirectory = this.soundsDirectory; if (soundsDirectory === void 0 || soundsDirectory === null || soundsDirectory === "null" || soundFile === "none" || soundFile === "null") return; try { const response = await fetch( await resolveUrl(`${soundsDirectory}/${soundFile}`) ); const arrayBuffer = await response.arrayBuffer(); const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer); this.audioBuffers[sound] = audioBuffer; } catch (e) { } } static async playSound(name) { if (this.audioContext.state === "suspended" || this.audioContext.state === "interrupted") await this.audioContext.resume(); if (!this.audioBuffers[name]) await this.loadSound(name); if (!this.audioBuffers[name]) return; const soundSource = this.audioContext.createBufferSource(); soundSource.buffer = this.audioBuffers[name]; const gainNode = this.audioContext.createGain(); gainNode.gain.value = AUDIO_FEEDBACK_VOLUME; soundSource.connect(gainNode).connect(this.audioContext.destination); soundSource.start(); } /** * To create programmatically a new mathfield use: * ```javascript let mfe = new MathfieldElement(); // Set initial value and options mfe.value = "\\frac{\\sin(x)}{\\cos(x)}"; // Options can be set either as an attribute (for simple options)... mfe.setAttribute("letter-shape-style", "french"); // ... or using properties mfe.letterShapeStyle = "french"; // Attach the element to the DOM document.body.appendChild(mfe); ``` */ constructor(options) { super(); if (options) { const warnings = []; for (const key of Object.keys(options)) { if (DEPRECATED_OPTIONS[key]) { if (DEPRECATED_OPTIONS[key].startsWith("mf.")) { if (!DEPRECATED_OPTIONS[key].startsWith(`mf.${key}`)) { const newName = DEPRECATED_OPTIONS[key].match(/([a-zA-Z]+) =/); warnings.push( `Option \`${key}\` has been renamed \`${newName[1]}\`` ); } else { warnings.push( `Option \`${key}\` cannot be used as a constructor option. Use ${DEPRECATED_OPTIONS[key]}` ); } } else { warnings.push( `Option \`${key}\` cannot be used as a constructor option. Use ${DEPRECATED_OPTIONS[key]}` ); } } } if (warnings.length > 0) { console.group( `%cMathLive 0.98.5: %cInvalid Options`, "color:#12b; font-size: 1.1rem", "color:#db1111; font-size: 1.1rem" ); console.warn( `Some of the options passed to \`new MathfieldElement(...)\` are invalid. See https://cortexjs.io/mathlive/changelog/ for details.` ); for (const warning of warnings) console.warn(warning); console.groupEnd(); } } if (isElementInternalsSupported()) { this._internals = this.attachInternals(); this._internals["role"] = "math"; this._internals.ariaLabel = "math input field"; this._internals.ariaMultiLine = "false"; } this.attachShadow({ mode: "open", delegatesFocus: true }); if (this.shadowRoot && "adoptedStyleSheets" in this.shadowRoot) { this.shadowRoot.adoptedStyleSheets = [ getStylesheet("core"), getStylesheet("mathfield"), getStylesheet("mathfield-element"), getStylesheet("ui"), getStylesheet("menu") ]; this.shadowRoot.appendChild(document.createElement("span")); const slot = document.createElement("slot"); slot.style.display = "none"; this.shadowRoot.appendChild(slot); } else { this.shadowRoot.innerHTML = "'; } if (options) this._setOptions(options); this.shadowRoot.addEventListener("slotchange", () => { var _a3; const slot = this.shadowRoot.querySelector("slot:not([name])"); this.value = (_a3 = slot == null ? void 0 : slot.assignedNodes().map((x) => x.nodeType === 3 ? x.textContent : "").join("").trim()) != null ? _a3 : ""; }); } showMenu(_) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.showMenu(_)) != null ? _b3 : false; } /** @internal */ get mathVirtualKeyboard() { throw new Error( "The `mathVirtualKeyboard` property is not available on the MathfieldElement. Use `window.mathVirtualKeyboard` instead." ); } /** @internal */ onPointerDown() { window.addEventListener( "pointerup", (evt) => { var _a3; if (evt.target === this && !((_a3 = this._mathfield) == null ? void 0 : _a3.disabled)) { this.dispatchEvent( new MouseEvent("click", { altKey: evt.altKey, button: evt.button, buttons: evt.buttons, clientX: evt.clientX, clientY: evt.clientY, ctrlKey: evt.ctrlKey, metaKey: evt.metaKey, movementX: evt.movementX, movementY: evt.movementY, relatedTarget: evt.relatedTarget, screenX: evt.screenX, screenY: evt.screenY, shiftKey: evt.shiftKey }) ); } }, { once: true } ); } /** * @inheritdoc Mathfield.getPromptValue * @category Prompts */ getPromptValue(placeholderId, format) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.getPromptValue(placeholderId, format)) != null ? _b3 : ""; } /** * @inheritdoc Mathfield.setPromptValue * @category Prompts * */ setPromptValue(id, content, insertOptions) { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.setPromptValue(id, content, insertOptions); } /** * Return the selection range for the specified prompt. * * This can be used for example to select the content of the prompt. * * ```js * mf.selection = mf.getPromptRange('my-prompt-id'); * ``` * * @category Prompts * */ getPromptRange(id) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.getPromptRange(id)) != null ? _b3 : null; } /** Return the id of the prompts matching the filter. * @category Prompts */ getPrompts(filter) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.getPrompts(filter)) != null ? _b3 : []; } get form() { var _a3; return (_a3 = this._internals) == null ? void 0 : _a3["form"]; } get name() { var _a3; return (_a3 = this.getAttribute("name")) != null ? _a3 : ""; } get type() { return this.localName; } get mode() { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.model.mode) != null ? _b3 : this.defaultMode === "text" ? "text" : "math"; } set mode(value) { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.switchMode(value); } /** * If the Compute Engine library is available, return a boxed MathJSON expression representing the value of the mathfield. * * To load the Compute Engine library, use: * ```js import 'https://unpkg.com/@cortex-js/compute-engine?module'; ``` * * @category Accessing and changing the content */ get expression() { if (!this._mathfield) return void 0; if (!window[Symbol.for("io.cortexjs.compute-engine")]) { console.error( `MathLive 0.98.5: The CortexJS Compute Engine library is not available. Load the library, for example with: import "https://unpkg.com/@cortex-js/compute-engine?module"` ); return null; } return this._mathfield.expression; } set expression(mathJson) { var _a3, _b3; if (!this._mathfield) return; const latex = (_b3 = (_a3 = _MathfieldElement.computeEngine) == null ? void 0 : _a3.box(mathJson).latex) != null ? _b3 : null; if (latex !== null) this._mathfield.setValue(latex); if (!window[Symbol.for("io.cortexjs.compute-engine")]) { console.error( `MathLive 0.98.5: The CortexJS Compute Engine library is not available. Load the library, for example with: import "https://unpkg.com/@cortex-js/compute-engine?module"` ); } } /** * Return an array of LaTeX syntax errors, if any. * @category Accessing and changing the content */ get errors() { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.errors) != null ? _b3 : []; } _getOptions(keys) { if (this._mathfield) return get(this._mathfield.options, keys); if (!gDeferredState.has(this)) return null; return __spreadValues({}, get( __spreadValues(__spreadValues({}, getDefault()), update(gDeferredState.get(this).options)), keys )); } getOptions(keys) { console.warn( `%cMathLive 0.98.5: %cDeprecated Usage%c \`mf.getOptions()\` is deprecated. Read the property directly on the mathfield instead. See https://cortexjs.io/mathlive/changelog/ for details.`, "color:#12b; font-size: 1.1rem", "color:#db1111; font-size: 1.1rem", "color: inherit, font-size: 1rem" ); if (this._mathfield) return get(this._mathfield.options, keys); if (!gDeferredState.has(this)) return null; return get( __spreadValues(__spreadValues({}, getDefault()), update(gDeferredState.get(this).options)), keys ); } /** @internal */ reflectAttributes() { const defaultOptions = getDefault(); const options = this._getOptions(); Object.keys(_MathfieldElement.optionsAttributes).forEach((x) => { const prop = toCamelCase(x); if (_MathfieldElement.optionsAttributes[x] === "on/off") { if (defaultOptions[prop] !== options[prop]) this.setAttribute(x, options[prop] ? "on" : "off"); else this.removeAttribute(x); } else if (defaultOptions[prop] !== options[prop]) { if (_MathfieldElement.optionsAttributes[x] === "boolean") { if (options[prop]) { this.setAttribute(x, ""); } else { this.removeAttribute(x); } } else { if (typeof options[prop] === "string" || typeof options[prop] === "number") this.setAttribute(x, options[prop].toString()); } } }); } /** * @category Options * @deprecated */ getOption(key) { console.warn( `%cMathLive 0.98.5: %cDeprecated Usage%c \`mf.getOption()\` is deprecated. Read the property directly on the mathfield instead. See https://cortexjs.io/mathlive/changelog/ for details.`, "color:#12b; font-size: 1.1rem", "color:#db1111; font-size: 1.1rem", "color: inherit, font-size: 1rem" ); return this._getOptions([key])[key]; } /** @internal */ _getOption(key) { return this._getOptions([key])[key]; } /** @internal */ _setOptions(options) { if (this._mathfield) this._mathfield.setOptions(options); else if (gDeferredState.has(this)) { const mergedOptions = __spreadValues(__spreadValues({}, gDeferredState.get(this).options), options); gDeferredState.set(this, __spreadProps(__spreadValues({}, gDeferredState.get(this)), { selection: { ranges: mergedOptions.readOnly ? [[0, 0]] : [[0, -1]] }, options: mergedOptions })); } else { gDeferredState.set(this, { value: void 0, selection: { ranges: [[0, 0]] }, options, menuItems: void 0 }); } this.reflectAttributes(); } /** * @category Options * @deprecated */ setOptions(options) { console.group( `%cMathLive 0.98.5: %cDeprecated Usage`, "color:#12b; font-size: 1.1rem", "color:#db1111; font-size: 1.1rem" ); console.warn( ` \`mf.setOptions()\` is deprecated. Set the property directly on the mathfield instead. See https://cortexjs.io/mathlive/changelog/ for details.` ); for (const key of Object.keys(options)) { if (DEPRECATED_OPTIONS[key]) { console.warn( `\`mf.setOptions({${key}:...})\` -> ${DEPRECATED_OPTIONS[key]}` ); } } console.groupEnd(); this._setOptions(options); } /** * @inheritdoc Mathfield.executeCommand */ executeCommand(command) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.executeCommand(command)) != null ? _b3 : false; } getValue(arg1, arg2, arg3) { var _a3, _b3; if (this._mathfield) return this._mathfield.model.getValue(arg1, arg2, arg3); if (gDeferredState.has(this)) { let start; let end; let format = void 0; if (isSelection(arg1)) { [start, end] = arg1.ranges[0]; format = arg2; } else if (isRange(arg1)) { [start, end] = arg1; format = arg2; } else if (isOffset(arg1) && isOffset(arg2)) { start = arg1; end = arg2; format = arg3; } else { start = 0; end = -1; format = arg1; } if ((format === void 0 || format === "latex") && start === 0 && end === -1) return (_b3 = (_a3 = gDeferredState.get(this).value) != null ? _a3 : this.textContent) != null ? _b3 : ""; } return ""; } /** * @inheritdoc Mathfield.setValue * @category Accessing and changing the content */ setValue(value, options) { if (this._mathfield && value !== void 0) { options != null ? options : options = { silenceNotifications: true, mode: "math" }; this._mathfield.setValue(value, options); return; } if (gDeferredState.has(this)) { const options2 = gDeferredState.get(this).options; gDeferredState.set(this, { value, selection: { ranges: [[-1, -1]], direction: "forward" }, options: options2, menuItems: void 0 }); return; } const attrOptions = getOptionsFromAttributes(this); gDeferredState.set(this, { value, selection: { ranges: [[-1, -1]], direction: "forward" }, options: attrOptions, menuItems: void 0 }); } /** * @inheritdoc Mathfield.hasFocus * * @category Focus * */ hasFocus() { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.hasFocus()) != null ? _b3 : false; } /** * Sets the focus to the mathfield (will respond to keyboard input). * * @category Focus * */ focus() { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.focus(); } /** * Remove the focus from the mathfield (will no longer respond to keyboard * input). * * @category Focus * */ blur() { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.blur(); } /** * Select the content of the mathfield. * @category Selection */ select() { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.select(); } /** * @inheritdoc Mathfield.insert * @category Accessing and changing the content */ insert(s, options) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.insert(s, options)) != null ? _b3 : false; } /** * @inheritdoc Mathfield.applyStyle * * @category Accessing and changing the content */ applyStyle(style, options) { var _a3; return (_a3 = this._mathfield) == null ? void 0 : _a3.applyStyle(style, options); } /** * * @category Accessing and changing the content */ queryStyle(style) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.queryStyle(style)) != null ? _b3 : "none"; } /** * @inheritdoc Mathfield.getCaretPoint * @category Selection */ get caretPoint() { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.getCaretPoint()) != null ? _b3 : null; } set caretPoint(point) { var _a3; if (!point) return; (_a3 = this._mathfield) == null ? void 0 : _a3.setCaretPoint(point.x, point.y); } /** * `x` and `y` are in viewport coordinates. * * Return true if the location of the point is a valid caret location. * * See also [[`caretPoint`]] * @category Selection */ setCaretPoint(x, y) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.setCaretPoint(x, y)) != null ? _b3 : false; } /** The offset closest to the location `(x, y)` in viewport coordinate. * * **`bias`**: if `0`, the vertical midline is considered to the left or * right sibling. If `-1`, the left sibling is favored, if `+1`, the right * sibling is favored. * * @category Selection */ offsetFromPoint(x, y, options) { if (!this._mathfield) return -1; return offsetFromPoint(this._mathfield, x, y, options); } /** The bounding rect of the atom at offset * * @category Selection * */ hitboxFromOffset(offset) { if (!this._mathfield) return null; const atom = this._mathfield.model.at(offset); if (!atom) return null; const bounds = getAtomBounds(this._mathfield, atom); if (!bounds) return null; return new DOMRect( bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top ); } /** * Reset the undo stack * * @category Undo */ resetUndo() { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.resetUndo(); } /** * Return whether there are undoable items * @category Undo */ canUndo() { if (!this._mathfield) return false; return this._mathfield.canUndo(); } /** * Return whether there are redoable items * @category Undo */ canRedo() { if (!this._mathfield) return false; return this._mathfield.canRedo(); } /** @internal */ handleEvent(evt) { var _a3, _b3, _c2, _d2; if (Scrim.state !== "closed") return; if (((_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.menu) == null ? void 0 : _b3.state) !== "closed") return; if (evt.type === "pointerdown") this.onPointerDown(); if (evt.type === "focus") (_c2 = this._mathfield) == null ? void 0 : _c2.focus(); if (evt.type === "blur") (_d2 = this._mathfield) == null ? void 0 : _d2.blur(); } /** * Custom elements lifecycle hooks * @internal */ connectedCallback() { var _a3, _b3, _c2, _d2; const computedStyle = window.getComputedStyle(this); const shadowRoot = this.shadowRoot; const userSelect = computedStyle.userSelect !== "none"; if (userSelect) shadowRoot.host.addEventListener("pointerdown", this, true); else { const span = shadowRoot.querySelector("span"); span.style.pointerEvents = "none"; } shadowRoot.host.addEventListener("focus", this, true); shadowRoot.host.addEventListener("blur", this, true); if (!isElementInternalsSupported()) { if (!this.hasAttribute("role")) this.setAttribute("role", "math"); if (!this.hasAttribute("aria-label")) this.setAttribute("aria-label", "math input field"); this.setAttribute("aria-multiline", "false"); } if (userSelect && !this.hasAttribute("contenteditable")) this.setAttribute("contenteditable", "true"); if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "0"); const slot = shadowRoot.querySelector("slot:not([name])"); if (slot) { try { this._style = slot.assignedElements().filter((x) => x.tagName.toLowerCase() === "style").map((x) => x.textContent).join(""); } catch (error) { console.error(error); } } if (this._style) { const styleElement = document.createElement("style"); styleElement.textContent = this._style; shadowRoot.appendChild(styleElement); } let value = ""; if (this.hasAttribute("value")) value = this.getAttribute("value"); else { value = (_a3 = slot == null ? void 0 : slot.assignedNodes().map((x) => x.nodeType === 3 ? x.textContent : "").join("").trim()) != null ? _a3 : ""; } this._mathfield = new _Mathfield( shadowRoot.querySelector(":host > span"), __spreadProps(__spreadValues({}, (_c2 = (_b3 = gDeferredState.get(this)) == null ? void 0 : _b3.options) != null ? _c2 : getOptionsFromAttributes(this)), { eventSink: this, value }) ); if (!gDeferredState.has(this)) { this.upgradeProperty("disabled"); this.upgradeProperty("readonly"); for (const attr of Object.keys(_MathfieldElement.optionsAttributes)) this.upgradeProperty(toCamelCase(attr)); } if (!((_d2 = this._mathfield) == null ? void 0 : _d2.model)) { this._mathfield = null; return; } if (gDeferredState.has(this)) { const mf = this._mathfield; const state = gDeferredState.get(this); const menuItems = state.menuItems; mf.model.deferNotifications({ content: false, selection: false }, () => { const value2 = state.value; if (value2 !== void 0) mf.setValue(value2); mf.model.selection = state.selection; gDeferredState.delete(this); }); if (menuItems) this.menuItems = menuItems; } window.queueMicrotask(() => { if (!this.isConnected) return; this.dispatchEvent( new Event("mount", { cancelable: false, bubbles: true, composed: true }) ); }); void loadFonts(); } /** * Custom elements lifecycle hooks * @internal */ disconnectedCallback() { var _a3, _b3; this.shadowRoot.host.removeEventListener("pointerdown", this, true); if (!this._mathfield) return; window.queueMicrotask( () => ( // Notify listeners that we have been unmounted this.dispatchEvent( new Event("unmount", { cancelable: false, bubbles: true, composed: true }) ) ) ); const options = get( this._mathfield.options, Object.keys(_MathfieldElement.optionsAttributes).map((x) => toCamelCase(x)) ); gDeferredState.set(this, { value: this._mathfield.getValue(), selection: this._mathfield.model.selection, menuItems: (_b3 = (_a3 = this._mathfield.menu) == null ? void 0 : _a3.menuItems) != null ? _b3 : void 0, options }); this._mathfield.dispose(); this._mathfield = null; } /** * Private lifecycle hooks * @internal */ upgradeProperty(prop) { if (this.hasOwnProperty(prop)) { const value = this[prop]; delete this[prop]; if (prop === "readonly" || prop === "read-only") prop = "readOnly"; this[prop] = value; } } /** * Custom elements lifecycle hooks * @internal */ attributeChangedCallback(name, oldValue, newValue) { if (oldValue === newValue) return; const hasValue = newValue !== null; switch (name) { case "contenteditable": requestUpdate(this._mathfield); break; case "disabled": this.disabled = hasValue; break; case "read-only": case "readonly": this.readOnly = hasValue; break; default: } } get readonly() { return this.hasAttribute("readonly") || this.hasAttribute("read-only"); } set readonly(value) { const isReadonly = Boolean(value); if (isReadonly) { this.setAttribute("readonly", ""); if (isElementInternalsSupported()) this._internals.ariaReadOnly = "true"; else this.setAttribute("aria-readonly", "true"); this.setAttribute("aria-readonly", "true"); } else { if (isElementInternalsSupported()) this._internals.ariaReadOnly = "false"; else this.removeAttribute("aria-readonly"); this.removeAttribute("readonly"); this.removeAttribute("read-only"); } this._setOptions({ readOnly: isReadonly }); } get disabled() { return this.hasAttribute("disabled"); } set disabled(value) { var _a3; const isDisabled = Boolean(value); if (isDisabled) this.setAttribute("disabled", ""); else this.removeAttribute("disabled"); if (isElementInternalsSupported()) this._internals.ariaDisabled = isDisabled ? "true" : "false"; else this.setAttribute("aria-disabled", isDisabled ? "true" : "false"); if (isDisabled && ((_a3 = this._mathfield) == null ? void 0 : _a3.hasFocus) && window.mathVirtualKeyboard.visible) this._mathfield.executeCommand("hideVirtualKeyboard"); } /** * The content of the mathfield as a LaTeX expression. * ```js * document.querySelector('mf').value = '\\frac{1}{\\pi}' * ``` * @category Accessing and changing the content */ get value() { return this.getValue(); } /** * @category Accessing and changing the content */ set value(value) { this.setValue(value); } /** @category Customization * @inheritDoc LayoutOptions.defaultMode */ get defaultMode() { return this._getOption("defaultMode"); } set defaultMode(value) { this._setOptions({ defaultMode: value }); } /** @category Customization * @inheritDoc LayoutOptions.macros */ get macros() { return this._getOption("macros"); } set macros(value) { this._setOptions({ macros: value }); } /** @category Customization * @inheritDoc Registers */ get registers() { const that = this; return new Proxy( {}, { get: (_, prop) => { if (typeof prop !== "string") return void 0; return that._getOption("registers")[prop]; }, set(_, prop, value) { if (typeof prop !== "string") return false; that._setOptions({ registers: __spreadProps(__spreadValues({}, that._getOption("registers")), { [prop]: value }) }); return true; } } ); } set registers(value) { this._setOptions({ registers: value }); } /** @category Customization * @inheritDoc LayoutOptions.colorMap */ get colorMap() { return this._getOption("colorMap"); } set colorMap(value) { this._setOptions({ colorMap: value }); } /** @category Customization * @inheritDoc LayoutOptions.backgroundColorMap */ get backgroundColorMap() { return this._getOption("backgroundColorMap"); } set backgroundColorMap(value) { this._setOptions({ backgroundColorMap: value }); } /** @category Customization * @inheritDoc LayoutOptions.letterShapeStyle */ get letterShapeStyle() { return this._getOption("letterShapeStyle"); } set letterShapeStyle(value) { this._setOptions({ letterShapeStyle: value }); } /** @category Customization * @inheritDoc LayoutOptions.minFontScale */ get minFontScale() { return this._getOption("minFontScale"); } set minFontScale(value) { this._setOptions({ minFontScale: value }); } /** @category Customization * @inheritDoc EditingOptions.smartMode */ get smartMode() { return this._getOption("smartMode"); } set smartMode(value) { this._setOptions({ smartMode: value }); } /** @category Customization * @inheritDoc EditingOptions.smartFence */ get smartFence() { return this._getOption("smartFence"); } set smartFence(value) { this._setOptions({ smartFence: value }); } /** @category Customization * @inheritDoc EditingOptions.smartSuperscript */ get smartSuperscript() { return this._getOption("smartSuperscript"); } set smartSuperscript(value) { this._setOptions({ smartSuperscript: value }); } /** @category Customization * @inheritDoc EditingOptions.scriptDepth */ get scriptDepth() { return this._getOption("scriptDepth"); } set scriptDepth(value) { this._setOptions({ scriptDepth: value }); } /** @category Customization * @inheritDoc EditingOptions.removeExtraneousParentheses */ get removeExtraneousParentheses() { return this._getOption("removeExtraneousParentheses"); } set removeExtraneousParentheses(value) { this._setOptions({ removeExtraneousParentheses: value }); } /** @category Customization * @inheritDoc EditingOptions.mathModeSpace */ get mathModeSpace() { return this._getOption("mathModeSpace"); } set mathModeSpace(value) { this._setOptions({ mathModeSpace: value }); } /** @category Customization * @inheritDoc EditingOptions.placeholderSymbol */ get placeholderSymbol() { return this._getOption("placeholderSymbol"); } set placeholderSymbol(value) { this._setOptions({ placeholderSymbol: value }); } /** @category Customization * @inheritDoc EditingOptions.popoverPolicy */ get popoverPolicy() { return this._getOption("popoverPolicy"); } set popoverPolicy(value) { this._setOptions({ popoverPolicy: value }); } /** * @category Customization * @inheritDoc EditingOptions.environmentPopoverPolicy */ get environmentPopoverPolicy() { return this._getOption("environmentPopoverPolicy"); } set environmentPopoverPolicy(value) { this._setOptions({ environmentPopoverPolicy: value }); } /** * @category Customization */ get menuItems() { var _a3, _b3, _c2; if (this._mathfield) return (_a3 = this._mathfield.menu._menuItems.map((x) => x.menuItem)) != null ? _a3 : []; return (_c2 = (_b3 = gDeferredState.get(this)) == null ? void 0 : _b3.menuItems) != null ? _c2 : []; } set menuItems(menuItems) { var _a3; if (this._mathfield) { const btn = (_a3 = this._mathfield.element) == null ? void 0 : _a3.querySelector( "[part=menu-toggle]" ); if (btn) btn.style.display = menuItems.length === 0 ? "none" : ""; this._mathfield.menu.menuItems = menuItems; } if (gDeferredState.has(this)) { gDeferredState.set(this, __spreadProps(__spreadValues({}, gDeferredState.get(this)), { menuItems })); } else { gDeferredState.set(this, { value: void 0, selection: { ranges: [[0, 0]] }, options: getOptionsFromAttributes(this), menuItems }); } } /** * @category Customization * @category Virtual Keyboard * @inheritDoc EditingOptions.mathVirtualKeyboardPolicy */ get mathVirtualKeyboardPolicy() { return this._getOption("mathVirtualKeyboardPolicy"); } set mathVirtualKeyboardPolicy(value) { this._setOptions({ mathVirtualKeyboardPolicy: value }); } /** @category Customization * @inheritDoc EditingOptions.inlineShortcuts */ get inlineShortcuts() { return this._getOption("inlineShortcuts"); } set inlineShortcuts(value) { this._setOptions({ inlineShortcuts: value }); } /** @category Customization * @inheritDoc EditingOptions.inlineShortcutTimeout */ get inlineShortcutTimeout() { return this._getOption("inlineShortcutTimeout"); } set inlineShortcutTimeout(value) { this._setOptions({ inlineShortcutTimeout: value }); } /** @category Customization * @inheritDoc EditingOptions.keybindings */ get keybindings() { return this._getOption("keybindings"); } set keybindings(value) { this._setOptions({ keybindings: value }); } /** @category Hooks * @inheritDoc MathfieldHooks.onInlineShortcut */ get onInlineShortcut() { return this._getOption("onInlineShortcut"); } set onInlineShortcut(value) { this._setOptions({ onInlineShortcut: value }); } /** @category Hooks * @inheritDoc MathfieldHooks.onScrollIntoView */ get onScrollIntoView() { return this._getOption("onScrollIntoView"); } set onScrollIntoView(value) { this._setOptions({ onScrollIntoView: value }); } /** @category Hooks * @inheritDoc MathfieldHooks.onExport */ get onExport() { return this._getOption("onExport"); } set onExport(value) { this._setOptions({ onExport: value }); } get readOnly() { return this._getOption("readOnly"); } set readOnly(value) { this._setOptions({ readOnly: value }); } get isSelectionEditable() { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.isSelectionEditable) != null ? _b3 : false; } /** @category Prompts */ setPromptState(id, state, locked) { var _a3; (_a3 = this._mathfield) == null ? void 0 : _a3.setPromptState(id, state, locked); } getPromptState(id) { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.getPromptState(id)) != null ? _b3 : [void 0, true]; } /** @category Virtual Keyboard */ get virtualKeyboardTargetOrigin() { return this._getOption("virtualKeyboardTargetOrigin"); } set virtualKeyboardTargetOrigin(value) { this._setOptions({ virtualKeyboardTargetOrigin: value }); } /** * An array of ranges representing the selection. * * It is guaranteed there will be at least one element. If a discontinuous * selection is present, the result will include more than one element. * * @category Selection * */ get selection() { if (this._mathfield) return this._mathfield.model.selection; if (gDeferredState.has(this)) return gDeferredState.get(this).selection; return { ranges: [[0, 0]], direction: "forward" }; } /** * * @category Selection */ set selection(sel) { if (typeof sel === "number") sel = { ranges: [[sel, sel]] }; if (this._mathfield) { this._mathfield.model.selection = sel; requestUpdate(this._mathfield); return; } if (gDeferredState.has(this)) { gDeferredState.set(this, __spreadProps(__spreadValues({}, gDeferredState.get(this)), { selection: sel })); return; } gDeferredState.set(this, { value: void 0, selection: sel, options: getOptionsFromAttributes(this), menuItems: void 0 }); } /** * @category Selection */ get selectionIsCollapsed() { const selection = this.selection; return selection.ranges.length === 1 && selection.ranges[0][0] === selection.ranges[0][1]; } /** * The position of the caret/insertion point, from 0 to `lastOffset`. * * @category Selection * */ get position() { if (this._mathfield) return this._mathfield.model.position; if (gDeferredState.has(this)) return gDeferredState.get(this).selection.ranges[0][0]; return 0; } /** * @category Selection */ set position(offset) { if (this._mathfield) { this._mathfield.model.position = offset; requestUpdate(this._mathfield); } if (gDeferredState.has(this)) { gDeferredState.set(this, __spreadProps(__spreadValues({}, gDeferredState.get(this)), { selection: { ranges: [[offset, offset]] } })); return; } gDeferredState.set(this, { value: void 0, selection: { ranges: [[offset, offset]] }, options: getOptionsFromAttributes(this), menuItems: void 0 }); } /** * The depth of an offset represent the depth in the expression tree. * @category Selection */ getOffsetDepth(offset) { var _a3, _b3; if (!this._mathfield) return 0; return ((_b3 = (_a3 = this._mathfield.model.at(offset)) == null ? void 0 : _a3.treeDepth) != null ? _b3 : 2) - 2; } /** * The last valid offset. * @category Selection */ get lastOffset() { var _a3, _b3; return (_b3 = (_a3 = this._mathfield) == null ? void 0 : _a3.model.lastOffset) != null ? _b3 : -1; } }; _MathfieldElement.version = "0.98.5"; /** @internal */ _MathfieldElement._fontsDirectory = "./fonts"; /** @internal */ _MathfieldElement._soundsDirectory = "./sounds"; /** * When a key on the virtual keyboard is pressed, produce a short haptic * feedback, if the device supports it. * @category Virtual Keyboard */ _MathfieldElement.keypressVibration = true; /** @internal */ _MathfieldElement._keypressSound = { spacebar: "keypress-spacebar.wav", return: "keypress-return.wav", delete: "keypress-delete.wav", default: "keypress-standard.wav" }; /** @ignore */ _MathfieldElement._plonkSound = "plonk.wav"; /** @internal */ _MathfieldElement.audioBuffers = {}; /** * Support for [Trusted Type](https://w3c.github.io/webappsec-trusted-types/dist/spec/). * * This optional function will be called before a string of HTML is * injected in the DOM, allowing that string to be sanitized * according to a policy defined by the host. */ _MathfieldElement.createHTML = (x) => x; /** @internal */ _MathfieldElement._speechEngineRate = "100%"; /** @internal */ _MathfieldElement._speechEngineVoice = "Joanna"; /** @internal */ _MathfieldElement._textToSpeechMarkup = ""; /** @internal */ _MathfieldElement._textToSpeechRules = "mathlive"; /** @internal */ _MathfieldElement._textToSpeechRulesOptions = {}; _MathfieldElement.speakHook = defaultSpeakHook; _MathfieldElement.readAloudHook = defaultReadAloudHook; /** @internal */ _MathfieldElement._decimalSeparator = "."; /** * When using the keyboard to navigate a fraction, the order in which the * numerator and navigator are traversed: * - "numerator-denominator": first the elements in the numerator, then * the elements in the denominator. * - "denominator-numerator": first the elements in the denominator, then * the elements in the numerator. In some East-Asian cultures, fractions * are read and written denominator first ("fēnzhī"). With this option * the keyboard navigation follows this convention. * * **Default**: `"numerator-denominator"` * @category Localization */ _MathfieldElement.fractionNavigationOrder = "numerator-denominator"; /** @internal */ _MathfieldElement._isFunction = (command) => { var _a3, _b3; const ce = window.MathfieldElement.computeEngine; return (_b3 = (_a3 = ce == null ? void 0 : ce.parse(command).domain) == null ? void 0 : _a3.isFunction) != null ? _b3 : false; }; var MathfieldElement = _MathfieldElement; function toCamelCase(s) { return s.replace(/[^a-zA-Z\d]+(.)/g, (_m, c) => c.toUpperCase()); } function getOptionsFromAttributes(mfe) { const result = { readOnly: false }; const attribs = MathfieldElement.optionsAttributes; Object.keys(attribs).forEach((x) => { if (mfe.hasAttribute(x)) { const value = mfe.getAttribute(x); if (x === "placeholder") result.contentPlaceholder = value != null ? value : ""; else if (attribs[x] === "boolean") result[toCamelCase(x)] = true; else if (attribs[x] === "on/off") { if (value === "on") result[toCamelCase(x)] = true; else if (value === "off") result[toCamelCase(x)] = false; else result[toCamelCase(x)] = void 0; } else if (attribs[x] === "number") result[toCamelCase(x)] = Number.parseFloat(value != null ? value : "0"); else result[toCamelCase(x)] = value; } }); return result; } function isElementInternalsSupported() { if (!("ElementInternals" in window) || !HTMLElement.prototype.attachInternals) return false; if (!("role" in window.ElementInternals.prototype)) return false; return true; } var mathfield_element_default = MathfieldElement; var _a2, _b2, _c, _d; if (isBrowser() && !((_a2 = window.customElements) == null ? void 0 : _a2.get("math-field"))) { (_c = window[_b2 = Symbol.for("io.cortexjs.mathlive")]) != null ? _c : window[_b2] = {}; const global = window[Symbol.for("io.cortexjs.mathlive")]; global.version = "0.98.5"; window.MathfieldElement = MathfieldElement; (_d = window.customElements) == null ? void 0 : _d.define("math-field", MathfieldElement); } // src/addons/static-render.ts function findEndOfMath(delimiter, text, startIndex) { let index = startIndex; let braceLevel = 0; const delimLength = delimiter.length; while (index < text.length) { const character = text[index]; if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) return index; if (character === "\\") index++; else if (character === "{") braceLevel++; else if (character === "}") braceLevel--; index++; } return -1; } function splitAtDelimiters(startData, leftDelim, rightDelim, mathstyle, format = "latex") { const finalData = []; for (const startDatum of startData) { if (startDatum.type === "text") { const text = startDatum.data; let lookingForLeft = true; let currIndex = 0; let nextIndex; nextIndex = text.indexOf(leftDelim); if (nextIndex !== -1) { currIndex = nextIndex; if (currIndex > 0) { finalData.push({ type: "text", data: text.slice(0, currIndex) }); } lookingForLeft = false; } let done = false; while (!done) { if (lookingForLeft) { nextIndex = text.indexOf(leftDelim, currIndex); if (nextIndex === -1) { done = true; break; } if (currIndex !== nextIndex) { finalData.push({ type: "text", data: text.slice(currIndex, nextIndex) }); } currIndex = nextIndex; } else { nextIndex = findEndOfMath( rightDelim, text, currIndex + leftDelim.length ); if (nextIndex === -1) { done = true; break; } let formula = text.slice(currIndex + leftDelim.length, nextIndex); if (format === "ascii-math") [, formula] = parseMathString(formula, { format: "ascii-math" }); finalData.push({ type: "math", data: formula, rawData: text.slice(currIndex, nextIndex + rightDelim.length), mathstyle }); currIndex = nextIndex + rightDelim.length; } lookingForLeft = !lookingForLeft; } if (currIndex < text.length) { finalData.push({ type: "text", data: text.slice(currIndex) }); } } else finalData.push(startDatum); } return finalData; } function splitWithDelimiters(text, texDelimiters, mathAsciiDelimiters) { let data = [{ type: "text", data: text }]; if (texDelimiters == null ? void 0 : texDelimiters.inline) { texDelimiters.inline.forEach(([openDelim, closeDelim]) => { data = splitAtDelimiters(data, openDelim, closeDelim, "textstyle"); }); } if (texDelimiters == null ? void 0 : texDelimiters.display) { texDelimiters.display.forEach(([openDelim, closeDelim]) => { data = splitAtDelimiters(data, openDelim, closeDelim, "displaystyle"); }); } if (mathAsciiDelimiters == null ? void 0 : mathAsciiDelimiters.inline) { mathAsciiDelimiters.inline.forEach(([openDelim, closeDelim]) => { data = splitAtDelimiters( data, openDelim, closeDelim, "textstyle", "ascii-math" ); }); } if (mathAsciiDelimiters == null ? void 0 : mathAsciiDelimiters.display) { mathAsciiDelimiters.display.forEach(([openDelim, closeDelim]) => { data = splitAtDelimiters( data, openDelim, closeDelim, "displaystyle", "ascii-math" ); }); } return data; } function createMathMLNode(latex, options) { const span = document.createElement("span"); span.setAttribute("translate", "no"); try { const html = "" + options.renderToMathML(latex) + ""; span.innerHTML = window.MathfieldElement.createHTML(html); } catch (error) { console.error( `MathLive 0.98.5: Could not convert "${latex}"' to MathML with ${error}` ); span.textContent = latex; } span.className = "ML__sr-only"; return span; } function createMarkupNode(text, options, mathstyle, createNodeOnFailure) { try { const html = options.renderToMarkup(text, { mathstyle, format: "html" }); const element = document.createElement("span"); element.dataset.latex = text; element.style.display = mathstyle === "displaystyle" ? "flex" : "inline-flex"; element.setAttribute("aria-hidden", "true"); element.setAttribute("translate", "no"); element.innerHTML = window.MathfieldElement.createHTML(html); return element; } catch (error) { console.error("Could not parse'" + text + "' with ", error); if (createNodeOnFailure) return document.createTextNode(text); } return null; } function createAccessibleMarkupPair(latex, mathstyle, options, createNodeOnFailure) { var _a3; const markupNode = createMarkupNode( latex, options, mathstyle ? mathstyle : "textstyle", createNodeOnFailure ); const accessibleContent = (_a3 = options.renderAccessibleContent) != null ? _a3 : ""; if (markupNode && /\b(mathml|speakable-text)\b/i.test(accessibleContent)) { const fragment = document.createElement("span"); if (/\bmathml\b/i.test(accessibleContent) && options.renderToMathML) fragment.append(createMathMLNode(latex, options)); if (/\bspeakable-text\b/i.test(accessibleContent) && options.renderToSpeakableText) { const span = document.createElement("span"); span.setAttribute("translate", "no"); const html = options.renderToSpeakableText(latex); span.innerHTML = window.MathfieldElement.createHTML(html); span.className = "ML__sr-only"; fragment.append(span); } fragment.append(markupNode); return fragment; } return markupNode; } function scanText2(text, options) { var _a3, _b3, _c2; let fragment = null; if (((_a3 = options.TeX) == null ? void 0 : _a3.processEnvironments) && /^\s*\\begin/.test(text)) { fragment = document.createDocumentFragment(); const node = createAccessibleMarkupPair(text, "", options, true); if (node) fragment.appendChild(node); } else { if (!text.trim()) return null; const data = splitWithDelimiters( text, (_b3 = options.TeX) == null ? void 0 : _b3.delimiters, (_c2 = options.asciiMath) == null ? void 0 : _c2.delimiters ); if (data.length === 1 && data[0].type === "text") { return null; } fragment = document.createDocumentFragment(); for (const datum of data) { if (datum.type === "text") fragment.appendChild(document.createTextNode(datum.data)); else { const node = createAccessibleMarkupPair( datum.data, datum.mathstyle === "textstyle" ? "textstyle" : "displaystyle", options, true ); if (node) fragment.appendChild(node); } } } return fragment; } function scanElement(element, options) { var _a3, _b3, _c2, _d2, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p; if (element.childNodes.length === 1 && element.childNodes[0].nodeType === 3) { const text = (_a3 = element.childNodes[0].textContent) != null ? _a3 : ""; if (((_b3 = options.TeX) == null ? void 0 : _b3.processEnvironments) && /^\s*\\begin/.test(text)) { element.textContent = ""; const node = createAccessibleMarkupPair(text, "", options, true); if (node) element.append(node); return; } const data = splitWithDelimiters( text, (_c2 = options.TeX) == null ? void 0 : _c2.delimiters, (_d2 = options.asciiMath) == null ? void 0 : _d2.delimiters ); if (data.length === 1 && data[0].type === "math") { element.textContent = ""; const node = createAccessibleMarkupPair( data[0].data, data[0].mathstyle === "textstyle" ? "textstyle" : "displaystyle", options, true ); if (node) element.append(node); return; } if (data.length === 1 && data[0].type === "text") { return; } } for (let i = element.childNodes.length - 1; i >= 0; i--) { const childNode = element.childNodes[i]; if (childNode.nodeType === 3) { const frag = scanText2((_e = childNode.textContent) != null ? _e : "", options); if (frag) { i += frag.childNodes.length - 1; childNode.replaceWith(frag); } } else if (childNode.nodeType === 1) { const el = childNode; const tag = childNode.nodeName.toLowerCase(); if (tag === "script") { const scriptNode = childNode; let textContent = void 0; if ((_f = options.processScriptTypePattern) == null ? void 0 : _f.test(scriptNode.type)) textContent = (_g = scriptNode.textContent) != null ? _g : ""; else if ((_h = options.processMathJSONScriptTypePattern) == null ? void 0 : _h.test(scriptNode.type)) { try { textContent = (_j = options.serializeToLatex) == null ? void 0 : _j.call( options, JSON.parse((_i = scriptNode.textContent) != null ? _i : "") ); } catch (e) { console.error(e); } } if (textContent) { let style = "textstyle"; for (const l of scriptNode.type.split(";")) { const [key, value] = l.toLowerCase().split("="); if (key.trim() === "mode") style = value.trim() === "display" ? "displaystyle" : "textstyle"; } const span = createAccessibleMarkupPair( textContent, style, options, true ); if (span) scriptNode.parentNode.replaceChild(span, scriptNode); } } else { const shouldRender = ((_l = (_k = options.processClassPattern) == null ? void 0 : _k.test(el.className)) != null ? _l : false) || !(((_n = (_m = options.skipTags) == null ? void 0 : _m.includes(tag)) != null ? _n : false) || ((_p = (_o = options.ignoreClassPattern) == null ? void 0 : _o.test(el.className)) != null ? _p : false)); if (shouldRender) { if (element.childNodes.length === 1 && element.childNodes[0].nodeType === 3) { const formula = element.textContent; element.textContent = ""; const node = createAccessibleMarkupPair( formula != null ? formula : "", "displaystyle", options, true ); if (node) element.append(node); } else scanElement(el, options); } } } } } var DEFAULT_AUTO_RENDER_OPTIONS = { // Name of tags whose content will not be scanned for math delimiters skipTags: [ "math-field", "noscript", "style", "textarea", "pre", "code", "annotation", "annotation-xml" ], //