diff --git a/CHANGES.rst b/CHANGES.rst index efd076e927..6e99894277 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,6 +16,8 @@ Unreleased deprecation period. :issue:`5815` - ``template_filter``, ``template_test``, and ``template_global`` decorators can be used without parentheses. :issue:`5729` +- Documentation builds now include copy-to-clipboard buttons for code blocks + via ``sphinx-copybutton``. :issue:`5848` Version 3.1.2 diff --git a/docs/conf.py b/docs/conf.py index af8adf0182..621c42d10e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,6 +16,7 @@ "sphinx.ext.autodoc", "sphinx.ext.extlinks", "sphinx.ext.intersphinx", + "sphinx_copybutton", "sphinxcontrib.log_cabinet", "sphinx_tabs.tabs", "pallets_sphinx_themes", @@ -38,6 +39,9 @@ "wtforms": ("https://wtforms.readthedocs.io/", None), "blinker": ("https://blinker.readthedocs.io/", None), } +copybutton_prompt_text = r">>> |\.\.\. |\$ " +copybutton_prompt_is_regexp = True +copybutton_only_copy_prompt_lines = False # HTML ----------------------------------------------------------------- diff --git a/docs/contributing.rst b/docs/contributing.rst index ca4b3aeef4..a64fa42535 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -6,3 +6,81 @@ to contribute, including reporting issues, requesting features, asking or answering questions, and making PRs. .. _contrib: https://palletsprojects.com/contributing/ + +Copy-to-Clipboard Buttons +------------------------- + +The Flask docs are built with Sphinx. Follow the steps below to add a copy +button to every code block by using the ``sphinx-copybutton`` extension. + +.. versionchanged:: 3.2 + Added copy button setup instructions for the documentation build. + +1. Install the extension in your activated virtual environment: + + .. code-block:: console + + (venv) $ pip install sphinx-copybutton + + If you keep documentation dependencies in ``pyproject.toml`` (group + ``docs``) or another requirements file, add ``sphinx-copybutton`` there and + regenerate any lock files (for example ``uv lock``) so other contributors get + the dependency automatically. + +2. Enable the extension in ``docs/conf.py`` by appending it to + ``extensions``: + + .. code-block:: python + + extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.extlinks", + "sphinx.ext.intersphinx", + "sphinx_copybutton", + "sphinxcontrib.log_cabinet", + "sphinx_tabs.tabs", + "pallets_sphinx_themes", + ] + +3. (Optional) Strip interactive prompts from the copied text so readers get + clean commands. Add the following configuration near the bottom of the + general settings in ``docs/conf.py``: + + .. code-block:: python + + copybutton_prompt_text = r">>> |\.\.\. |\$ " + copybutton_prompt_is_regexp = True + copybutton_only_copy_prompt_lines = False + + Tweak ``copybutton_prompt_text`` if your docs use different prompt strings. + +4. Build the documentation locally to confirm everything works: + + .. code-block:: console + + (venv) $ make html + + This runs ``sphinx-build`` via the docs ``Makefile`` and places HTML under + ``docs/_build/html``. Resolve any warnings or errors before committing. + +5. Test the copy button in the generated site. Open the landing page in your + browser (macOS example shown): + + .. code-block:: console + + (venv) $ open docs/_build/html/index.html + + Hover over any code block—each one now shows a copy icon. Click the icon, + paste into a terminal or editor, and verify that prompts such as ``>>>`` and + ``$`` were stripped if you enabled the regex configuration. + +Best Practices +~~~~~~~~~~~~~~ + +* Run ``make clean`` (or delete ``docs/_build``) when you switch branches to + avoid stale artifacts. +* Consider ``SPHINXOPTS=-W make html`` to treat warnings as errors and keep the + docs healthy. +* Use ``sphinx-autobuild`` for faster authoring loops: ``uv run -m sphinx_autobuild docs docs/_build/dirhtml``. +* Preview multiple sections after theme or JavaScript changes to ensure the copy + button renders consistently everywhere. diff --git a/pyproject.toml b/pyproject.toml index 1a4e6bea4a..2929cf8e81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ dev = [ docs = [ "pallets-sphinx-themes", "sphinx", + "sphinx-copybutton", "sphinx-tabs", "sphinxcontrib-log-cabinet", ] diff --git a/tests/test_docs_copybutton.py b/tests/test_docs_copybutton.py new file mode 100644 index 0000000000..47fc822e76 --- /dev/null +++ b/tests/test_docs_copybutton.py @@ -0,0 +1,17 @@ +from pathlib import Path + + +def test_docs_dependency_includes_copybutton() -> None: + """Docs dependency group must install sphinx-copybutton.""" + + text = Path("pyproject.toml").read_text(encoding="utf-8") + assert "sphinx-copybutton" in text + + +def test_docs_conf_enables_copybutton() -> None: + """Sphinx config must enable the extension and prompt stripping.""" + + conf = Path("docs/conf.py").read_text(encoding="utf-8") + assert '"sphinx_copybutton"' in conf + assert "copybutton_prompt_text" in conf +