import React from 'react';
import katex from 'katex';
import 'katex/dist/katex.min.css';
type KaTeXProps = {
/** Raw LaTeX source (without `$`/`$$` delimiters). */
latex: string;
/** Render as block (display) math when true, inline otherwise. */
displayMode?: boolean;
};
/**
* Lazily-loaded KaTeX renderer.
*
* This module statically imports `katex` and its stylesheet, so both only enter
* the bundle via the dynamic `import()` of this file (see the `lazy()` wrapper
* in `react-custom-html-parser.tsx`). They are therefore NOT part of the eager
* import graph.
*
* We render with `throwOnError: false`, so KaTeX itself renders a parse error
* inline (in its error colour) rather than throwing. The HTML returned by
* `renderToString` is produced by our own trusted call from a fixed options
* object — it is safe to inject via `dangerouslySetInnerHTML`.
*
* `maxSize`/`maxExpand` cap how large a single glyph (`\\rule`, etc.) or macro
* expansion remote LaTeX can request, and `trust: false` disables commands
* that can embed arbitrary HTML/URLs (e.g. `\\includegraphics`, `\\href`) —
* without these a hostile `$$...$$` from a remote message can DoS or (via
* `trust`) inject unsafe links (Gitea #65). `strict: 'ignore'` keeps unknown-
* but-harmless LaTeX from spamming the console as before. Extremely long
* source is rendered as plain text rather than handed to KaTeX at all.
*/
const MAX_LATEX_LENGTH = 5000;
export default function KaTeX({ latex, displayMode = false }: KaTeXProps) {
if (latex.length > MAX_LATEX_LENGTH) {
const Plain = displayMode ? 'div' : 'span';
return {latex};
}
const html = katex.renderToString(latex, {
displayMode,
throwOnError: false,
output: 'htmlAndMathml',
maxSize: 10,
maxExpand: 100,
trust: false,
strict: 'ignore',
});
const Wrapper = displayMode ? 'div' : 'span';
return (
);
}