Add copy button to code blocks (closes #18)
This commit is contained in:
parent
6354a2fc09
commit
8a18e31ced
5 changed files with 61 additions and 2 deletions
|
@ -113,6 +113,7 @@ pre {
|
|||
border-radius: 0.25em;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.code-inline,
|
||||
|
|
|
@ -5,3 +5,47 @@ window.Alpine = Alpine;
|
|||
|
||||
Alpine.plugin(persist);
|
||||
Alpine.start();
|
||||
|
||||
/* Copy button component */
|
||||
|
||||
const copyIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M7 4V2h10v2h3.007c.548 0 .993.445.993.993v16.014a.994.994 0 0 1-.993.993H3.993A.994.994 0 0 1 3 21.007V4.993C3 4.445 3.445 4 3.993 4H7zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"/></svg>`;
|
||||
const checkIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>`;
|
||||
const defaultButtonLabel = `Zkopírovat text do schránky`;
|
||||
const copiedButtonLabel = `Text zkopírován`;
|
||||
const revertTimeout = 5_000;
|
||||
|
||||
const accessibleLabel = (text) => `<span class="sr-only">${text}</span>`;
|
||||
|
||||
const defaultButtonContent = copyIcon + accessibleLabel(defaultButtonLabel);
|
||||
const copiedButtonContent = checkIcon + accessibleLabel(copiedButtonLabel);
|
||||
|
||||
navigator.permissions
|
||||
.query({
|
||||
name: "clipboard-read",
|
||||
})
|
||||
.then((permission) => {
|
||||
if (permission.state == "denied") {
|
||||
return;
|
||||
}
|
||||
document
|
||||
.querySelectorAll(".prose pre code, .code-block")
|
||||
.forEach((codeBlock) => {
|
||||
const button = document.createElement("button");
|
||||
button.innerHTML = defaultButtonContent;
|
||||
button.className = "button absolute top-3 right-3 bg-white";
|
||||
|
||||
button.addEventListener("click", () => {
|
||||
navigator.clipboard.writeText(codeBlock.innerHTML).then(() => {
|
||||
button.innerHTML = copiedButtonContent;
|
||||
setTimeout(() => {
|
||||
button.innerHTML = defaultButtonContent;
|
||||
}, revertTimeout);
|
||||
});
|
||||
});
|
||||
|
||||
codeBlock.parentElement.insertBefore(
|
||||
button,
|
||||
codeBlock.nextElementSibling
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -630,6 +630,14 @@ video {
|
|||
right: 1.5rem;
|
||||
}
|
||||
|
||||
.top-3 {
|
||||
top: 0.75rem;
|
||||
}
|
||||
|
||||
.right-3 {
|
||||
right: 0.75rem;
|
||||
}
|
||||
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
|
@ -784,6 +792,11 @@ video {
|
|||
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.px-6 {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
|
@ -966,6 +979,7 @@ pre {
|
|||
border-radius: 0.25em;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.code-inline,
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{- $js := resources.Get "main.js" | js.Build | resources.Minify | fingerprint -}}
|
||||
{{- $js := resources.Get "main.js" | js.Build | fingerprint -}}
|
||||
<script src="{{ $js.RelPermalink }}" integrity="{{ $js.Data.Integrity }}" defer></script>
|
||||
|
|
|
@ -2,7 +2,7 @@ const colors = require("tailwindcss/");
|
|||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["content/**/*.md", "layouts/**/*.html"],
|
||||
content: ["content/**/*.md", "layouts/**/*.html", "assets/**/*.js"],
|
||||
theme: {
|
||||
fontFamily: {
|
||||
main: [
|
||||
|
|
Loading…
Reference in a new issue