From bf42e4b4e9abcb25fcb1815bc76a63b49e29718a Mon Sep 17 00:00:00 2001 From: Hung Do Date: Tue, 12 Aug 2025 19:43:12 -0400 Subject: [PATCH 1/6] Configured copybutton to strip Python REPL prompts and output when copying --- doc/source/conf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/source/conf.py b/doc/source/conf.py index f222a228531ff..02526f7d04d26 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -461,6 +461,9 @@ # If false, no module index is generated. # latex_use_modindex = True +# Configure copybutton to strip Python REPL prompts and output when copying +copybutton_prompt_text = r">>> |\.\.\.:|In \[\d+\]:?|Out\[\d+\]:?" +copybutton_prompt_is_regexp = True if include_api: intersphinx_mapping = { From b6e757f2d160afa02416ea947b27aa499ecec2ad Mon Sep 17 00:00:00 2001 From: Hung Do Date: Wed, 13 Aug 2025 16:29:55 -0400 Subject: [PATCH 2/6] Attempted to change copy result depending on toggle visibility --- doc/source/_static/js/custom-copy.js | 43 ++++++++++++++++++++++++++++ doc/source/conf.py | 12 ++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 doc/source/_static/js/custom-copy.js diff --git a/doc/source/_static/js/custom-copy.js b/doc/source/_static/js/custom-copy.js new file mode 100644 index 0000000000000..00cc04bcb1081 --- /dev/null +++ b/doc/source/_static/js/custom-copy.js @@ -0,0 +1,43 @@ +document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll(".copybtn").forEach((btn) => { + btn.addEventListener("click", async function (event) { + event.preventDefault(); + + const codeBlock = btn.closest("div.highlight"); + if (!codeBlock) return; + + const clone = codeBlock.cloneNode(true); + + // Remove spans with data-hidden="true" + clone.querySelectorAll("span.copybutton").forEach((el) => { + if (el.getAttribute("data-hidden") === "true") { + el.remove(); + } + }); + + const text = clone.innerText; + + try { + await navigator.clipboard.writeText(text); + console.log("Copied cleaned code to clipboard."); + } catch (err) { + console.warn("Clipboard API failed, using fallback."); + fallbackCopy(text); + } + }); + }); + + function fallbackCopy(text) { + const textarea = document.createElement("textarea"); + textarea.value = text; + document.body.appendChild(textarea); + textarea.select(); + try { + document.execCommand("copy"); + console.log("Copied using fallback."); + } catch (err) { + console.error("Fallback copy failed:", err); + } + document.body.removeChild(textarea); + } +}); diff --git a/doc/source/conf.py b/doc/source/conf.py index 02526f7d04d26..86077070432af 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -57,6 +57,7 @@ "matplotlib.sphinxext.plot_directive", "numpydoc", "sphinx_copybutton", + 'sphinx_toggleprompt', "sphinx_design", "sphinx.ext.autodoc", "sphinx.ext.autosummary", @@ -296,6 +297,10 @@ "css/pandas.css", ] +html_js_files = [ + 'js/custom-copy.js' +] + # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. @@ -462,8 +467,11 @@ # latex_use_modindex = True # Configure copybutton to strip Python REPL prompts and output when copying -copybutton_prompt_text = r">>> |\.\.\.:|In \[\d+\]:?|Out\[\d+\]:?" -copybutton_prompt_is_regexp = True +toggleprompt_prompt_text = r">>> |\.\.\.:|In \[\d+\]:|Out\[\d+\]:" +toggleprompt_is_regexp = True + +copybutton_prompt_text = '' +copybutton_is_regexp = False if include_api: intersphinx_mapping = { From db6fe221066e0e3e3e7dedfa8e85c0eef220ffee Mon Sep 17 00:00:00 2001 From: Hung Do Date: Wed, 13 Aug 2025 16:36:48 -0400 Subject: [PATCH 3/6] Reverted previous JS additions --- doc/source/_static/js/custom-copy.js | 43 ---------------------------- doc/source/conf.py | 8 ++---- 2 files changed, 3 insertions(+), 48 deletions(-) delete mode 100644 doc/source/_static/js/custom-copy.js diff --git a/doc/source/_static/js/custom-copy.js b/doc/source/_static/js/custom-copy.js deleted file mode 100644 index 00cc04bcb1081..0000000000000 --- a/doc/source/_static/js/custom-copy.js +++ /dev/null @@ -1,43 +0,0 @@ -document.addEventListener("DOMContentLoaded", function () { - document.querySelectorAll(".copybtn").forEach((btn) => { - btn.addEventListener("click", async function (event) { - event.preventDefault(); - - const codeBlock = btn.closest("div.highlight"); - if (!codeBlock) return; - - const clone = codeBlock.cloneNode(true); - - // Remove spans with data-hidden="true" - clone.querySelectorAll("span.copybutton").forEach((el) => { - if (el.getAttribute("data-hidden") === "true") { - el.remove(); - } - }); - - const text = clone.innerText; - - try { - await navigator.clipboard.writeText(text); - console.log("Copied cleaned code to clipboard."); - } catch (err) { - console.warn("Clipboard API failed, using fallback."); - fallbackCopy(text); - } - }); - }); - - function fallbackCopy(text) { - const textarea = document.createElement("textarea"); - textarea.value = text; - document.body.appendChild(textarea); - textarea.select(); - try { - document.execCommand("copy"); - console.log("Copied using fallback."); - } catch (err) { - console.error("Fallback copy failed:", err); - } - document.body.removeChild(textarea); - } -}); diff --git a/doc/source/conf.py b/doc/source/conf.py index 86077070432af..b388cc08dbad5 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -466,12 +466,10 @@ # If false, no module index is generated. # latex_use_modindex = True -# Configure copybutton to strip Python REPL prompts and output when copying -toggleprompt_prompt_text = r">>> |\.\.\.:|In \[\d+\]:|Out\[\d+\]:" -toggleprompt_is_regexp = True +# Configure copybutton to strip Python REPL prompts and output when copying code cells +copybutton_prompt_text = r">>> |\.\.\.:|In \[\d+\]:\n?|Out\[\d+\]:\n?" +copybutton_prompt_is_regexp = True -copybutton_prompt_text = '' -copybutton_is_regexp = False if include_api: intersphinx_mapping = { From e8d7be2e26e9e9b15c811c22840f994b3612a686 Mon Sep 17 00:00:00 2001 From: Hung Do Date: Wed, 13 Aug 2025 16:39:15 -0400 Subject: [PATCH 4/6] Added toggleprompt to environment.yml and requirements-dev.txt --- environment.yml | 1 + requirements-dev.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/environment.yml b/environment.yml index 29ce9e8a03446..6960230229c16 100644 --- a/environment.yml +++ b/environment.yml @@ -91,6 +91,7 @@ dependencies: - sphinx - sphinx-design - sphinx-copybutton + - sphinx-toggleprompt - types-python-dateutil - types-PyMySQL - types-pytz diff --git a/requirements-dev.txt b/requirements-dev.txt index ce0ff91b2c8b3..a60a0ba615d75 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -66,6 +66,7 @@ pytest-cython sphinx sphinx-design sphinx-copybutton +sphinx-toggleprompt types-python-dateutil types-PyMySQL types-pytz From ebcaaeeadc2d5ec8888e7b03d7172d55d5cd9f0b Mon Sep 17 00:00:00 2001 From: Hung Do Date: Thu, 14 Aug 2025 16:28:56 -0400 Subject: [PATCH 5/6] Removed reference to js file in conf.py --- doc/source/conf.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index b388cc08dbad5..add7f8f49aeee 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -297,10 +297,6 @@ "css/pandas.css", ] -html_js_files = [ - 'js/custom-copy.js' -] - # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. From d546306b145aa081718c6088882a05445953e17f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:36:19 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index add7f8f49aeee..1ff9c57f10988 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -57,7 +57,7 @@ "matplotlib.sphinxext.plot_directive", "numpydoc", "sphinx_copybutton", - 'sphinx_toggleprompt', + "sphinx_toggleprompt", "sphinx_design", "sphinx.ext.autodoc", "sphinx.ext.autosummary",