Files
tsuki/assets/js/code-copy.js
T
tiennm99 e19bb67c88 feat: visual layer with vi typography, dark mode, view transitions (Phase 6)
- 9 CSS files (tokens, reset, typography, layout, components, home,
  archive, toc, view-transitions) bundled via resources.Concat
- 3 ES module JS files (theme-toggle, code-copy, toc-active); toc-active
  loaded only on long posts
- @view-transition: navigation auto for cross-page morph (CSS-only)
- TOC partial gated by WordCount>400 and Params.toc!=false; sticky on
  wide viewports, framed block on narrow
- render-heading.html adds cosmetic anchor links
- Hugo asset pipeline: resources.Concat | minify | fingerprint (no
  SCSS, no PostCSS, no Node)
- i18n/vi.yml extended with prev/next/posts/archiveEmpty/toggleTheme
- Bundle sizes: CSS 3.3 KB gz (budget 15), JS 0.8 KB gz (budget 8)

Config: github-ascii heading IDs, :contentbasename permalink token for
clean ASCII URLs, pagination.pagerSize migration (Hugo 0.128+).
2026-05-07 21:27:46 +07:00

24 lines
655 B
JavaScript

const COPY = "Sao chép";
const COPIED = "Đã chép";
const FAILED = "Lỗi";
for (const pre of document.querySelectorAll("pre")) {
const code = pre.querySelector("code");
if (!code) continue;
const btn = document.createElement("button");
btn.type = "button";
btn.className = "code-copy";
btn.setAttribute("aria-label", COPY);
btn.textContent = COPY;
pre.appendChild(btn);
btn.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(code.innerText);
btn.textContent = COPIED;
} catch {
btn.textContent = FAILED;
}
setTimeout(() => { btn.textContent = COPY; }, 1500);
});
}