From d40259681fd4711f25d364571a497def207ec473 Mon Sep 17 00:00:00 2001 From: Tim Monko Date: Tue, 19 May 2026 11:37:48 -0500 Subject: [PATCH 1/6] imrpove language of gallery landing page --- docs/gallery.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/gallery.md b/docs/gallery.md index c14dfa8a4..961d8d394 100644 --- a/docs/gallery.md +++ b/docs/gallery.md @@ -4,9 +4,17 @@ Examples of napari usage. -All examples in this gallery can be downloaded as Python scripts or Jupyter -notebooks to be executed locally. Check out [](launch-jupyter) for more details -on using napari in Jupyter notebooks. +Each example page includes downloads for both the source `.py` file and a +generated Jupyter notebook. If you download the Python script, you can run it +with `napari path/to/my_example.py` or drag the `.py` file onto a running napari viewer +to execute it there. Some examples may require additional dependencies beyond +napari itself, so be sure to check the example's source code for any additional +requirements if you see an error when trying to run it. +Check out [](launch-jupyter) for more details on using +napari in Jupyter notebooks. + +Use the tag index below to browse examples by topic, or jump straight into the +gallery grid. ```{note} From 431c86946be733389e7995c45e8e0c2bd8056f18 Mon Sep 17 00:00:00 2001 From: Tim Monko Date: Tue, 19 May 2026 11:38:13 -0500 Subject: [PATCH 2/6] WIP initial LLM working strategy --- docs/_static/custom.css | 27 +++++++++++++++++ docs/conf.py | 64 +++++++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/docs/_static/custom.css b/docs/_static/custom.css index e5c50e450..918057251 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -44,6 +44,33 @@ html[data-theme="dark"] div.sphx-glr-download a:hover { background-color: #222832 !important; } +.napari-gallery-downloads { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 0 0 1.25rem; +} + +.napari-gallery-downloads .sphx-glr-download { + margin: 0; +} + +html[data-theme="light"] .napari-gallery-downloads div.sphx-glr-download a { + border-color: #d7deea !important; +} + +html[data-theme="dark"] .napari-gallery-downloads div.sphx-glr-download a { + border-color: #4f5f79 !important; + color: #fff; +} + +.sphx-glr-download-link-note, +.sphx-glr-download-jupyter, +.sphx-glr-download-python, +.sphx-glr-download-zip { + display: none; +} + /* Version warning banner color */ #bd-header-version-warning { background-color: color-mix(in srgb, var(--pst-color-secondary-bg), transparent 30%); diff --git a/docs/conf.py b/docs/conf.py index 569b5b0da..362b9bf76 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -396,6 +396,60 @@ def napari_scraper(block, block_vars, gallery_conf): return scrapers.figure_rst(img_paths, gallery_conf['src_dir']) +GALLERY_DOWNLOAD_NOTE_RE = re.compile( + r'\n\.\. only:: html\n\n' + r' \.\. note::\n' + r' :class: sphx-glr-download-link-note\n\n' + r' :ref:`Go to the end ]+>`\n' + r' to download the full example as a Python script or as a\n' + r' Jupyter notebook\.\.?\n', + re.MULTILINE, +) +GALLERY_TITLE_RE = re.compile(r'^(?P.+\n=+\n)', re.MULTILINE) + + +def add_gallery_download_buttons(app, docname, source): + """Add compact top-of-page download links to generated gallery examples.""" + if not docname.startswith('gallery/'): + return + if docname.endswith('/index') or docname.endswith('sg_execution_times'): + return + + content = source[0] + if 'THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.' not in content: + return + + content = GALLERY_DOWNLOAD_NOTE_RE.sub('\n', content, count=1) + if 'napari-gallery-downloads' in content: + source[0] = content + return + + example_name = Path(docname).name + title_match = GALLERY_TITLE_RE.search(content) + if title_match is None: + source[0] = content + return + + download_block = f""" +.. only:: html + + .. container:: napari-gallery-downloads + + .. container:: sphx-glr-download + + :download:`Python (.py) <{example_name}.py>` + + .. container:: sphx-glr-download + + :download:`Notebook (.ipynb) <{example_name}.ipynb>` +""" + source[0] = ( + content[: title_match.end()] + + download_block + + content[title_match.end() :] + ) + + gen_rst.EXAMPLE_HEADER = """ .. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. @@ -403,15 +457,6 @@ def napari_scraper(block, block_vars, gallery_conf): .. "{0}" .. LINE NUMBERS ARE GIVEN BELOW. -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end <sphx_glr_download_{1}>` - to download the full example as a Python script or as a - Jupyter notebook.{2} - .. rst-class:: sphx-glr-example-title .. _sphx_glr_{1}: @@ -549,6 +594,7 @@ def setup(app): """ app.registry.source_suffix.pop('.ipynb', None) app.connect('source-read', add_google_calendar_secrets) + app.connect('source-read', add_gallery_download_buttons) app.connect('linkcheck-process-uri', rewrite_github_anchor) app.connect('autodoc-process-docstring', qt_docstrings) From fc1477b4f50d9d120329e7389d4c873b2f1ce27f Mon Sep 17 00:00:00 2001 From: Tim Monko <timmonko@gmail.com> Date: Tue, 19 May 2026 12:13:29 -0500 Subject: [PATCH 3/6] simplify imlpementation and css --- docs/_static/custom.css | 9 --------- docs/conf.py | 24 +++++++----------------- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 918057251..0eed907b2 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -55,15 +55,6 @@ html[data-theme="dark"] div.sphx-glr-download a:hover { margin: 0; } -html[data-theme="light"] .napari-gallery-downloads div.sphx-glr-download a { - border-color: #d7deea !important; -} - -html[data-theme="dark"] .napari-gallery-downloads div.sphx-glr-download a { - border-color: #4f5f79 !important; - color: #fff; -} - .sphx-glr-download-link-note, .sphx-glr-download-jupyter, .sphx-glr-download-python, diff --git a/docs/conf.py b/docs/conf.py index 362b9bf76..43b7cdf72 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -396,20 +396,16 @@ def napari_scraper(block, block_vars, gallery_conf): return scrapers.figure_rst(img_paths, gallery_conf['src_dir']) -GALLERY_DOWNLOAD_NOTE_RE = re.compile( - r'\n\.\. only:: html\n\n' - r' \.\. note::\n' - r' :class: sphx-glr-download-link-note\n\n' - r' :ref:`Go to the end <sphx_glr_download_[^>]+>`\n' - r' to download the full example as a Python script or as a\n' - r' Jupyter notebook\.\.?\n', - re.MULTILINE, -) -GALLERY_TITLE_RE = re.compile(r'^(?P<title>.+\n=+\n)', re.MULTILINE) +GALLERY_TITLE_RE = re.compile(r'^.+\n=+\n', re.MULTILINE) def add_gallery_download_buttons(app, docname, source): - """Add compact top-of-page download links to generated gallery examples.""" + """Add compact top-of-page download links to generated gallery examples. + + The title of the example is used to determine where to insert the download links, + which are only added to generated gallery examples. + The links are added after the title. + """ if not docname.startswith('gallery/'): return if docname.endswith('/index') or docname.endswith('sg_execution_times'): @@ -419,15 +415,9 @@ def add_gallery_download_buttons(app, docname, source): if 'THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.' not in content: return - content = GALLERY_DOWNLOAD_NOTE_RE.sub('\n', content, count=1) - if 'napari-gallery-downloads' in content: - source[0] = content - return - example_name = Path(docname).name title_match = GALLERY_TITLE_RE.search(content) if title_match is None: - source[0] = content return download_block = f""" From a036fec20b538863db370b43dab3c93516057351 Mon Sep 17 00:00:00 2001 From: Tim Monko <timmonko@gmail.com> Date: Wed, 20 May 2026 15:00:03 -0500 Subject: [PATCH 4/6] update with #1026 css logic --- docs/_static/custom.css | 135 +++++++++++++++++++++------------------- docs/index.md | 6 +- 2 files changed, 74 insertions(+), 67 deletions(-) diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 0eed907b2..87a94abb8 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -1,60 +1,45 @@ -/* -Sphinx-Gallery has compatible CSS to fix default sphinx themes -Tested for Sphinx 1.3.1 for all themes: default, alabaster, sphinxdoc, -scrolls, agogo, traditional, nature, haiku, pyramid -Tested for Read the Docs theme 0.1.7 */ - -html[data-theme="light"] div.sphx-glr-download a { - background-color: rgb(255, 255, 255) !important; - background-image: linear-gradient(to bottom, rgb(255, 255, 255), #ffffff) !important; +/* ── Buttons for homepage and gallery ───────────────────────────────────── */ + +.button-primary, +.button-alt, +.napari-gallery-downloads .sphx-glr-download a { + background-image: none !important; border-radius: 4px; - border: 1px solid #ffffff !important; - color: #000; - display: inline-block; - font-weight: bold; - padding: 1ex; text-align: center; + text-decoration: none; } -html[data-theme="light"] div.sphx-glr-download a:hover { - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), - 0 1px 5px rgba(0, 0, 0, 0.25); - text-decoration: none; - background-image: none; - background-color: #ffffff !important; +/* makes homepage button take up width of column */ +.button-primary { + display: block; } -html[data-theme="dark"] div.sphx-glr-download a { - background-color: #222832 !important; - background-image: linear-gradient(to bottom, #222832, #222832) !important; - border-radius: 4px; - border: 1px solid #222832 !important; - color: #000; +/* Allow border override to show through on example buttons */ +.napari-gallery-downloads .sphx-glr-download a { + border: 1px solid transparent; display: inline-block; - font-weight: bold; - padding: 1ex; - text-align: center; + padding: 0.45rem 0.8rem; } -html[data-theme="dark"] div.sphx-glr-download a:hover { - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), - 0 1px 5px rgba(0, 0, 0, 0.25); - text-decoration: none; - background-image: none; - background-color: #222832 !important; +/* force sphinx-gallery download code to inherit text color */ +.napari-gallery-downloads .sphx-glr-download a code.download { + color: inherit !important; } +/* horizontally align and reduce lower margin of container */ .napari-gallery-downloads { display: flex; flex-wrap: wrap; - gap: 0.5rem; - margin: 0 0 1.25rem; + gap: 0.375rem; + margin: 0 0 0.35rem; } +/* remove spacing around download buttons */ .napari-gallery-downloads .sphx-glr-download { margin: 0; } +/* Remove the sphinx-gallery downloads note and buttons */ .sphx-glr-download-link-note, .sphx-glr-download-jupyter, .sphx-glr-download-python, @@ -62,53 +47,75 @@ html[data-theme="dark"] div.sphx-glr-download a:hover { display: none; } -/* Version warning banner color */ -#bd-header-version-warning { - background-color: color-mix(in srgb, var(--pst-color-secondary-bg), transparent 30%); +html[data-theme="light"] .button-primary, +html[data-theme="light"] .napari-gallery-downloads .sphx-glr-download a { + background-color: var(--napari-primary-blue) !important; + border-color: var(--napari-primary-blue) !important; + color: var(--napari-color-text-base) !important; } -#bd-header-version-warning .pst-button-link-to-stable-version { - background-color: color-mix(in srgb, var(--pst-color-secondary-bg), transparent 0%); - border-color: var(--pst-color-secondary-bg); - color: var(--napari-color-text-base); - font-weight: 700; +html[data-theme="dark"] .button-primary, +html[data-theme="dark"] .napari-gallery-downloads .sphx-glr-download a { + background-color: var(--napari-purple) !important; + border-color: var(--napari-purple) !important; + color: var(--napari-color-text-base) !important; } -#bd-header-version-warning .pst-button-link-to-stable-version:hover { - background-color: var(--pst-color-secondary-bg); - border-color: var(--pst-color-secondary-bg); - color: var(--napari-color-text-base); - font-weight: 700; +html[data-theme="light"] .button-primary:hover, +html[data-theme="light"] .napari-gallery-downloads .sphx-glr-download a:hover { + background-color: color-mix(in srgb, var(--napari-primary-blue), transparent 25%) !important; + text-decoration: underline; } -/* ── Homepage accent cards ─────────────────────────────────────────── - Install, Download cards with theme-aware napari blue. - sphinx-design marks every property !important, so we must too. */ - -.homepage-button { - display: block; +html[data-theme="dark"] .button-primary:hover, +html[data-theme="dark"] .napari-gallery-downloads .sphx-glr-download a:hover { + background-color: color-mix(in srgb, var(--napari-purple), transparent 25%) !important; + text-decoration: underline; } -html[data-theme="light"] .homepage-button { - background-color: var(--napari-primary-blue) !important; +html[data-theme="light"] .button-alt { + background-color: var(--pst-color-background) !important; border-color: var(--napari-primary-blue) !important; color: var(--napari-color-text-base) !important; } -html[data-theme="dark"] .homepage-button { - background-color: var(--napari-purple) !important; +html[data-theme="dark"] .button-alt { + background-color: var(--pst-color-background) !important; border-color: var(--napari-purple) !important; color: var(--napari-color-text-base) !important; } -html[data-theme="light"] .homepage-button:hover { +html[data-theme="light"] .button-alt:hover { + background-color: var(--pst-color-background) !important; + border-color: var(--napari-primary-blue) !important; + color: var(--napari-color-text-base) !important; text-decoration: underline; - background-color: color-mix(in srgb, var(--napari-primary-blue), transparent 25%) !important; } -html[data-theme="dark"] .homepage-button:hover { +html[data-theme="dark"] .button-alt:hover { + background-color: var(--pst-color-background) !important; + border-color: var(--napari-purple) !important; + color: var(--napari-color-text-base) !important; text-decoration: underline; - background-color: color-mix(in srgb, var(--napari-purple), transparent 25%) !important; +} + +/* Version warning banner color */ +#bd-header-version-warning { + background-color: color-mix(in srgb, var(--pst-color-secondary-bg), transparent 30%); +} + +#bd-header-version-warning .pst-button-link-to-stable-version { + background-color: color-mix(in srgb, var(--pst-color-secondary-bg), transparent 0%); + border-color: var(--pst-color-secondary-bg); + color: var(--napari-color-text-base); + font-weight: 700; +} + +#bd-header-version-warning .pst-button-link-to-stable-version:hover { + background-color: var(--pst-color-secondary-bg); + border-color: var(--pst-color-secondary-bg); + color: var(--napari-color-text-base); + font-weight: 700; } /* ── Homepage quicklinks (icon columns) ──────────────────────────────── */ diff --git a/docs/index.md b/docs/index.md index b775ffabb..aa3935234 100644 --- a/docs/index.md +++ b/docs/index.md @@ -64,7 +64,7 @@ theme: :color: primary :ref-type: myst :shadow: -:class: homepage-button +:class: button-primary {material-regular}`arrow_forward;1.2em` **Get started** ``` @@ -133,8 +133,8 @@ A standalone installer for when you want napari without setting up Python first. Display an image in napari and explore the viewer with a minimal example. </p> <div class="homepage-featured-example__actions"> - <a class="sd-btn sd-btn-primary sd-shadow-sm homepage-button" href="gallery.html">Examples gallery</a> - <button class="sd-btn sd-btn-outline-primary sd-shadow-sm homepage-example-button" id="homepage-featured-example-reroll" type="button">Show another example</button> + <a class="sd-btn sd-btn-primary sd-shadow-sm button-primary" href="gallery.html">Examples gallery</a> + <button class="sd-btn sd-btn-outline-primary sd-shadow-sm button-alt" id="homepage-featured-example-reroll" type="button">Show another example</button> </div> </div> <a class="homepage-featured-example__media" href="gallery/add_image.html" aria-label="View the featured napari example"> From fb920a52f73c0d60cee93ca70094ef492363274e Mon Sep 17 00:00:00 2001 From: Tim Monko <timmonko@gmail.com> Date: Wed, 20 May 2026 15:15:37 -0500 Subject: [PATCH 5/6] remove vestigial css --- docs/_static/custom.css | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 87a94abb8..0070f87e3 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -248,8 +248,3 @@ html[data-theme="dark"] .homepage-quicklinks a { html[data-theme="dark"] img#homepage-featured-example-image { background-color: var(--pst-color-background) !important; } - -.homepage-example-button:hover { - background-color: var(--pst-color-background) !important; - color: var(--napari-color-text-base) !important; -} \ No newline at end of file From ad0639dd1f9854a13b540e2cc1dfc106db4928d7 Mon Sep 17 00:00:00 2001 From: Tim Monko <timmonko@gmail.com> Date: Tue, 26 May 2026 23:26:24 -0500 Subject: [PATCH 6/6] add buttons just before python script --- docs/conf.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 43b7cdf72..581ae0907 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -396,15 +396,18 @@ def napari_scraper(block, block_vars, gallery_conf): return scrapers.figure_rst(img_paths, gallery_conf['src_dir']) -GALLERY_TITLE_RE = re.compile(r'^.+\n=+\n', re.MULTILINE) +GALLERY_METADATA_END_RE = re.compile( + r'^\.\. GENERATED FROM PYTHON SOURCE LINES \d+-\d+\s*$', re.MULTILINE +) def add_gallery_download_buttons(app, docname, source): - """Add compact top-of-page download links to generated gallery examples. - - The title of the example is used to determine where to insert the download links, - which are only added to generated gallery examples. - The links are added after the title. + """Add compact download links near the top of generated gallery examples. + + Sphinx-Gallery emits the example title first, followed by the short + description and tags, and only then the ``GENERATED FROM PYTHON SOURCE`` + marker. Insert the links just before that first marker so they stay below + the description metadata without overriding Sphinx-Gallery templates. """ if not docname.startswith('gallery/'): return @@ -416,8 +419,8 @@ def add_gallery_download_buttons(app, docname, source): return example_name = Path(docname).name - title_match = GALLERY_TITLE_RE.search(content) - if title_match is None: + metadata_end_match = GALLERY_METADATA_END_RE.search(content) + if metadata_end_match is None: return download_block = f""" @@ -434,9 +437,9 @@ def add_gallery_download_buttons(app, docname, source): :download:`Notebook (.ipynb) <{example_name}.ipynb>` """ source[0] = ( - content[: title_match.end()] + content[: metadata_end_match.start()] + download_block - + content[title_match.end() :] + + content[metadata_end_match.start() :] )