Skip to content

Commit

Permalink
Refactor Click-to-copy with Bootstrap5
Browse files Browse the repository at this point in the history
Refactor of PR #1245. Bootstrap5-compatible code.
  • Loading branch information
geriom committed Feb 28, 2023
1 parent 36c7405 commit c67788e
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 159 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,6 +25,8 @@ For a list of issues targeted for the next release, see the [23Q1][] milestone.
- Dropped `$primary-light`.
- Dropped `color-diff()`.

[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:
Expand Down
102 changes: 28 additions & 74 deletions assets/js/click-to-copy.js
Original file line number Diff line number Diff line change
@@ -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());
}

};
149 changes: 66 additions & 83 deletions assets/scss/_code.scss
Original file line number Diff line number Diff line change
@@ -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;
}
}
2 changes: 1 addition & 1 deletion layouts/partials/scripts.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

{{ if .Site.Params.prism_syntax_highlighting -}}
<script src='{{ "js/prism.js" | relURL }}'></script>
{{ 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 -}}
Expand Down
18 changes: 18 additions & 0 deletions userguide/content/en/docs/adding-content/lookandfeel.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit c67788e

Please sign in to comment.