Re-introduce inline LaTeX rendering with more robust exception handling (#7402)

This commit is contained in:
mamei16 2026-03-04 21:44:19 +01:00 committed by GitHub
parent 68109bc5da
commit abb7cc02e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 186 additions and 2 deletions

184
js/katex/auto-render.js Normal file
View file

@ -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
}()
}));

View file

@ -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(;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;){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}()}));

View file

@ -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 },
],

View file

@ -147,7 +147,7 @@ def create_interface():
'<link rel="preload" href="file/css/NotoSans/NotoSans-MediumItalic.woff2" as="font" type="font/woff2" crossorigin>',
'<link rel="preload" href="file/css/NotoSans/NotoSans-Bold.woff2" as="font" type="font/woff2" crossorigin>',
'<script src="file/js/katex/katex.min.js"></script>',
'<script src="file/js/katex/auto-render.min.js"></script>',
'<script src="file/js/katex/auto-render.js"></script>',
'<script src="file/js/highlightjs/highlight.min.js"></script>',
'<script src="file/js/highlightjs/highlightjs-copy.min.js"></script>',
'<script src="file/js/morphdom/morphdom-umd.min.js"></script>',