UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

134 lines (131 loc) 3.97 kB
'use client'; import { useEffect, useMemo, useState } from "react"; import { useTheme } from "antd-style"; import { Md5 } from "ts-md5"; //#region src/hooks/useMermaid.ts const MD5_LENGTH_THRESHOLD = 1e4; const mermaidCache = /* @__PURE__ */ new Map(); const MAX_CACHE_SIZE = 500; const cleanupCache = () => { if (mermaidCache.size > MAX_CACHE_SIZE) { const entriesToRemove = Math.floor(MAX_CACHE_SIZE * .2); const keysToRemove = Array.from(mermaidCache.keys()).slice(0, entriesToRemove); for (const key of keysToRemove) mermaidCache.delete(key); } }; let mermaidPromise = null; const loadMermaid = () => { if (typeof window === "undefined") return Promise.resolve(null); if (!mermaidPromise) mermaidPromise = import("mermaid").then((mod) => mod.default); return mermaidPromise; }; const createMermaidConfig = (theme, customTheme) => ({ fontFamily: theme.fontFamilyCode, gantt: { useWidth: 1920 }, securityLevel: "loose", startOnLoad: false, theme: customTheme || (theme.isDarkMode ? "dark" : "neutral"), themeVariables: customTheme ? void 0 : { errorBkgColor: theme.colorTextDescription, errorTextColor: theme.colorTextDescription, fontFamily: theme.fontFamily, lineColor: theme.colorTextSecondary, mainBkg: theme.colorBgContainer, noteBkgColor: theme.colorInfoBg, noteTextColor: theme.colorInfoText, pie1: theme.geekblue, pie2: theme.colorWarning, pie3: theme.colorSuccess, pie4: theme.colorError, primaryBorderColor: theme.colorBorder, primaryColor: theme.colorBgContainer, primaryTextColor: theme.colorText, secondaryBorderColor: theme.colorInfoBorder, secondaryColor: theme.colorInfoBg, secondaryTextColor: theme.colorInfoText, tertiaryBorderColor: theme.colorSuccessBorder, tertiaryColor: theme.colorSuccessBg, tertiaryTextColor: theme.colorSuccessText, textColor: theme.colorText } }); /** * 验证并处理 Mermaid 图表内容 - 优化版本(移除 SWR) */ const useMermaid = (content, { id, theme: customTheme }) => { const theme = useTheme(); const [data, setData] = useState(""); const mermaidConfig = useMemo(() => createMermaidConfig(theme, customTheme), [ theme.fontFamilyCode, theme.isDarkMode, theme.colorTextDescription, theme.fontFamily, theme.colorTextSecondary, theme.colorBgContainer, theme.colorInfoBg, theme.colorInfoText, theme.geekblue, theme.colorWarning, theme.colorSuccess, theme.colorError, theme.colorBorder, theme.colorInfoBorder, theme.colorSuccessBorder, theme.colorSuccessBg, theme.colorSuccessText, theme.colorText, customTheme ]); const cacheKey = useMemo(() => { const hash = content.length < MD5_LENGTH_THRESHOLD ? content : Md5.hashStr(content); return [ id, customTheme || (theme.isDarkMode ? "d" : "l"), hash ].filter(Boolean).join("-"); }, [ content, id, theme.isDarkMode, customTheme ]); useEffect(() => { const cachedPromise = mermaidCache.get(cacheKey); if (cachedPromise) { cachedPromise.then((svg) => { setData(svg); }).catch(() => {}); return; } const renderPromise = (async () => { try { const mermaidInstance = await loadMermaid(); if (!mermaidInstance) return ""; if (await mermaidInstance.parse(content)) { mermaidInstance.initialize(mermaidConfig); const { svg } = await mermaidInstance.render(id, content); return svg; } else throw new Error("Mermaid 语法无效"); } catch (error_) { console.error("Mermaid 解析错误:", error_); return ""; } })(); mermaidCache.set(cacheKey, renderPromise); cleanupCache(); renderPromise.then((svg) => { if (mermaidCache.get(cacheKey) === renderPromise) setData(svg); }).catch(() => { if (mermaidCache.get(cacheKey) === renderPromise) mermaidCache.delete(cacheKey); }); }, [ cacheKey, content, id, mermaidConfig ]); return data; }; //#endregion export { createMermaidConfig, loadMermaid, useMermaid }; //# sourceMappingURL=useMermaid.mjs.map