import { useEffect, useState } from "react"; import type { RenderedMarkdownDocument } from "@md-to-pdf/core"; export interface MarkdownRenderCallbacks { onRenderStart?: () => void; onStatusChange?: (status: string) => void; } export function useMarkdownRender( markdown: string, language: string, callbacks: MarkdownRenderCallbacks = {} ) { const [result, setResult] = useState(null); const [error, setError] = useState(""); const { onRenderStart, onStatusChange } = callbacks; useEffect(() => { const controller = new AbortController(); const timer = window.setTimeout(() => { onStatusChange?.("正在渲染…"); onRenderStart?.(); setError(""); void fetch("/api/render", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ markdown, language }), signal: controller.signal }) .then(async (response) => { const payload = (await response.json()) as | RenderedMarkdownDocument | { message?: string }; if (!response.ok) { throw new Error( "message" in payload ? payload.message ?? "渲染失败" : "渲染失败" ); } return payload as RenderedMarkdownDocument; }) .then((payload) => { setResult(payload); onStatusChange?.("预览已更新"); }) .catch((reason: unknown) => { if (!controller.signal.aborted) { setError( reason instanceof Error ? reason.message : "渲染失败" ); onStatusChange?.("预览失败"); } }); }, 250); return () => { window.clearTimeout(timer); controller.abort(); }; }, [language, markdown, onRenderStart, onStatusChange]); return { error, result }; }