Skip to content

Commit b37935c

Browse files
authored
Add copy for code blocks (#68)
1 parent e104d2a commit b37935c

File tree

6 files changed

+86
-1
lines changed

6 files changed

+86
-1
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"outfile",
1919
"packagejson",
2020
"predev",
21-
"prereleased"
21+
"prereleased",
22+
"zeroclipboard"
2223
]
2324
}

src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import vscode from "vscode";
22
import commands from "./commands";
33
import onRefreshMarkdownPreview from "./events/onRefreshMarkdownPreview";
44
import markdownItTheme from "./plugins/markdown-it-theme";
5+
import markdownItCodeCopy from "./plugins/markdown-it-code-copy";
56

67
export function activate(context: vscode.ExtensionContext) {
78
const registerCommands = commands.map(({ command, commandHander }) =>
@@ -14,6 +15,7 @@ export function activate(context: vscode.ExtensionContext) {
1415
extendMarkdownIt(md: markdownit) {
1516
return md
1617
.use(markdownItTheme)
18+
.use(markdownItCodeCopy)
1719
.use(require("markdown-it-emoji"))
1820
.use(require("markdown-it-github-headings"), {
1921
linkIcon: `<svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg>`,

src/plugins/markdown-it-code-copy.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import type Renderer from "markdown-it/lib/renderer";
2+
3+
export default function markdownItCodeCopy(md: markdownit) {
4+
function createRenderRule(originRule: Renderer.RenderRule) {
5+
return function (...args: Parameters<Renderer.RenderRule>) {
6+
const [tokens, idx] = args;
7+
const content = tokens[idx].content.split("").reduce((result, pre) => {
8+
switch (pre) {
9+
case '"':
10+
result += "&quot;";
11+
break;
12+
case "'":
13+
result += "&lt;";
14+
break;
15+
default:
16+
result += pre;
17+
break;
18+
}
19+
return result;
20+
}, "");
21+
22+
return `
23+
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto">
24+
${originRule(...args)}
25+
<div class="zeroclipboard-container position-absolute right-0 top-0">
26+
<clipboard-copy style="margin: 7.8px;" aria-label="Copied!" data-view-component="true" class="ClipboardButton btn js-clipboard-copy tooltipped-no-delay p-0" data-copy-feedback="Copied!" value="${content}" tabindex="0" role="button">
27+
<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2">
28+
<path fill-rule="evenodd" d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z"></path><path fill-rule="evenodd" d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z"></path>
29+
</svg>
30+
<svg style="display: none;" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success m-2">
31+
<path fill-rule="evenodd" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path>
32+
</svg>
33+
</clipboard-copy>
34+
</div>
35+
</div>
36+
`;
37+
};
38+
}
39+
40+
md.renderer.rules.code_block = createRenderRule(md.renderer.rules.code_block);
41+
md.renderer.rules.fence = createRenderRule(md.renderer.rules.fence);
42+
43+
return md;
44+
}

styles/main.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22
@import "@primer/css/base/index.scss";
33
@import "@primer/css/markdown/index.scss";
44
@import "@primer/css/support/index.scss";
5+
@import "@primer/css/buttons/index.scss";
6+
@import "@primer/css/utilities/index.scss";
7+
@import "@primer/css/tooltips/index.scss";
58
@import "./reset.scss";
69
@import "./highlight.scss";

styles/reset.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,21 @@ body.showEditorSelection {
5656
.footnote-backref {
5757
font-family: monospace;
5858
}
59+
60+
.highlight {
61+
.zeroclipboard-container {
62+
display: none;
63+
animation: fade-out 200ms both;
64+
}
65+
&:hover {
66+
.zeroclipboard-container {
67+
display: block;
68+
animation: fade-in 200ms both;
69+
}
70+
}
71+
.ClipboardButton.ClipboardButton--success {
72+
border-color: var(--color-success-emphasis);
73+
box-shadow: 0 0 0 0.2em rgb(52 208 88 / 40%);
74+
}
75+
}
5976
}

web/main.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import "@primer/view-components/app/components/primer/beta/clipboard_copy";
2+
import "@primer/view-components/app/components/primer/alpha/tool_tip";
3+
4+
document.addEventListener("clipboard-copy", function (event) {
5+
const button = event.target as HTMLButtonElement;
6+
button.classList.add(
7+
"ClipboardButton--success",
8+
"tooltipped",
9+
"tooltipped-w",
10+
);
11+
setTimeout(() => {
12+
button.classList.remove(
13+
"ClipboardButton--success",
14+
"tooltipped",
15+
"tooltipped-w",
16+
);
17+
}, 2e3);
18+
});

0 commit comments

Comments
 (0)