From b37935c92b8c17ae0777a6be296392c7a945725e Mon Sep 17 00:00:00 2001 From: Monet Bird Date: Tue, 20 Dec 2022 01:19:54 +0800 Subject: [PATCH] Add copy for code blocks (#68) --- .vscode/settings.json | 3 +- src/main.ts | 2 ++ src/plugins/markdown-it-code-copy.ts | 44 ++++++++++++++++++++++++++++ styles/main.scss | 3 ++ styles/reset.scss | 17 +++++++++++ web/main.ts | 18 ++++++++++++ 6 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/plugins/markdown-it-code-copy.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 19ea39f..a651455 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,7 @@ "outfile", "packagejson", "predev", - "prereleased" + "prereleased", + "zeroclipboard" ] } diff --git a/src/main.ts b/src/main.ts index d946ad0..da75a00 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,7 @@ import vscode from "vscode"; import commands from "./commands"; import onRefreshMarkdownPreview from "./events/onRefreshMarkdownPreview"; import markdownItTheme from "./plugins/markdown-it-theme"; +import markdownItCodeCopy from "./plugins/markdown-it-code-copy"; export function activate(context: vscode.ExtensionContext) { const registerCommands = commands.map(({ command, commandHander }) => @@ -14,6 +15,7 @@ export function activate(context: vscode.ExtensionContext) { extendMarkdownIt(md: markdownit) { return md .use(markdownItTheme) + .use(markdownItCodeCopy) .use(require("markdown-it-emoji")) .use(require("markdown-it-github-headings"), { linkIcon: ``, diff --git a/src/plugins/markdown-it-code-copy.ts b/src/plugins/markdown-it-code-copy.ts new file mode 100644 index 0000000..9c33eb1 --- /dev/null +++ b/src/plugins/markdown-it-code-copy.ts @@ -0,0 +1,44 @@ +import type Renderer from "markdown-it/lib/renderer"; + +export default function markdownItCodeCopy(md: markdownit) { + function createRenderRule(originRule: Renderer.RenderRule) { + return function (...args: Parameters) { + const [tokens, idx] = args; + const content = tokens[idx].content.split("").reduce((result, pre) => { + switch (pre) { + case '"': + result += """; + break; + case "'": + result += "<"; + break; + default: + result += pre; + break; + } + return result; + }, ""); + + return ` +
+ ${originRule(...args)} +
+ + + + +
+
+ `; + }; + } + + md.renderer.rules.code_block = createRenderRule(md.renderer.rules.code_block); + md.renderer.rules.fence = createRenderRule(md.renderer.rules.fence); + + return md; +} diff --git a/styles/main.scss b/styles/main.scss index cfa97c8..fb474f1 100644 --- a/styles/main.scss +++ b/styles/main.scss @@ -2,5 +2,8 @@ @import "@primer/css/base/index.scss"; @import "@primer/css/markdown/index.scss"; @import "@primer/css/support/index.scss"; +@import "@primer/css/buttons/index.scss"; +@import "@primer/css/utilities/index.scss"; +@import "@primer/css/tooltips/index.scss"; @import "./reset.scss"; @import "./highlight.scss"; diff --git a/styles/reset.scss b/styles/reset.scss index 651cfc6..a3cdf49 100644 --- a/styles/reset.scss +++ b/styles/reset.scss @@ -56,4 +56,21 @@ body.showEditorSelection { .footnote-backref { font-family: monospace; } + + .highlight { + .zeroclipboard-container { + display: none; + animation: fade-out 200ms both; + } + &:hover { + .zeroclipboard-container { + display: block; + animation: fade-in 200ms both; + } + } + .ClipboardButton.ClipboardButton--success { + border-color: var(--color-success-emphasis); + box-shadow: 0 0 0 0.2em rgb(52 208 88 / 40%); + } + } } diff --git a/web/main.ts b/web/main.ts index e69de29..fc584de 100644 --- a/web/main.ts +++ b/web/main.ts @@ -0,0 +1,18 @@ +import "@primer/view-components/app/components/primer/beta/clipboard_copy"; +import "@primer/view-components/app/components/primer/alpha/tool_tip"; + +document.addEventListener("clipboard-copy", function (event) { + const button = event.target as HTMLButtonElement; + button.classList.add( + "ClipboardButton--success", + "tooltipped", + "tooltipped-w", + ); + setTimeout(() => { + button.classList.remove( + "ClipboardButton--success", + "tooltipped", + "tooltipped-w", + ); + }, 2e3); +});