diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index cf14c783d9..3c60aed206 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -15,6 +15,7 @@ import attributes from "../../services/attributes"; import froca from "../../services/froca"; import keyboard_actions from "../../services/keyboard_actions"; import { ViewScope } from "../../services/link"; +import math from "../../services/math"; import options, { type OptionValue } from "../../services/options"; import protected_session_holder from "../../services/protected_session_holder"; import server from "../../services/server"; @@ -1435,3 +1436,25 @@ export function useColorScheme() { return prefersDark ? "dark" : "light"; } + +/** + * Renders math equations within elements that have the `.math-tex` class. + * Used by sidebar widgets like Table of Contents and Highlights list to display math content. + * + * @param containerRef - Ref to the container element that may contain math elements + * @param deps - Dependencies that trigger re-rendering (e.g., text content) + */ +export function useMathRendering(containerRef: RefObject, deps: unknown[]) { + useEffect(() => { + if (!containerRef.current) return; + const mathElements = containerRef.current.querySelectorAll(".math-tex"); + + for (const mathEl of mathElements) { + try { + math.render(mathEl.textContent || "", mathEl as HTMLElement); + } catch (e) { + console.warn("Failed to render math:", e); + } + } + }, deps); // eslint-disable-line react-hooks/exhaustive-deps +} diff --git a/apps/client/src/widgets/sidebar/HighlightsList.tsx b/apps/client/src/widgets/sidebar/HighlightsList.tsx index d0c447c283..1cd874a457 100644 --- a/apps/client/src/widgets/sidebar/HighlightsList.tsx +++ b/apps/client/src/widgets/sidebar/HighlightsList.tsx @@ -3,9 +3,8 @@ import { createPortal } from "preact/compat"; import { useCallback, useEffect, useRef, useState } from "preact/hooks"; import { t } from "../../services/i18n"; -import math from "../../services/math"; import { randomString } from "../../services/utils"; -import { useActiveNoteContext, useContentElement, useIsNoteReadOnly, useNoteProperty, useTextEditor, useTriliumOptionJson } from "../react/hooks"; +import { useActiveNoteContext, useContentElement, useIsNoteReadOnly, useMathRendering, useNoteProperty, useTextEditor, useTriliumOptionJson } from "../react/hooks"; import Modal from "../react/Modal"; import RawHtml from "../react/RawHtml"; import { HighlightsListOptions } from "../type_widgets/options/text_notes"; @@ -111,19 +110,7 @@ function HighlightItem({ highlight, onClick }: { }) { const contentRef = useRef(null); - // Render math equations after component mounts/updates - useEffect(() => { - if (!contentRef.current) return; - const mathElements = contentRef.current.querySelectorAll(".math-tex"); - - for (const mathEl of mathElements ?? []) { - try { - math.render(mathEl.textContent || "", mathEl as HTMLElement); - } catch (e) { - console.warn("Failed to render math in highlights:", e); - } - } - }, [highlight.text]); + useMathRendering(contentRef, [highlight.text]); return (
  • diff --git a/apps/client/src/widgets/sidebar/TableOfContents.tsx b/apps/client/src/widgets/sidebar/TableOfContents.tsx index eef19100eb..03c62e1ad4 100644 --- a/apps/client/src/widgets/sidebar/TableOfContents.tsx +++ b/apps/client/src/widgets/sidebar/TableOfContents.tsx @@ -5,9 +5,8 @@ import clsx from "clsx"; import { useCallback, useEffect, useRef, useState } from "preact/hooks"; import { t } from "../../services/i18n"; -import math from "../../services/math"; import { randomString } from "../../services/utils"; -import { useActiveNoteContext, useContentElement, useGetContextData, useIsNoteReadOnly, useNoteProperty, useTextEditor } from "../react/hooks"; +import { useActiveNoteContext, useContentElement, useGetContextData, useIsNoteReadOnly, useMathRendering, useNoteProperty, useTextEditor } from "../react/hooks"; import Icon from "../react/Icon"; import RawHtml from "../react/RawHtml"; import RightPanelWidget from "./RightPanelWidget"; @@ -84,19 +83,7 @@ function TableOfContentsHeading({ heading, scrollToHeading, activeHeadingId }: { const isActive = heading.id === activeHeadingId; const contentRef = useRef(null); - // Render math equations after component mounts/updates - useEffect(() => { - if (!contentRef.current) return; - const mathElements = contentRef.current.querySelectorAll(".math-tex"); - - for (const mathEl of mathElements ?? []) { - try { - math.render(mathEl.textContent || "", mathEl as HTMLElement); - } catch (e) { - console.warn("Failed to render math in TOC:", e); - } - } - }, [heading.text]); + useMathRendering(contentRef, [heading.text]); return ( <>