From f031666ffcba75589aad7c411a25825ff79d4aea Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Tue, 30 Dec 2025 11:38:08 -0500 Subject: [PATCH] code style change --- src/components/blog/PostBodyClient.tsx | 67 ++++++++++++++++++++++++++ src/routes/blog/post.css | 17 +++++++ 2 files changed, 84 insertions(+) diff --git a/src/components/blog/PostBodyClient.tsx b/src/components/blog/PostBodyClient.tsx index 87e8715..14ea319 100644 --- a/src/components/blog/PostBodyClient.tsx +++ b/src/components/blog/PostBodyClient.tsx @@ -96,6 +96,66 @@ export default function PostBodyClient(props: PostBodyClientProps) { let contentRef: HTMLDivElement | undefined; const [hljs, setHljs] = createSignal(null); + const addCopyButtons = () => { + if (!contentRef) return; + + const codeBlocks = contentRef.querySelectorAll("pre code"); + + codeBlocks.forEach((codeBlock) => { + const pre = codeBlock.parentElement; + if (!pre || pre.querySelector(".copy-button")) return; + + // Create wrapper for positioning + pre.style.position = "relative"; + + // Create copy button + const copyButton = document.createElement("button"); + copyButton.className = + "copy-button absolute top-2 right-2 px-3 py-1.5 text-xs font-medium rounded transition-all duration-200 z-10"; + copyButton.style.cssText = + "background-color: var(--color-surface0); color: var(--color-text); border: 1px solid var(--color-overlay0);"; + copyButton.textContent = "Copy"; + + copyButton.addEventListener("mouseenter", () => { + copyButton.style.backgroundColor = "var(--color-surface1)"; + }); + + copyButton.addEventListener("mouseleave", () => { + if (copyButton.textContent === "Copy") { + copyButton.style.backgroundColor = "var(--color-surface0)"; + } + }); + + copyButton.addEventListener("click", async () => { + const code = codeBlock.textContent || ""; + + try { + await navigator.clipboard.writeText(code); + copyButton.textContent = "Copied!"; + copyButton.style.backgroundColor = "var(--color-green)"; + copyButton.style.color = "var(--color-base)"; + + setTimeout(() => { + copyButton.textContent = "Copy"; + copyButton.style.backgroundColor = "var(--color-surface0)"; + copyButton.style.color = "var(--color-text)"; + }, 2000); + } catch (err) { + console.error("Failed to copy code:", err); + copyButton.textContent = "Failed"; + copyButton.style.backgroundColor = "var(--color-red)"; + + setTimeout(() => { + copyButton.textContent = "Copy"; + copyButton.style.backgroundColor = "var(--color-surface0)"; + }, 2000); + } + }); + + pre.appendChild(copyButton); + }); + }; + const processReferences = () => { if (!contentRef) return; @@ -253,6 +313,7 @@ export default function PostBodyClient(props: PostBodyClientProps) { if (hljsInstance && props.hasCodeBlock && contentRef) { setTimeout(() => { hljsInstance.highlightAll(); + addCopyButtons(); }, 100); } }); @@ -261,6 +322,9 @@ export default function PostBodyClient(props: PostBodyClientProps) { onMount(() => { setTimeout(() => { processReferences(); + if (props.hasCodeBlock) { + addCopyButtons(); + } }, 150); }); @@ -269,6 +333,9 @@ export default function PostBodyClient(props: PostBodyClientProps) { if (props.body && contentRef) { setTimeout(() => { processReferences(); + if (props.hasCodeBlock) { + addCopyButtons(); + } }, 150); } }); diff --git a/src/routes/blog/post.css b/src/routes/blog/post.css index 9164502..7d31393 100644 --- a/src/routes/blog/post.css +++ b/src/routes/blog/post.css @@ -687,3 +687,20 @@ button:active, #post-content-body span#references-section-start { display: none !important; } +pre { + background: #0d0d0d; + color: #fff; + font-family: "Source Code Pro", monospace; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + + code { + color: inherit; + padding: 0; + background: none; + font-size: 0.8rem; + max-height: 60vh; + overflow-y: auto; + scrollbar-color: var(--color-text) transparent; + } +}