Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/components/math/katex.tsx
Views: 687
/*1More complicated not-necessarily-synchronous (but actually it is sync) math formula component, which2works fine on the frontend but NOT on a backend with node.js.34This supports rendering using KaTeX.56Right now it is *just* katex, so in fact is synchronous.7*/89import { useEffect, useRef } from "react";10import { math_escape, math_unescape } from "@cocalc/util/markdown-utils";11import { remove_math, replace_math } from "@cocalc/util/mathjax-utils";12import { latexMathToHtmlOrError } from "@cocalc/frontend/misc/math-to-html";13import { replace_all } from "@cocalc/util/misc";14import { replaceMathBracketDelims } from "./util";1516interface Props {17data: string;18inMarkdown?: boolean;19}2021export default function KaTeX({ data, inMarkdown }: Props) {22const ref = useRef<any>(null);23data = replaceMathBracketDelims(data);24const [text, math] = remove_math(math_escape(data));2526useEffect(() => {27// be no-op when math.length == 0.28if (ref.current == null) return;29// There was an error during attemptKatex below, so will fallback to the old30// katex + mathjaxv2 via an old jquery plugin.31ref.current.innerHTML = data;32// @ts-ignore33$(ref.current).katex({ preProcess: true }); // this also calls mathjax as a fallback.34}, [data]);3536if (math.length == 0) {37// no math and the input is text, so return as is. Definitely do NOT wrap in a span.38// See https://github.com/sagemathinc/cocalc/issues/592039return <>{data}</>;40}4142if (inMarkdown) {43const __html = attemptKatex(text, math);44if (__html != null) {45// no error -- using katex is allowed and fully worked.46return <span dangerouslySetInnerHTML={{ __html }}></span>;47}48}4950// didn't end up using katex, so we make a span, which we will fill in via that51// useEffect above.52return <span ref={ref}></span>;53}5455function attemptKatex(text: string, math: string[]): undefined | string {56// Try to use KaTeX directly, with no jquery or useEffect doing anything:57for (let i = 0; i < math.length; i++) {58const { __html, err } = latexMathToHtmlOrError(math[i]);59if (!err) {60math[i] = __html;61} else {62// there was an error63const div = $("<div>")64.text(math[i])65.css("color", "red")66.attr("title", `${err}`);67const htmlString = div.prop("outerHTML");68math[i] = htmlString;69}70}71// Substitute processed math back in.72return replace_all(math_unescape(replace_math(text, math)), "\\$", "$");73}747576