From d6a91919e0731b956503893d3e3d05b8c0358a65 Mon Sep 17 00:00:00 2001 From: Lea Verou Date: Fri, 14 Feb 2025 14:53:18 -0500 Subject: [PATCH] Code block improvements - Add ids, use ids to link copy button. No need for client-side script or updating the copy button manually for dynamic code snippets. - Add button to link to code block - Slight refactor on copy plugin to use the 11ty API properly --- docs/.eleventy.js | 2 +- docs/_includes/base.njk | 1 - docs/_utils/copy-code.js | 43 +++++++++++++++++++------------- docs/assets/scripts/copy-code.js | 15 ----------- docs/assets/styles/copy-code.css | 16 ++++++++++++ src/components/page/page.css | 2 +- 6 files changed, 44 insertions(+), 35 deletions(-) delete mode 100644 docs/assets/scripts/copy-code.js diff --git a/docs/.eleventy.js b/docs/.eleventy.js index 86bba34fd..c32049193 100644 --- a/docs/.eleventy.js +++ b/docs/.eleventy.js @@ -94,7 +94,7 @@ export default function (eleventyConfig) { eleventyConfig.addPlugin(highlightCodePlugin()); // Add copy code buttons to code blocks - eleventyConfig.addPlugin(copyCodePlugin()); + eleventyConfig.addPlugin(copyCodePlugin); // Various text replacements eleventyConfig.addPlugin( diff --git a/docs/_includes/base.njk b/docs/_includes/base.njk index d0d8cafd4..a7cb9a04d 100644 --- a/docs/_includes/base.njk +++ b/docs/_includes/base.njk @@ -5,7 +5,6 @@ - diff --git a/docs/_utils/copy-code.js b/docs/_utils/copy-code.js index 19d04a958..b28b95cf5 100644 --- a/docs/_utils/copy-code.js +++ b/docs/_utils/copy-code.js @@ -3,30 +3,39 @@ import { parse } from 'node-html-parser'; /** * Eleventy plugin to add copy buttons to code blocks. */ -export function copyCodePlugin(options = {}) { +export function copyCodePlugin(eleventyConfig, options = {}) { options = { container: 'body', ...options, }; - return function (eleventyConfig) { - eleventyConfig.addTransform('copy-code', content => { - const doc = parse(content, { blockTextElements: { code: true } }); - const container = doc.querySelector(options.container); + let codeCount = 0; + eleventyConfig.addTransform('copy-code', content => { + const doc = parse(content, { blockTextElements: { code: true } }); + const container = doc.querySelector(options.container); - if (!container) { - return content; + if (!container) { + return content; + } + + // Look for code blocks + container.querySelectorAll('pre > code').forEach(code => { + const pre = code.closest('pre'); + let preId = pre.getAttribute('id') || `code-block-${++codeCount}`; + let codeId = code.getAttribute('id') || `${preId}-inner`; + + if (!code.getAttribute('id')) { + code.setAttribute('id', codeId); + } + if (!pre.getAttribute('id')) { + pre.setAttribute('id', preId); } - // Look for code blocks - container.querySelectorAll('pre > code').forEach(code => { - const pre = code.closest('pre'); - - // Add a copy button (we set the copy data at runtime to reduce page bloat) - pre.innerHTML = `` + pre.innerHTML; - }); - - return doc.toString(); + // Add a copy button + pre.innerHTML += ` + `; }); - }; + + return doc.toString(); + }); } diff --git a/docs/assets/scripts/copy-code.js b/docs/assets/scripts/copy-code.js deleted file mode 100644 index ff8f82a6e..000000000 --- a/docs/assets/scripts/copy-code.js +++ /dev/null @@ -1,15 +0,0 @@ -function setCopyValue() { - document.querySelectorAll('.copy-button').forEach(copyButton => { - const pre = copyButton.closest('pre'); - const code = pre?.querySelector('code'); - - if (code) { - copyButton.value = code.textContent; - } - }); -} - -// Set data for all copy buttons when the page loads -setCopyValue(); - -document.addEventListener('turbo:load', setCopyValue); diff --git a/docs/assets/styles/copy-code.css b/docs/assets/styles/copy-code.css index d9fe94e36..f65887b64 100644 --- a/docs/assets/styles/copy-code.css +++ b/docs/assets/styles/copy-code.css @@ -27,3 +27,19 @@ wa-copy-button.copy-button { opacity: 1; } } + +.block-link-icon { + position: absolute; + inset-block-start: 0; + inset-inline-end: calc(100% + var(--wa-space-s)); + + transition: var(--wa-transition-slow); + + &:not(:hover, :focus) { + opacity: 50%; + } + + :not(:hover, :focus-within) > & { + opacity: 0; + } +} diff --git a/src/components/page/page.css b/src/components/page/page.css index 928501763..782afcf30 100644 --- a/src/components/page/page.css +++ b/src/components/page/page.css @@ -9,7 +9,7 @@ --banner-height: 0px; --header-height: 0px; --subheader-height: 0px; - --scroll-margin-top: calc(var(--header-height, 0px) + var(--subheader-height, 0px)); + --scroll-margin-top: calc(var(--header-height, 0px) + var(--subheader-height, 0px) + 0.5em); } slot[name]:not([name='skip-to-content'], [name='navigation-toggle'])::slotted(*) {