Browse Source

feat: #9 add copy code button

Yifei Zhang 1 year ago
parent
commit
e57bd51809
3 changed files with 59 additions and 5 deletions
  1. 25 4
      app/components/markdown.tsx
  2. 1 1
      app/page.tsx
  3. 33 0
      app/styles/globals.scss

+ 25 - 4
app/components/markdown.tsx

@@ -4,15 +4,36 @@ import RemarkMath from "remark-math";
 import RehypeKatex from "rehype-katex";
 import RemarkGfm from "remark-gfm";
 import RehypePrsim from "rehype-prism-plus";
+import { useRef } from "react";
+import { copyToClipboard } from "../utils";
+
+export function PreCode(props: { children: any }) {
+  const ref = useRef<HTMLPreElement>(null);
+
+  return (
+    <pre ref={ref}>
+      <span
+        className="copy-code-button"
+        onClick={() => {
+          if (ref.current) {
+            const code = ref.current.innerText;
+            copyToClipboard(code);
+          }
+        }}
+      ></span>
+      {props.children}
+    </pre>
+  );
+}
 
 export function Markdown(props: { content: string }) {
   return (
     <ReactMarkdown
       remarkPlugins={[RemarkMath, RemarkGfm]}
-      rehypePlugins={[
-        RehypeKatex,
-        [RehypePrsim, { ignoreMissing: true }],
-      ]}
+      rehypePlugins={[RehypeKatex, [RehypePrsim, { ignoreMissing: true }]]}
+      components={{
+        pre: PreCode,
+      }}
     >
       {props.content}
     </ReactMarkdown>

+ 1 - 1
app/page.tsx

@@ -1,5 +1,5 @@
 import { Analytics } from "@vercel/analytics/react";
-import { Home } from './components/home'
+import { Home } from "./components/home";
 
 export default function App() {
   return (

+ 33 - 0
app/styles/globals.scss

@@ -206,3 +206,36 @@ div.math {
     text-decoration: underline;
   }
 }
+
+pre {
+  position: relative;
+
+  &:hover .copy-code-button {
+    pointer-events: all;
+    transform: translateX(0px);
+    opacity: 0.5;
+  }
+
+  .copy-code-button {
+    position: absolute;
+    right: 10px;
+    cursor: pointer;
+    padding: 0px 5px;
+    background-color: var(--black);
+    color: var(--white);
+    border: var(--border-in-light);
+    border-radius: 10px;
+    transform: translateX(10px);
+    pointer-events: none;
+    opacity: 0;
+    transition: all ease 0.3s;
+
+    &:after {
+      content: "copy";
+    }
+
+    &:hover {
+      opacity: 1;
+    }
+  }
+}