From abb7cc02e90f1c36e24088e868e63d5f6ba9f801 Mon Sep 17 00:00:00 2001 From: mamei16 Date: Wed, 4 Mar 2026 21:44:19 +0100 Subject: [PATCH] Re-introduce inline LaTeX rendering with more robust exception handling (#7402) --- js/katex/auto-render.js | 184 ++++++++++++++++++++++++++++++++++++ js/katex/auto-render.min.js | 1 - js/main.js | 1 + server.py | 2 +- 4 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 js/katex/auto-render.js delete mode 100644 js/katex/auto-render.min.js diff --git a/js/katex/auto-render.js b/js/katex/auto-render.js new file mode 100644 index 00000000..c9385c56 --- /dev/null +++ b/js/katex/auto-render.js @@ -0,0 +1,184 @@ +! function(e, t) { + "object" == typeof exports && "object" == typeof module ? module.exports = t(require("katex")) : "function" == typeof define && define.amd ? define(["katex"], t) : "object" == typeof exports ? exports.renderMathInElement = t(require("katex")) : e.renderMathInElement = t(e.katex) +}("undefined" != typeof self ? self : this, (function(e) { + return function() { + "use strict"; + var t = { + 771: function(t) { + t.exports = e + } + }, + n = {}; + + function r(e) { + var o = n[e]; + if (void 0 !== o) return o.exports; + var i = n[e] = { + exports: {} + }; + return t[e](i, i.exports, r), i.exports + } + r.n = function(e) { + var t = e && e.__esModule ? function() { + return e.default + } : function() { + return e + }; + return r.d(t, { + a: t + }), t + }, r.d = function(e, t) { + for (var n in t) r.o(t, n) && !r.o(e, n) && Object.defineProperty(e, n, { + enumerable: !0, + get: t[n] + }) + }, r.o = function(e, t) { + return Object.prototype.hasOwnProperty.call(e, t) + }; + var o = {}; + return function() { + r.d(o, { + default: function() { + return d + } + }); + var e = r(771), + t = r.n(e); + const n = function(e, t, n) { + let r = n, + o = 0; + const i = e.length; + for (; r < t.length;) { + const n = t[r]; + if (o <= 0 && t.slice(r, r + i) === e) return r; + "\\" === n ? r++ : "{" === n ? o++ : "}" === n && o--, r++ + } + return -1 + }, + i = /^\\begin{/; + var a = function(e, t) { + let r; + const o = [], + a = new RegExp("(" + t.map((e => e.left.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"))).join("|") + ")"); + for (; r = e.search(a), -1 !== r;) { + const charAfterOpen = e[r + 1]; + if (e[r] == "$" && charAfterOpen != "$") { + const closeDollarIndex = e.indexOf('$', r + 1); + if (closeDollarIndex != -1) { + const charBeforeOpen = r > 0 ? e[r - 1] : ''; + const charBeforeClose = r + 1 < closeDollarIndex ? e[closeDollarIndex - 1] : ''; + const charBeforeBeforeClose = r + 1 < closeDollarIndex ? e[closeDollarIndex - 2] : ''; + const charAfterClose = closeDollarIndex + 1 < e.length ? e[closeDollarIndex + 1] : ''; + if ((/[A-Za-z0-9_$-]/.test(charBeforeOpen)) || ((' ' == charBeforeClose) || + /[0-9]/.test(charAfterOpen) && + (/[A-Za-z0-9]/.test(charAfterClose) + || '-' == charBeforeClose))) { + o.push({ + type: "text", + data: e.slice(0, r + 1), + }); + e = e.slice(r + 1); // now text starts after delimiter + continue; + } + } + } + r > 0 && (o.push({ + type: "text", + data: e.slice(0, r) + }), e = e.slice(r)); + const a = t.findIndex((t => e.startsWith(t.left))); + if (r = n(t[a].right, e, t[a].left.length), -1 === r) break; + const l = e.slice(0, r + t[a].right.length), + s = i.test(l) ? l : e.slice(t[a].left.length, r); + o.push({ + type: "math", + data: s, + rawData: l, + display: t[a].display + }), e = e.slice(r + t[a].right.length) + } + return "" !== e && o.push({ + type: "text", + data: e + }), o + }; + const l = function(e, n) { + const r = a(e, n.delimiters); + if (1 === r.length && "text" === r[0].type) return null; + const o = document.createDocumentFragment(); + for (let e = 0; e < r.length; e++) + if ("text" === r[e].type) o.appendChild(document.createTextNode(r[e].data)); + else { + const i = document.createElement("span"); + let a = r[e].data; + n.displayMode = r[e].display; + try { + n.preProcess && (a = n.preProcess(a)), t().render(a, i, n) + } catch (i) { + if (!(i instanceof t().ParseError)) throw i; + n.errorCallback("KaTeX auto-render: Failed to parse `" + r[e].data + "` with ", i), o.appendChild(document.createTextNode(r[e].rawData)); + continue + } + o.appendChild(i) + } + return o + }, + s = function(e, t) { + for (let n = 0; n < e.childNodes.length; n++) { + const r = e.childNodes[n]; + if (3 === r.nodeType) { + let o = r.textContent, + i = r.nextSibling, + a = 0; + for (; i && i.nodeType === Node.TEXT_NODE;) o += i.textContent, i = i.nextSibling, a++; + const s = l(o, t); + if (s) { + for (let e = 0; e < a; e++) r.nextSibling.remove(); + n += s.childNodes.length - 1, e.replaceChild(s, r) + } else n += a + } else if (1 === r.nodeType) { + const e = " " + r.className + " "; - 1 === t.ignoredTags.indexOf(r.nodeName.toLowerCase()) && t.ignoredClasses.every((t => -1 === e.indexOf(" " + t + " "))) && s(r, t) + } + } + }; + var d = function(e, t) { + if (!e) throw new Error("No element provided to render"); + const n = {}; + for (const e in t) t.hasOwnProperty(e) && (n[e] = t[e]); + n.delimiters = n.delimiters || [{ + left: "$$", + right: "$$", + display: !0 + }, { + left: "\\(", + right: "\\)", + display: !1 + }, { + left: "\\begin{equation}", + right: "\\end{equation}", + display: !0 + }, { + left: "\\begin{align}", + right: "\\end{align}", + display: !0 + }, { + left: "\\begin{alignat}", + right: "\\end{alignat}", + display: !0 + }, { + left: "\\begin{gather}", + right: "\\end{gather}", + display: !0 + }, { + left: "\\begin{CD}", + right: "\\end{CD}", + display: !0 + }, { + left: "\\[", + right: "\\]", + display: !0 + }], n.ignoredTags = n.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"], n.ignoredClasses = n.ignoredClasses || [], n.errorCallback = n.errorCallback || console.error, n.macros = n.macros || {}, s(e, n) + } + }(), o = o.default + }() +})); diff --git a/js/katex/auto-render.min.js b/js/katex/auto-render.min.js deleted file mode 100644 index 46d62af2..00000000 --- a/js/katex/auto-render.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};return function(){r.d(o,{default:function(){return d}});var e=r(771),t=r.n(e);const n=function(e,t,n){let r=n,o=0;const i=e.length;for(;re.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;r=e.search(a),-1!==r;){r>0&&(o.push({type:"text",data:e.slice(0,r)}),e=e.slice(r));const a=t.findIndex((t=>e.startsWith(t.left)));if(r=n(t[a].right,e,t[a].left.length),-1===r)break;const l=e.slice(0,r+t[a].right.length),s=i.test(l)?l:e.slice(t[a].left.length,r);o.push({type:"math",data:s,rawData:l,display:t[a].display}),e=e.slice(r+t[a].right.length)}return""!==e&&o.push({type:"text",data:e}),o};const l=function(e,n){const r=a(e,n.delimiters);if(1===r.length&&"text"===r[0].type)return null;const o=document.createDocumentFragment();for(let e=0;e-1===e.indexOf(" "+t+" ")))&&s(r,t)}}};var d=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},s(e,n)}}(),o=o.default}()})); \ No newline at end of file diff --git a/js/main.js b/js/main.js index 67f60279..1317e9e7 100644 --- a/js/main.js +++ b/js/main.js @@ -274,6 +274,7 @@ function doSyntaxHighlighting() { renderMathInElement(container, { delimiters: [ { left: "$$", right: "$$", display: true }, + { left: "$", right: "$", display: false }, { left: "\\(", right: "\\)", display: false }, { left: "\\[", right: "\\]", display: true }, ], diff --git a/server.py b/server.py index 304a0478..ccfda5ac 100644 --- a/server.py +++ b/server.py @@ -147,7 +147,7 @@ def create_interface(): '', '', '', - '', + '', '', '', '',