diff --git a/docs_theme/css/copy-button.css b/docs_theme/css/copy-button.css new file mode 100644 index 0000000000..589ec95979 --- /dev/null +++ b/docs_theme/css/copy-button.css @@ -0,0 +1,30 @@ +.copy-block-button { + position: absolute; + top: 6px; + right: 6px; + z-index: 10; + white-space: nowrap; /* Prevent text wrap */ +} + +/* Ensure the PRE container provides positioning context */ +pre { + position: relative; + padding-top: 35px; /* Room for the button */ + overflow-x: auto; /* Allow horizontal scrolling */ +} + +/* Code block scrollable */ +pre code { + display: block; + overflow-x: auto; +} + +/* + The MkDocs/DRF theme injects a inside buttons and applies + a text color that overrides btn-inverse defaults. + This override is intentionally scoped and limited to color only. +*/ +.copy-block-button, +.copy-block-button span { + color: #ffffff !important; +} diff --git a/docs_theme/js/copy-button.js b/docs_theme/js/copy-button.js new file mode 100644 index 0000000000..667460c8be --- /dev/null +++ b/docs_theme/js/copy-button.js @@ -0,0 +1,24 @@ +document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll("pre > code").forEach(function (codeBlock) { + const button = document.createElement("button"); + button.className = "copy-block-button btn btn-inverse btn-small"; + button.type = "button"; + button.textContent = "Copy"; + + button.addEventListener("click", function () { + navigator.clipboard.writeText(codeBlock.textContent) + .then(() => { + button.textContent = "Copied!"; + setTimeout(() => button.textContent = "Copy", 1200); + }) + .catch(() => { + button.textContent = "Failed"; + setTimeout(() => button.textContent = "Copy", 1200); + }); + }); + + const pre = codeBlock.parentNode; + pre.style.position = "relative"; + pre.appendChild(button); + }); +}); diff --git a/docs_theme/main.html b/docs_theme/main.html index e373095955..a584f95393 100644 --- a/docs_theme/main.html +++ b/docs_theme/main.html @@ -16,6 +16,9 @@ + {% for path in config.extra_css %} + + {% endfor %}