feat: copy button for code blocks (#67)
* Add code copy * fix: safari copyButton style * fix: addPreCopyButton up time * modify: CopyButton style * fix: Duplicate rendering issue with copy button
This commit is contained in:
parent
815692899d
commit
88a7414625
|
@ -13,6 +13,58 @@ const className = Astro.props.class;
|
||||||
<slot/>
|
<slot/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { i18n } from "@i18n/translation";
|
||||||
|
import I18nKey from "@i18n/i18nKey";
|
||||||
|
|
||||||
|
const observer = new MutationObserver(addPreCopyButton);
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", addPreCopyButton);
|
||||||
|
|
||||||
|
function addPreCopyButton() {
|
||||||
|
observer.disconnect();
|
||||||
|
|
||||||
|
let codeBlocks = Array.from(document.querySelectorAll("pre"));
|
||||||
|
|
||||||
|
for (let codeBlock of codeBlocks) {
|
||||||
|
if (codeBlock.parentElement?.nodeName === "DIV" && codeBlock.parentElement?.classList.contains("code-block")) continue
|
||||||
|
|
||||||
|
let wrapper = document.createElement("div");
|
||||||
|
wrapper.className = "relative code-block";
|
||||||
|
|
||||||
|
let copyButton = document.createElement("button");
|
||||||
|
copyButton.className = "copy-code btn-regular absolute top-0 right-0 text-sm px-3 py-2 rounded-bl-lg rounded-tr-lg opacity-75 hover:opacity-100 transition-all duration-200 ease-in-out";
|
||||||
|
copyButton.textContent = i18n(I18nKey.codeCopy);
|
||||||
|
|
||||||
|
codeBlock.setAttribute("tabindex", "0");
|
||||||
|
if (codeBlock.parentNode) {
|
||||||
|
codeBlock.parentNode.insertBefore(wrapper, codeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.appendChild(codeBlock);
|
||||||
|
wrapper.appendChild(copyButton);
|
||||||
|
|
||||||
|
copyButton.addEventListener("click", async () => {
|
||||||
|
let text = codeBlock?.querySelector("code")?.innerText;
|
||||||
|
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
|
||||||
|
copyButton.textContent = i18n(I18nKey.codeCopied);
|
||||||
|
copyButton.classList.toggle("opacity-100");
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
copyButton.textContent = i18n(I18nKey.codeCopy);
|
||||||
|
copyButton.classList.toggle("opacity-100");
|
||||||
|
}, 700);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style lang="stylus" is:global>
|
<style lang="stylus" is:global>
|
||||||
.custom-md
|
.custom-md
|
||||||
h1, h2, h3, h4, h5, h6
|
h1, h2, h3, h4, h5, h6
|
||||||
|
|
|
@ -32,6 +32,9 @@ enum I18nKey {
|
||||||
author = 'author',
|
author = 'author',
|
||||||
publishedAt = 'publishedAt',
|
publishedAt = 'publishedAt',
|
||||||
license = 'license',
|
license = 'license',
|
||||||
|
|
||||||
|
codeCopy = 'copy',
|
||||||
|
codeCopied = 'codeCopied',
|
||||||
}
|
}
|
||||||
|
|
||||||
export default I18nKey
|
export default I18nKey
|
||||||
|
|
|
@ -35,4 +35,7 @@ export const en: Translation = {
|
||||||
[Key.author]: 'Author',
|
[Key.author]: 'Author',
|
||||||
[Key.publishedAt]: 'Published at',
|
[Key.publishedAt]: 'Published at',
|
||||||
[Key.license]: 'License',
|
[Key.license]: 'License',
|
||||||
|
|
||||||
|
[Key.codeCopy]: 'Copy',
|
||||||
|
[Key.codeCopied]: 'Code copied',
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,4 +35,7 @@ export const ja: Translation = {
|
||||||
[Key.author]: '作者',
|
[Key.author]: '作者',
|
||||||
[Key.publishedAt]: '公開日',
|
[Key.publishedAt]: '公開日',
|
||||||
[Key.license]: 'ライセンス',
|
[Key.license]: 'ライセンス',
|
||||||
|
|
||||||
|
[Key.codeCopy]: 'コピー',
|
||||||
|
[Key.codeCopied]: 'コピーしました',
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,4 +35,7 @@ export const zh_CN: Translation = {
|
||||||
[Key.author]: '作者',
|
[Key.author]: '作者',
|
||||||
[Key.publishedAt]: '发布于',
|
[Key.publishedAt]: '发布于',
|
||||||
[Key.license]: '许可协议',
|
[Key.license]: '许可协议',
|
||||||
|
|
||||||
|
[Key.codeCopy]: '复制',
|
||||||
|
[Key.codeCopied]: '复制成功',
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,4 +35,7 @@ export const zh_TW: Translation = {
|
||||||
[Key.author]: '作者',
|
[Key.author]: '作者',
|
||||||
[Key.publishedAt]: '發佈於',
|
[Key.publishedAt]: '發佈於',
|
||||||
[Key.license]: '許可協議',
|
[Key.license]: '許可協議',
|
||||||
|
|
||||||
|
[Key.codeCopy]: '複製',
|
||||||
|
[Key.codeCopied]: '複製成功',
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue