diff --git a/packages/mini-markdown-editor/src/components/Preview/index.tsx b/packages/mini-markdown-editor/src/components/Preview/index.tsx index ce3ba304d800c5c3665c536ec4b523729a7d5c73..8b56dcd5672c54517c282e6ad69c42516708af8d 100644 --- a/packages/mini-markdown-editor/src/components/Preview/index.tsx +++ b/packages/mini-markdown-editor/src/components/Preview/index.tsx @@ -1,18 +1,15 @@ import React, { FC, useEffect, useRef, useCallback, useContext } from "react"; -import { createRoot, type Root } from "react-dom/client"; import { parseMarkdown, transformHtml } from "@mini-markdown/ast-parser"; import styled from "styled-components"; import { useEditorContentStore } from "@/store/editor"; import { handlePreviewScroll } from "@/utils/handle-scroll"; import { usePreviewTheme } from "@/hooks/use-preview-theme"; import { ConfigContext } from "../providers/config-provider"; -import { CopyButton } from "./CopyCodeButton"; +import { useCopyCode } from "@/hooks/use-copy-code"; const Preview: FC<{ content: string; isSyncScroll: boolean }> = ({ content, isSyncScroll }) => { const { scrollWrapper, setScrollWrapper, setPreviewView, editorView } = useEditorContentStore(); const previewRef = useRef(null); - //* 存储清理函数 - const cleanupRef = useRef<(() => void) | null>(null); // 更新预览视图 const updatePreviewView = useCallback( @@ -55,67 +52,8 @@ const Preview: FC<{ content: string; isSyncScroll: boolean }> = ({ content, isSy const { theme } = useContext(ConfigContext); usePreviewTheme(theme as "light" | "dark"); - // 处理代码块复制按钮 - useEffect(() => { - if (!previewRef.current) return; - // 清理之前的按钮 - if (cleanupRef.current) { - cleanupRef.current(); - } - // 添加新的按钮 - const addCopyButtons = () => { - const codeHeaders = previewRef.current?.querySelectorAll(".mini-md-code-right"); - const currentRoots = new Map(); - - codeHeaders?.forEach((header) => { - try { - if (header.querySelector(".copy-code-button")) return; - - const codeElement = header.closest(".mini-md-code-container")?.querySelector("code"); - if (!codeElement) return; - - const copyButtonContainer = document.createElement("div"); - copyButtonContainer.className = "copy-code-button-wrapper"; - - const root = createRoot(copyButtonContainer); - currentRoots.set(copyButtonContainer, root); - - root.render(); - - header.appendChild(copyButtonContainer); - } catch (error) { - console.error("Copy Error:", error); - } - }); - - // 保存清理函数 - cleanupRef.current = () => { - setTimeout(() => { - currentRoots.forEach((root, container) => { - try { - root.unmount(); - container.remove(); - } catch (error) { - console.error("Failed to cleanup copy button:", error); - } - }); - currentRoots.clear(); - }, 0); - }; - }; - - // 防止添加按钮时dom未渲染 - requestAnimationFrame(() => { - addCopyButtons(); - }); - - return () => { - // 组件卸载时执行清理,把清理函数执行 - if (cleanupRef.current) { - cleanupRef.current(); - } - }; - }, [node]); + // copy按钮 + useCopyCode({ previewRef, node }); return ( ; + node: string; +}) => { + //* 存储清理函数 + const cleanupRef = useRef<(() => void) | null>(null); + // 处理代码块复制按钮 + useEffect(() => { + if (!previewRef.current) return; + // 清理之前的按钮 + if (cleanupRef.current) { + cleanupRef.current(); + } + // 添加新的按钮 + const addCopyButtons = () => { + const codeHeaders = previewRef.current?.querySelectorAll(".mini-md-code-right"); + const currentRoots = new Map(); + + codeHeaders?.forEach((header: Element) => { + try { + if (header.querySelector(".copy-code-button")) return; + + const codeElement = header.closest(".mini-md-code-container")?.querySelector("code"); + if (!codeElement) return; + + const copyButtonContainer = document.createElement("div"); + copyButtonContainer.className = "copy-code-button-wrapper"; + + const root = createRoot(copyButtonContainer); + currentRoots.set(copyButtonContainer, root); + + root.render(); + + header.appendChild(copyButtonContainer); + } catch (error) { + console.error("Copy Error:", error); + } + }); + + // 保存清理函数 + cleanupRef.current = () => { + setTimeout(() => { + currentRoots.forEach((root, container) => { + try { + root.unmount(); + container.remove(); + } catch (error) { + console.error("Failed to cleanup copy button:", error); + } + }); + currentRoots.clear(); + }, 0); + }; + }; + + // 防止添加按钮时dom未渲染 + requestAnimationFrame(() => { + addCopyButtons(); + }); + + return () => { + // 组件卸载时执行清理,把清理函数执行 + if (cleanupRef.current) { + cleanupRef.current(); + } + }; + }, [node]); +}; diff --git a/packages/mini-markdown-editor/vite.config.ts b/packages/mini-markdown-editor/vite.config.ts index 043f3a0242ad69048fd95fc32ce5fe3fc2b1f82e..24611fa9960b01fa439e3070eaa0cec559e9092b 100644 --- a/packages/mini-markdown-editor/vite.config.ts +++ b/packages/mini-markdown-editor/vite.config.ts @@ -62,6 +62,7 @@ export default defineConfig(({ mode }) => { "@codemirror/language-data": "languageData$1", "@codemirror/view": "view", "highlight.js": "hljs", + nanoid: "nanoid", }, }, },