diff --git a/src/parser/copycode.ts b/src/parser/copycode.ts
new file mode 100644
index 0000000..2fedd6c
--- /dev/null
+++ b/src/parser/copycode.ts
@@ -0,0 +1,19 @@
+import MarkdownIt from 'markdown-it';
+import octicons from '@primer/octicons';
+
+const copyIcon = octicons['copy'].toSVG({ class: 'icon-copy' });
+
+export default function copycode(md: MarkdownIt) {
+ const defaultRender = md.renderer.rules.fence!;
+ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
+ const renderedPreBlock = defaultRender(tokens, idx, options, env, self);
+ return `
+
+ ${renderedPreBlock}
+
+
+
+
+`;
+ };
+}
diff --git a/src/parser/markdown.ts b/src/parser/markdown.ts
index 9a0fe9d..ffdadeb 100644
--- a/src/parser/markdown.ts
+++ b/src/parser/markdown.ts
@@ -1,5 +1,6 @@
import MarkdownIt from 'markdown-it';
import anchor from 'markdown-it-anchor';
+import copycode from './copycode.js';
import frontMatter from 'markdown-it-front-matter';
import highlight from './highlight.js';
import graphviz from './dot.js';
@@ -68,6 +69,7 @@ mdit.use(anchor, {
placement: 'before',
}),
});
+mdit.use(copycode);
mdit.use(graphviz);
mdit.use(githubAlerts);
mdit.use(mermaid);
diff --git a/static/markdown.css b/static/markdown.css
index e15c326..ecf17c7 100644
--- a/static/markdown.css
+++ b/static/markdown.css
@@ -180,6 +180,35 @@ blockquote {
color: var(--alert-caution);
}
+/* --------------------------------------------------------------------------
+ * COPY-CODE-BUTTON --------------------------------------------------------- */
+
+.copy-wrapper {
+ position: absolute;
+ top: 0.5rem;
+ right: 0.5rem;
+}
+.copy-button {
+ padding: 0.4rem;
+ border: 0;
+ border-radius: 0.4rem;
+ background: none;
+ opacity: 0;
+ outline: none;
+ cursor: pointer;
+ transition: opacity 0.2s, background 0.2s;
+}
+pre:hover + .copy-wrapper .copy-button {
+ opacity: 0.3;
+}
+.copy-button:hover {
+ opacity: 1;
+ background-color: var(--border-regular);
+}
+.copy-button {
+ fill: var(--text-primary);
+}
+
/* --------------------------------------------------------------------------
* MISCELLANEOUS ------------------------------------------------------------ */