From 9f7511b203317fc38862e99e0d2fa659d9e6cbd0 Mon Sep 17 00:00:00 2001 From: Geri Ochoa Date: Mon, 27 Feb 2023 14:59:14 -0500 Subject: [PATCH] Refactor Click-to-copy with Bootstrap5 Refactor of PR #1245. Bootstrap5-compatible code. --- CHANGELOG.md | 8 +- assets/js/click-to-copy.js | 102 ++++-------- assets/scss/_code.scss | 149 ++++++++---------- layouts/partials/scripts.html | 2 +- .../en/docs/adding-content/lookandfeel.md | 18 +++ 5 files changed, 120 insertions(+), 159 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0029dc5e0..83867b0a6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,11 @@ For a list of issues targeted for the next release, see the [23Q1][] milestone. **New**: -**Breaking changes**: +- **Click to copy button for Chroma-highlighted code blocks**: If you already + implemented this functionality on your website, you can disable it. More + information on the [Chroma highlighting docs][chroma-docsy]. + +**Breaking changesdocs - **[Upgraded Bootstrap (#470)][470]** to v5. For a list of Bootstrap breaking changes, see the [Bootstrap migration guide][bsv5mig]. Other, Docsy-specific @@ -25,6 +29,8 @@ For a list of issues targeted for the next release, see the [23Q1][] milestone. [1442]: https://github.com/google/docsy/issues/1442 +[chroma-docsy]: https://www.docsy.dev/docs/adding-content/lookandfeel/#code-highlighting-with-chroma + **Other changes**: - Non-breaking changes that result from the Bootstrap v5 upgrade: diff --git a/assets/js/click-to-copy.js b/assets/js/click-to-copy.js index 5fdb041a86..a146b2c90e 100644 --- a/assets/js/click-to-copy.js +++ b/assets/js/click-to-copy.js @@ -1,86 +1,40 @@ -let codeListings = document.querySelectorAll('.highlight > pre'); +let codeListings = document.querySelectorAll(".highlight > pre"); -for (let index = 0; index < codeListings.length; index++) -{ - const codeSample = codeListings[index].querySelector('code'); +for (let index = 0; index < codeListings.length; index++) { + const codeSample = codeListings[index].querySelector("code"); const copyButton = document.createElement("button"); - copyButton.setAttribute('type', 'button'); - copyButton.onclick = function() { copyCode(codeSample); }; - copyButton.classList.add('fas', 'fa-copy'); - - const buttonTooltip = document.createElement('div'); - buttonTooltip.classList.add('c2c-tooltip'); - buttonTooltip.setAttribute('role', 'tooltip'); - buttonTooltip.innerHTML += 'Copy to clipboard'; - - const buttonDiv = document.createElement('div'); - buttonDiv.classList.add('click-to-copy'); - - // Use Popper to create and handle the tooltip behavior. - - const popperInstance = Popper.createPopper(copyButton, buttonTooltip, - { - modifiers: - [ - { - name: 'offset', - options: - { - offset: [0, -48], - }, - }, - ], + const buttonAttributes = { + type: "button", + title: "Copy to clipboard", + "data-bs-toggle": "tooltip", + "data-bs-placement": "top", + "data-bs-container": "body", + }; + + Object.keys(buttonAttributes).forEach((key) => { + copyButton.setAttribute(key, buttonAttributes[key]); }); - copyButton.addEventListener('click', () => - { - buttonTooltip.innerHTML = 'Copied!'; - }); - - copyButton.addEventListener('mouseenter', () => - { - buttonTooltip.setAttribute('show-tooltip', ''); + copyButton.classList.add("fas", "fa-copy", "btn", "btn-dark", "btn-sm"); + const tooltip = new bootstrap.Tooltip(copyButton); - // Enable eventListeners when the code block is on the viewport - - popperInstance.setOptions((options) => ({ - ...options, - modifiers: - [ - ...options.modifiers, - { name: 'eventListeners', enabled: true }, - ], - })); - popperInstance.update(); - }); + copyButton.onclick = () => { + copyCode(codeSample); + copyButton.setAttribute("data-bs-original-title", "Copied!"); + tooltip.show(); + }; - copyButton.addEventListener('mouseleave', () => - { - buttonTooltip.removeAttribute('show-tooltip'); - - // Reset the message in case the button was clicked - buttonTooltip.innerHTML = 'Copy to clipboard'; - - // Disble eventListeners when the code block is NOT on the viewport - - popperInstance.setOptions((options) => ({ - ...options, - modifiers: - [ - ...options.modifiers, - { name: 'eventListeners', enabled: false }, - ], - })); - }); + copyButton.onmouseout = () => { + copyButton.setAttribute("data-bs-original-title", "Copy to clipboard"); + tooltip.hide(); + }; + const buttonDiv = document.createElement("div"); + buttonDiv.classList.add("click-to-copy"); buttonDiv.append(copyButton); - buttonDiv.append(buttonTooltip); codeListings[index].insertBefore(buttonDiv, codeSample); - } -function copyCode(codeSample) -{ +const copyCode = (codeSample) => { navigator.clipboard.writeText(codeSample.textContent.trim()); -} - +}; diff --git a/assets/scss/_code.scss b/assets/scss/_code.scss index b96850bff6..e6f5554934 100644 --- a/assets/scss/_code.scss +++ b/assets/scss/_code.scss @@ -1,101 +1,84 @@ // Code formatting. .td-content { - // Highlighted code. - .highlight { - @extend .card; - - margin: 2rem 0; - padding: 0; - position: relative; + // Highlighted code. + .highlight { + @extend .card; - .click-to-copy { - display: block; - text-align: right; - height: 1ex; - } - - pre { - margin: 0; - padding: 1rem; + margin: 2rem 0; + padding: 0; + position: relative; - // Default click-to-copy button - - button { - position: absolute; - color: $gray-400; - border-radius: 3px; - border-width: 0; - background-color: inherit; - box-shadow: 1px 1px $gray-400; - right: 8px; - top: 6px; + .click-to-copy { + display: block; + text-align: right; + height: 1ex; + } - &:hover { - color: $dark; - background-color: $gray-400; - } - &:active { - color: $dark; - background-color: $gray-400; - transform: translateY(2px); - } - } + pre { + margin: 0; + padding: 1rem; - .c2c-tooltip { - background: $dark; - color: $white; - padding: 2px 4px; - border-radius: 3px; - display: block; - visibility: hidden; - opacity: 0; - transition: visibility 0s, opacity 0.5s linear; - } + // click-to-copy button + button { + position: absolute; + color: $gray-400; + border-radius: 3px; + border-width: 0; + background-color: inherit; + box-shadow: 1px 1px $gray-400; + right: 4px; + top: 2px; - .c2c-tooltip[show-tooltip] { - visibility: visible; - opacity: 1; - } + &:hover { + color: $dark; + background-color: $gray-400; + } + &:active { + color: $dark; + background-color: $gray-400; + transform: translateY(2px); } + } } + } - // Inline code - p code, li > code, table code { - color: inherit; - padding: 0.2em 0.4em; - margin: 0; - font-size: 85%; - word-break: normal; - background-color: rgba($black, 0.05); - border-radius: $border-radius; + // Inline code + p code, + li > code, + table code { + color: inherit; + padding: 0.2em 0.4em; + margin: 0; + font-size: 85%; + word-break: normal; + background-color: rgba($black, 0.05); + border-radius: $border-radius; - br { - display: none; - } + br { + display: none; } + } + // Code blocks + pre { + word-wrap: normal; + background-color: $gray-100; + padding: $spacer; - // Code blocks - pre { - word-wrap: normal; - background-color: $gray-100; - padding: $spacer; - - - > code { - background-color: inherit !important; - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - border: 0; - } + > code { + background-color: inherit !important; + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + border: 0; } + } - pre.mermaid { - background-color: inherit; - font-size: 0; - } + pre.mermaid { + background-color: inherit; + font-size: 0; + } } diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index 8e1d386ceb..e905025e40 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -91,7 +91,7 @@ {{ if .Site.Params.prism_syntax_highlighting -}} -{{ else if false -}} +{{ else if ( not .Site.Params.disable_click2copy_chroma ) -}} {{ $c2cJS := resources.Get "js/click-to-copy.js" -}} {{ if hugo.IsProduction -}} {{ $c2cJS = $c2cJS | minify | fingerprint -}} diff --git a/userguide/content/en/docs/adding-content/lookandfeel.md b/userguide/content/en/docs/adding-content/lookandfeel.md index 4026c98d6c..e491f05d93 100644 --- a/userguide/content/en/docs/adding-content/lookandfeel.md +++ b/userguide/content/en/docs/adding-content/lookandfeel.md @@ -148,6 +148,24 @@ guessSyntax: true {{< /tab >}} {{< /tabpane >}} +If you are using a Docsy version later than `0.6.0`, the code blocks show a +"Copy to clipboard" icon in the top right-hand corner. To disable this +functionality add the `disable_click2copy_chroma` option to your +configuration file, under `params`: + +{{< tabpane persistLang=false >}} +{{< tab header="Configuration file:" disabled=true />}} +{{< tab header="hugo.toml" lang="toml" >}} +disable_click2copy_chroma = true +{{< /tab >}} +{{< tab header="hugo.yaml" lang="yaml" >}} +disable_click2copy_chroma: true +{{< /tab >}} +{{< tab header="hugo.json" lang="json" >}} +"disable_click2copy_chroma": true +{{< /tab >}} +{{< /tabpane >}} + You can find out more about code highlighting in Hugo with Chroma in [Syntax Highlighting](https://gohugo.io/content-management/syntax-highlighting/). ## Code highlighting with Prism