diff --git a/doc/api_assets/api.js b/doc/api_assets/api.js
index 49906b1a2abab5..c1151ae493e8da 100644
--- a/doc/api_assets/api.js
+++ b/doc/api_assets/api.js
@@ -136,6 +136,36 @@
updateHashes();
}
+ function setupCopyButton() {
+ const buttons = document.querySelectorAll('.copy-button');
+ buttons.forEach((button) => {
+ button.addEventListener('click', (el) => {
+ const parentNode = el.target.parentNode;
+
+ const flavorSelector = parentNode.querySelector('.js-flavor-selector');
+
+ let code = '';
+
+ if (flavorSelector) {
+ if (flavorSelector.checked) {
+ code = parentNode.querySelector('.mjs').textContent;
+ } else {
+ code = parentNode.querySelector('.cjs').textContent;
+ }
+ } else {
+ code = parentNode.querySelector('code').textContent;
+ }
+
+ button.textContent = 'Copied';
+ navigator.clipboard.writeText(code);
+
+ setTimeout(() => {
+ button.textContent = 'Copy';
+ }, 2500);
+ });
+ });
+ }
+
function bootstrap() {
// Check if we have JavaScript support.
document.documentElement.classList.add('has-js');
@@ -151,6 +181,8 @@
// Make link to other versions of the doc open to the same hash target (if it exists).
setupAltDocsLink();
+
+ setupCopyButton();
}
if (document.readyState === 'loading') {
diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css
index 42126949d55d5c..6b27fa1fb71b94 100644
--- a/doc/api_assets/style.css
+++ b/doc/api_assets/style.css
@@ -973,6 +973,33 @@ kbd {
.dark-mode .js-flavor-selector {
filter: invert(1);
}
+
+.copy-button {
+ float: right;
+
+ outline: none;
+ font-size: 10px;
+ color: #fff;
+ background-color: var(--green1);
+ line-height: 1;
+ border-radius: 500px;
+ border: 1px solid transparent;
+ letter-spacing: 2px;
+ min-width: 7.5rem;
+ text-transform: uppercase;
+ font-weight: 700;
+ padding: 0 .5rem;
+ margin-right: .2rem;
+ height: 1.5rem;
+ transition-property: background-color,border-color,color,box-shadow,filter;
+ transition-duration: .3s;
+ cursor: pointer;
+}
+
+.copy-button:hover {
+ background-color: var(--green2);
+}
+
@supports (aspect-ratio: 1 / 1) {
.js-flavor-selector {
height: 1.5em;
diff --git a/tools/doc/html.mjs b/tools/doc/html.mjs
index 339a48ce762c44..8e6bfe6a89aede 100644
--- a/tools/doc/html.mjs
+++ b/tools/doc/html.mjs
@@ -226,10 +226,13 @@ export function preprocessElements({ filename }) {
const className = isJSFlavorSnippet(node) ?
`language-js ${node.lang}` :
`language-${node.lang}`;
+
const highlighted =
`${(getLanguage(node.lang || '') ? highlight(node.value, { language: node.lang }) : node).value}
`;
node.type = 'html';
+ const copyButton = '';
+
if (isJSFlavorSnippet(node)) {
const previousNode = parent.children[index - 1] || {};
const nextNode = parent.children[index + 1] || {};
@@ -253,16 +256,17 @@ export function preprocessElements({ filename }) {
' aria-label="Show modern ES modules syntax">' +
previousNode.value +
highlighted +
+ copyButton +
'';
node.lang = null;
previousNode.value = '';
previousNode.lang = null;
} else {
// Isolated JS snippet, no need to add the checkbox.
- node.value = `
${highlighted}`; + node.value = `
${highlighted} ${copyButton}`; } } else { - node.value = `
${highlighted}`; + node.value = `
${highlighted} ${copyButton}`; } } else if (node.type === 'html' && common.isYAMLBlock(node.value)) { node.value = parseYAML(node.value);