{"version":3,"file":"discourse-math.js","names":["define","_exports","_loadScript","_pluginApi","async","katex","elem","mathElems","querySelectorAll","length","default","css","e","console","error","ensureKaTeX","katexOpts","trust","context","includes","command","macros","displayMode","forEach","mathElem","tagName","dataset","appliedKatex","classList","contains","displayClass","text","textContent","add","window","render","decorate","Object","defineProperty","value","name","initialize","container","siteSettings","lookup","discourse_math_enabled","discourse_math_provider","withPluginApi","api","decorateCookedElement","id","decorateChatMessage","element","initializeMath","_runloop","_getUrl","initializedMathJax","ensureMathJax","opts","extensions","enable_accessibility","push","settings","jax","TeX","showProcessingMessages","messageStyle","root","getURLWithCDN","zoom_on_hover","menuSettings","zoom","MathEvents","hover","MathJax","initMathJax","mathjax","enable_asciimath","isPreview","then","appliedMathjax","tag","type","mathScript","document","createElement","innerText","mathWrapper","split","style","display","appendChild","after","later","this","Hub","Queue","parentElement","offsetParent","Typeset","discourse_math_opts","discourse_math_zoom_on_hover","discourse_math_enable_accessibility","discourse_math_enable_asciimath","discourseMathOptions","setup","helper","markdownIt","registerOptions","features","math","asciimath","registerPlugin","md","options","discourse","inline","ruler","asciiMath","inlineMath","block","blockMath","alt","additionalPunctuation","isSafeBoundary","character_code","delimiter_code","utils","isWhiteSpace","isMdAsciiPunct","isPunctChar","math_input","state","silent","found","pos","posMax","src","charCodeAt","i","next","data","slice","token","escaped","escapeHtml","math_class","content","isBlockMarker","start","max","isSpace","startLine","endLine","bMarks","tShift","eMarks","nextLine","closed","endContent","line"],"sources":["discourse/plugins/discourse-math/initializers/discourse-math-katex.js","discourse/plugins/discourse-math/initializers/discourse-math-mathjax.js","discourse/plugins/discourse-math/lib/discourse-markdown/discourse-math.js"],"sourcesContent":["define(\"discourse/plugins/discourse-math/initializers/discourse-math-katex\", [\"exports\", \"discourse/lib/load-script\", \"discourse/lib/plugin-api\"], function (_exports, _loadScript, _pluginApi) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n async function ensureKaTeX() {\n try {\n await (0, _loadScript.default)(\"/plugins/discourse-math/katex/katex.min.js\");\n await (0, _loadScript.default)(\"/plugins/discourse-math/katex/katex.min.css\", {\n css: true\n });\n await (0, _loadScript.default)(\"/plugins/discourse-math/katex/mhchem.min.js\");\n await (0, _loadScript.default)(\"/plugins/discourse-math/katex/copy-tex.min.js\");\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\"Failed to load KaTeX dependencies.\", e);\n }\n }\n function decorate(elem, katexOpts) {\n katexOpts[\"displayMode\"] = elem.tagName === \"DIV\";\n if (elem.dataset.appliedKatex) {\n return;\n }\n elem.dataset.appliedKatex = true;\n if (!elem.classList.contains(\"math\")) {\n return;\n }\n const tag = elem.tagName === \"DIV\" ? \"div\" : \"span\";\n const displayClass = tag === \"div\" ? \"block-math\" : \"inline-math\";\n const text = elem.textContent;\n elem.classList.add(\"math-container\", displayClass, \"katex-math\");\n elem.textContent = \"\";\n window.katex.render(text, elem, katexOpts);\n }\n async function katex(elem) {\n if (!elem) {\n return;\n }\n const mathElems = elem.querySelectorAll(\".math\");\n if (!mathElems.length > 0) {\n return;\n }\n await ensureKaTeX();\n\n // enable persistent macros with are disabled by default: https://katex.org/docs/api.html#persistent-macros\n // also enable equation labelling and referencing which are disabled by default\n // both of these are enabled in mathjax by default, so now the katex implementation is (more) mathjax compatible\n const katexOpts = {\n trust: context => [\"\\\\htmlId\", \"\\\\href\"].includes(context.command),\n macros: {\n \"\\\\eqref\": \"\\\\href{###1}{(\\\\text{#1})}\",\n \"\\\\ref\": \"\\\\href{###1}{\\\\text{#1}}\",\n \"\\\\label\": \"\\\\htmlId{#1}{}\"\n },\n displayMode: false\n };\n mathElems.forEach(mathElem => decorate(mathElem, katexOpts));\n }\n function initializeMath(api) {\n api.decorateCookedElement(function (elem) {\n katex(elem);\n }, {\n id: \"katex\"\n });\n if (api.decorateChatMessage) {\n api.decorateChatMessage(element => {\n katex(element);\n }, {\n id: \"katex-chat\"\n });\n }\n }\n var _default = _exports.default = {\n name: \"apply-math-katex\",\n initialize(container) {\n const siteSettings = container.lookup(\"service:site-settings\");\n if (siteSettings.discourse_math_enabled && siteSettings.discourse_math_provider === \"katex\") {\n (0, _pluginApi.withPluginApi)(\"0.5\", function (api) {\n initializeMath(api);\n });\n }\n }\n };\n});","define(\"discourse/plugins/discourse-math/initializers/discourse-math-mathjax\", [\"exports\", \"@ember/runloop\", \"discourse/lib/get-url\", \"discourse/lib/load-script\", \"discourse/lib/plugin-api\"], function (_exports, _runloop, _getUrl, _loadScript, _pluginApi) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n let initializedMathJax = false;\n function initMathJax(opts) {\n if (initializedMathJax) {\n return;\n }\n const extensions = [\"toMathML.js\", \"Safe.js\"];\n if (opts.enable_accessibility) {\n extensions.push(\"[a11y]/accessibility-menu.js\");\n }\n let settings = {\n jax: [\"input/TeX\", \"input/AsciiMath\", \"input/MathML\", \"output/CommonHTML\"],\n TeX: {\n extensions: [\"AMSmath.js\", \"AMSsymbols.js\", \"autoload-all.js\"]\n },\n extensions,\n showProcessingMessages: false,\n messageStyle: \"none\",\n root: (0, _getUrl.getURLWithCDN)(\"/plugins/discourse-math/mathjax\")\n };\n if (opts.zoom_on_hover) {\n settings.menuSettings = {\n zoom: \"Hover\"\n };\n settings.MathEvents = {\n hover: 750\n };\n }\n window.MathJax = settings;\n initializedMathJax = true;\n }\n function ensureMathJax(opts) {\n initMathJax(opts);\n return (0, _loadScript.default)(\"/plugins/discourse-math/mathjax/MathJax.2.7.5.js\");\n }\n function decorate(elem, isPreview) {\n if (elem.dataset.appliedMathjax) {\n return;\n }\n elem.dataset.appliedMathjax = true;\n let tag, classList, type;\n if (elem.classList.contains(\"math\")) {\n tag = elem.tagName === \"DIV\" ? \"div\" : \"span\";\n const display = tag === \"div\" ? \"; mode=display\" : \"\";\n const displayClass = tag === \"div\" ? \"block-math\" : \"inline-math\";\n type = `math/tex${display}`;\n classList = `math-container ${displayClass} mathjax-math`;\n } else if (elem.classList.contains(\"asciimath\")) {\n tag = \"span\";\n classList = \"math-container inline-math ascii-math\";\n type = \"math/asciimath\";\n }\n const mathScript = document.createElement(\"script\");\n mathScript.type = type;\n mathScript.innerText = elem.innerText;\n const mathWrapper = document.createElement(tag);\n mathWrapper.classList.add(classList.split(\" \"));\n mathWrapper.style.display = \"none\";\n mathWrapper.appendChild(mathScript);\n elem.after(mathWrapper);\n (0, _runloop.later)(this, () => {\n window.MathJax.Hub.Queue(() => {\n // don't bother processing previews removed from DOM\n if (elem?.parentElement?.offsetParent !== null) {\n window.MathJax.Hub.Typeset(mathScript, () => {\n elem.style.display = \"none\";\n mathWrapper.style.display = null;\n });\n }\n });\n }, isPreview ? 200 : 0);\n }\n function mathjax(elem, opts) {\n if (!elem) {\n return;\n }\n let mathElems;\n if (opts.enable_asciimath) {\n mathElems = elem.querySelectorAll(\".math, .asciimath\");\n } else {\n mathElems = elem.querySelectorAll(\".math\");\n }\n if (mathElems.length > 0) {\n const isPreview = elem.classList.contains(\"d-editor-preview\");\n ensureMathJax(opts).then(() => {\n mathElems.forEach(mathElem => decorate(mathElem, isPreview));\n });\n }\n }\n function initializeMath(api, discourseMathOptions) {\n api.decorateCookedElement(element => {\n mathjax(element, discourseMathOptions);\n }, {\n id: \"mathjax\"\n });\n if (api.decorateChatMessage) {\n api.decorateChatMessage(element => {\n mathjax(element, discourseMathOptions);\n }, {\n id: \"mathjax-chat\"\n });\n }\n }\n var _default = _exports.default = {\n name: \"apply-math-mathjax\",\n initialize(container) {\n const siteSettings = container.lookup(\"service:site-settings\");\n let discourse_math_opts = {\n zoom_on_hover: siteSettings.discourse_math_zoom_on_hover,\n enable_accessibility: siteSettings.discourse_math_enable_accessibility,\n enable_asciimath: siteSettings.discourse_math_enable_asciimath\n };\n if (siteSettings.discourse_math_enabled && siteSettings.discourse_math_provider === \"mathjax\") {\n (0, _pluginApi.withPluginApi)(\"0.5\", function (api) {\n initializeMath(api, discourse_math_opts);\n });\n }\n }\n };\n});","define(\"discourse/plugins/discourse-math/lib/discourse-markdown/discourse-math\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.setup = setup;\n // inspired by https://github.com/classeur/markdown-it-mathjax/blob/master/markdown-it-mathjax.js\n //\n //\n //\n\n const additionalPunctuation = [\n // Chinese and Japanese punctuation\n 0x3001,\n // 、\n 0x3002,\n // 。\n\n // Full-width punctuation used in East Asian languages\n 0xff0c,\n // ,\n 0xff1a,\n // :\n 0xff1b,\n // ;\n 0xff0e,\n // .\n 0xff1f,\n // ?\n 0xff01,\n // !\n\n // Arabic punctuation\n 0x060c,\n // ،\n 0x061b,\n // ؛\n 0x061f,\n // ؟\n\n // Thai punctuation\n 0x0e2f // ฯ\n ];\n function isSafeBoundary(character_code, delimiter_code, md) {\n if (character_code === delimiter_code) {\n return false;\n }\n if (md.utils.isWhiteSpace(character_code)) {\n return true;\n }\n if (md.utils.isMdAsciiPunct(character_code)) {\n return true;\n }\n if (md.utils.isPunctChar(character_code)) {\n return true;\n }\n if (additionalPunctuation.includes(character_code)) {\n return true;\n }\n return false;\n }\n function math_input(state, silent, delimiter_code) {\n let pos = state.pos,\n posMax = state.posMax;\n if (silent || state.src.charCodeAt(pos) !== delimiter_code || posMax < pos + 2) {\n return false;\n }\n\n // too short\n if (state.src.charCodeAt(pos + 1) === delimiter_code) {\n return false;\n }\n if (pos > 0) {\n let prev = state.src.charCodeAt(pos - 1);\n if (!isSafeBoundary(prev, delimiter_code, state.md)) {\n return false;\n }\n }\n let found;\n for (let i = pos + 1; i < posMax; i++) {\n let code = state.src.charCodeAt(i);\n if (code === delimiter_code && state.src.charCodeAt(i - 1) !== 92 /* \\ */) {\n found = i;\n break;\n }\n }\n if (!found) {\n return false;\n }\n if (found + 1 <= posMax) {\n let next = state.src.charCodeAt(found + 1);\n if (next && !isSafeBoundary(next, delimiter_code, state.md)) {\n return false;\n }\n }\n let data = state.src.slice(pos + 1, found);\n let token = state.push(\"html_raw\", \"\", 0);\n const escaped = state.md.utils.escapeHtml(data);\n let math_class = delimiter_code === 36 ? \"'math'\" : \"'asciimath'\";\n token.content = `${escaped}`;\n state.pos = found + 1;\n return true;\n }\n function inlineMath(state, silent) {\n return math_input(state, silent, 36 /* $ */);\n }\n function asciiMath(state, silent) {\n return math_input(state, silent, 37 /* % */);\n }\n function isBlockMarker(state, start, max, md) {\n if (state.src.charCodeAt(start) !== 36 /* $ */) {\n return false;\n }\n start++;\n if (state.src.charCodeAt(start) !== 36 /* $ */) {\n return false;\n }\n start++;\n\n // ensure we only have newlines after our $$\n for (let i = start; i < max; i++) {\n if (!md.utils.isSpace(state.src.charCodeAt(i))) {\n return false;\n }\n }\n return true;\n }\n function blockMath(state, startLine, endLine, silent) {\n let start = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n if (!isBlockMarker(state, start, max, state.md)) {\n return false;\n }\n if (silent) {\n return true;\n }\n let nextLine = startLine;\n let closed = false;\n for (;;) {\n nextLine++;\n\n // unclosed $$ is considered math\n if (nextLine >= endLine) {\n break;\n }\n if (isBlockMarker(state, state.bMarks[nextLine] + state.tShift[nextLine], state.eMarks[nextLine], state.md)) {\n closed = true;\n break;\n }\n }\n let token = state.push(\"html_raw\", \"\", 0);\n let endContent = closed ? state.eMarks[nextLine - 1] : state.eMarks[nextLine];\n let content = state.src.slice(state.bMarks[startLine + 1] + state.tShift[startLine + 1], endContent);\n const escaped = state.md.utils.escapeHtml(content);\n token.content = `