uv/docs/js/extra.js
eth3lbert 89947681d1
Improve copy of console command examples (#5397)
## Summary

This PR improves the copy of the console command example by:

- Preventing the selection of generic prompts and generic output
- Lazily setting copy content by leveraging intersection observer

Most of the changes are inspired by
https://github.com/opensafely/documentation/pull/1461

Some other useful refs:
- https://github.com/squidfunk/mkdocs-material/issues/3647
-
https://mkdocstrings.github.io/recipes/#prevent-selection-of-prompts-and-output-in-python-code-blocks

Resolves #5355

## Test Plan

- 
  ``` shell-session
  mkdocs serve -f mkdocs.public.yml
  ``` 
- Navigate to http://localhost:8000/uv/first-steps/#viewing-the-version
- Try clicking the copy button
- Try copying by selecting the content

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-07-31 14:52:02 +00:00

53 lines
1.8 KiB
JavaScript

function cleanupClipboardText(targetSelector) {
const targetElement = document.querySelector(targetSelector);
// exclude "Generic Prompt" and "Generic Output" spans from copy
const excludedClasses = ["gp", "go"];
const clipboardText = Array.from(targetElement.childNodes)
.filter(
(node) =>
!excludedClasses.some((className) =>
node?.classList?.contains(className),
),
)
.map((node) => node.textContent)
.filter((s) => s != "");
return clipboardText.join("").trim();
}
// Sets copy text to attributes lazily using an Intersection Observer.
function setCopyText() {
// The `data-clipboard-text` attribute allows for customized content in the copy
// See: https://www.npmjs.com/package/clipboard#copy-text-from-attribute
const attr = "clipboardText";
// all "copy" buttons whose target selector is a <code> element
const elements = document.querySelectorAll(
'button[data-clipboard-target$="code"]',
);
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
// target in the viewport that have not been patched
if (
entry.intersectionRatio > 0 &&
entry.target.dataset[attr] === undefined
) {
entry.target.dataset[attr] = cleanupClipboardText(
entry.target.dataset.clipboardTarget,
);
}
});
});
elements.forEach((elt) => {
observer.observe(elt);
});
}
// Using the document$ observable is particularly important if you are using instant loading since
// it will not result in a page refresh in the browser
// See `How to integrate with third-party JavaScript libraries` guideline:
// https://squidfunk.github.io/mkdocs-material/customization/?h=javascript#additional-javascript
document$.subscribe(function () {
setCopyText();
});