diff --git a/app/(routes)/(main)/blog/[slug]/page.tsx b/app/(routes)/(main)/blog/[slug]/page.tsx index d321345..a84d06f 100644 --- a/app/(routes)/(main)/blog/[slug]/page.tsx +++ b/app/(routes)/(main)/blog/[slug]/page.tsx @@ -8,6 +8,7 @@ import Image from 'next/image'; import { Badge } from '@/components/ui/badge'; import Markdown from '@/components/markdown'; import TableOfContents from '@/app/_components/_main/table-of-contents'; +import MarkdownCopyListener from '@/app/_components/_main/markdown-copy-listener'; export async function generateMetadata({ params, @@ -80,6 +81,7 @@ export default async function Page({ params }: { params: { slug: string } }) { )} + {headings.length > 0 && } ); diff --git a/app/_components/_main/markdown-copy-listener.tsx b/app/_components/_main/markdown-copy-listener.tsx new file mode 100644 index 0000000..88cd824 --- /dev/null +++ b/app/_components/_main/markdown-copy-listener.tsx @@ -0,0 +1,29 @@ +'use client' +import { useEffect } from "react"; + +export default function MarkdownCopyListener() { + useEffect(() => { + const copyBtns = document.querySelectorAll('button.copy-code-btn') + copyBtns.forEach((btn) => { + (btn as HTMLButtonElement).addEventListener('click', () => { + const codeBlockContent = btn.parentElement?.nextElementSibling?.textContent + if (codeBlockContent) { + navigator.clipboard.writeText(codeBlockContent).then(() => { + btn.textContent = 'Copied' + setTimeout(() => { + btn.textContent = 'Copy' + }, 2000) + }) + } + }) + }) + + return () => { + copyBtns.forEach((btn) => { + (btn as HTMLButtonElement).removeEventListener('click', () => { }) + }) + } + }, []) + + return null +} diff --git a/components/markdown.tsx b/components/markdown.tsx index 7176065..9e6759e 100644 --- a/components/markdown.tsx +++ b/components/markdown.tsx @@ -43,7 +43,7 @@ const Markdown = ({ markdown }: { markdown: string }) => { `; }, code({ text, lang }) { - return `
${lang}
${text}
`; + return `
${lang}
${text}
`; }, link(args) { const link = marked.Renderer.prototype.link.call(this, args); @@ -81,7 +81,6 @@ const Markdown = ({ markdown }: { markdown: string }) => { dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(marked.parse(markdown) as string, { USE_PROFILES: { html: true }, - ADD_ATTR: ['onclick'], }), }} >