Skip to content

Replace sphinx-inline-tabs/sphinx-design with first-party UX packages#38

Draft
tony wants to merge 11 commits into
mainfrom
gp-sphinx-design
Draft

Replace sphinx-inline-tabs/sphinx-design with first-party UX packages#38
tony wants to merge 11 commits into
mainfrom
gp-sphinx-design

Conversation

@tony
Copy link
Copy Markdown
Member

@tony tony commented May 17, 2026

gp-sphinx no longer depends on sphinx-inline-tabs or sphinx-design. Four first-party packages now own the directives and roles previously provided by those upstreams, all styled under the gp-sphinx-* CSS namespace and integrated with the workspace's Tailwind v4 + @layer gp-sphinx cascade. The authoring surface in source docs (RST and MyST) is unchanged — every directive and role keeps its name and option spec, so downstream consumers need no source edits. The tabs package was further polished to full feature parity with both upstreams (localStorage persistence, URL deep-links, prehydrate to eliminate flash-of-wrong-selection) and restyled to the visual quality of the libtmux-mcp installer widget.

Summary

  • Add sphinx-ux-tabs.. tab:: (with :new-set:), .. tab-set::, .. tab-item::. Drop-in for both sphinx-inline-tabs and sphinx-design's tab directives, with SPA-aware sync JS, localStorage persistence, URL-based deep-links, and a gp-sphinx-tabs--large size modifier.
  • Add sphinx-ux-grid.. grid:: / .. grid-item:: / .. grid-item-card:: with CSS Grid layout and breakpoint custom-property overrides.
  • Add sphinx-ux-octicons{octicon} role with a curated bundle of icons gp-sphinx actually uses, inlined as SVG.
  • Extend sphinx-ux-badges — adds the {bdg-*} MyST role family (11 colors × filled/outline) routed to the existing BadgeNode, including semantic color triples with dark-mode overrides.
  • Replace sphinx_inline_tabs and sphinx_design in DEFAULT_EXTENSIONS with the four first-party packages, in a single commit so directive registration is never order-ambiguous.
  • Guard against accidental re-introduction: merge_sphinx_config raises ExtensionError if a downstream extra_extensions reinstates a legacy name alongside its first-party replacement.
  • Remove the remove_tabs_js post-build workaround that deleted _static/tabs.js after every build, along with the sphinx_inline_tabs._impl warning filter and the legacy dependencies from pyproject.toml.
  • Document every new package with the full Diátaxis subpage set (tutorial / how-to / reference / explanation / examples / dependents) auto-discovered by the {package-landing} directive.

Packages introduced

Package Charter
sphinx-ux-octicons {octicon} role, curated 18-icon JSON bundle, inline SVG render
sphinx-ux-grid .. grid::, .. grid-item::, .. grid-item-card:: with sphinx-design-parity option set
sphinx-ux-tabs .. tab:: (:new-set:), .. tab-set::, .. tab-item::, two-pass post-transform, localStorage sync, URL deep-links, prehydrate
sphinx-ux-badges (extended) {bdg-primary|secondary|success|info|warning|danger|light|muted|dark|white|black} and -line outline variants

All four follow the existing workspace package shape (pre-built static CSS under _static/css/, setup(app) registering nodes via app.add_node(..., html=(visit, depart)), builder-inited callback appending the package's _static/ to html_static_path). None requires sphinx-vite-builder — Vite stays scoped to the theme package.

Authoring surface preserved

Source feature Before After
Inline-style tabs .. tab:: Label / :new-set: unchanged
Tab-set + items :::{tab-set} / :::{tab-item} unchanged
Responsive grid :::{grid} 1 2 3 4 unchanged
Card in grid :::{grid-item-card} unchanged
Inline badge {bdg-primary}\`Alpha\` unchanged
Inline icon {octicon}\`rocket\` unchanged

Rendered output uses the gp-sphinx-* CSS namespace exclusively. The radio-button HTML structure for tabs is identical in shape; classes are renamed (sd-tab-*gp-sphinx-tabs__*, sd-cardgp-sphinx-grid-card, sd-badgegp-sphinx-badge, etc.).

New capabilities beyond the migration

Tabs

  • :class: gp-sphinx-tabs--large modifier — opt into the larger size variant (body-size labels, roomier padding) suitable for callout sections, feature-comparison tables, and landing-page hero tabs. Default size matches the prior compact rendering.
  • localStorage persistence under gp-sphinx-tabs.sync.<group> — a user's tab choice survives page reloads and SPA navigation.
  • URL deep-links?tabs=Label (sphinx-inline-tabs idiom) and ?<group>=<id> (sphinx-design idiom) both pre-select tabs on first paint, write through to localStorage. URL takes precedence on first paint; subsequent SPA-nav events read from localStorage only.
  • Prehydrate — an inline <head> <script data-cfasync="false"> (Cloudflare Rocket Loader compatible) plus @layer gp-sphinx-tabs-prehydrate CSS paints the saved tab on the first frame, eliminating flash-of-wrong-selection. Gated to pages with sync'd tabs only.
  • :class-container: option on {tab-item} — completes the sphinx-design option parity (alongside :class-label: and :class-content:).
  • Restyled to use Furo theme tokens directly (var(--color-*)), color-mix background tints, :focus-visible outlines, brand-primary active state.

Design decisions

Single atomic flip of DEFAULT_EXTENSIONS. Sphinx directive registration is last-registered-wins. A release with both old and new extensions in the default list would have order-dependent runtime behavior. The flip and the four new package landings are sequenced so each commit leaves the workspace buildable, and the cutover happens in one commit.

nodes.container for grid/card, custom nodes for tabs. Grid layout is decoration — nodes.container plus class names degrades cleanly to LaTeX/text/man builders. Tab rendering needs the radio-button HTML structure that no default visitor produces, so it's worth five custom nodes (TabContainer, TabSetNode, TabItemNode, TabInputNode, TabLabelNode) and a two-pass post-transform.

Breakpoint values as inline custom properties. Grid breakpoint columns/gutter/margin/padding land as style="--gp-sphinx-grid-cols-xs: 1; ..." on the container. The static CSS file has a finite set of rules consuming the custom properties, regardless of how many grid directives appear in the docs.

Custom :class: parser on {tab-set}. docutils' directives.class_option collapses -- to -, so the BEM modifier gp-sphinx-tabs--large cannot survive a round-trip through the standard parser. sphinx-ux-tabs ships a scoped _raw_class_option that splits on whitespace and keeps tokens verbatim, narrowly applied to TabSetDirective's :class: option.

Curated icon bundle, not the full Octicons set. Bundling only the ~18 icons gp-sphinx actually uses keeps the wheel small. A maintainer-only scripts/sync_octicons.py regenerates the JSON from upstream @primer/octicons when the curated set changes.

Borrowed prehydrate pattern, not a generic package. libtmux-mcp's {mcp-install} widget pioneered the inline-<head>-script-plus-@layer-CSS approach to prevent flash-of-wrong-selection on SPA navigation. The pattern applies cleanly to tabs; the mechanism (env walker + html-page-context hook + JSON-encoded script payload) is duplicated inside sphinx-ux-tabs/_prehydrate.py rather than extracted into a shared package — single-consumer abstraction would have required parametrizing storage-key namespaces and selector generators, work that is not justified until a second consumer appears.

Migration guardrail rather than silent override. Downstream consumers who explicitly re-add sphinx_design or sphinx_inline_tabs via merge_sphinx_config(..., extra_extensions=[...]) get an ExtensionError naming the legacy extension and its replacement. Single error reports all collisions at once.

Verification

No sd-* classes remain in the rendered docs:

```console
$ rm -rf docs/_build && just build-docs && rg -n 'sd-(badge|card|tab|grid|row|col)\b' docs/_build/html/
```

No references to the dropped extensions remain in the workspace:

```console
$ rg -n 'sphinx_-' --type-add 'allcode:*.{py,toml,md,yaml,yml,json}' -t allcode | grep -v 'drop-in|replacement|_LEGACY_EXTENSION_REPLACEMENTS|ecosystem context'
```

The remove_tabs_js workaround is gone:

```console
$ rg -n 'remove_tabs_js|tabs.js' packages/ tests/
```

Neither legacy package is installed:

```console
$ uv pip list | grep -iE 'sphinx-?(inline|design)'
```

The first-party packages own the directives at runtime:

```console
$ rg -n 'gp-sphinx-(badge|grid-card|octicon|tabs)' docs/_build/html/index.html
```

Prehydrate emits when sync'd tabs are present, and only then:

```console
$ rg -n 'gp-sphinx-tabs-prehydrate' docs/_build/html/packages/sphinx-ux-tabs/examples/index.html
$ rg -n 'gp-sphinx-tabs-prehydrate' docs/_build/html/packages/sphinx-ux-octicons/index.html
```

Test plan

  • `uv run ruff check . --fix --show-fixes` — workspace lint clean
  • `uv run ruff format .` — workspace format clean
  • `uv run mypy` — type checks pass across the four new packages and existing code
  • `uv run py.test --reruns 0 -vvv` — full suite passes, including pure-node tests, post-transform unit tests, prehydrate generator tests, and integration builds for each new package
  • `just build-docs` — docs build with zero warnings (down from the prior baseline where sphinx-inline-tabs deprecation and sphinx-design `{bdg-*}` collisions emitted warnings)
  • `tests/ext/octicons/test_integration.py` — verifies HTML emits SVG only (no trailing icon-name text leak) and text builder emits the icon name as fallback
  • `tests/ext/grid/test_integration.py` — verifies `{grid-item-card}` with `:link-type: doc` resolves to an internal href
  • `tests/ext/tabs/test_integration.py` — verifies both RST `.. tab::` (grouping) and MyST `:::{tab-set}`/`:::{tab-item}` (nesting) styles render the same radio-button HTML structure
  • `tests/ext/tabs/test_post_transform_expansion.py` — verifies `:sync-group:`/`:sync:`/`:name:`/`:class-container:` all survive expansion and reach the rendered HTML
  • `tests/ext/tabs/test_prehydrate.py` — verifies the prehydrate generator output and the gated empty-set short-circuit
  • `tests/ext/badges/test_badges.py` — verifies all 22 `{bdg-*}` roles register and produce the expected class set on `BadgeNode`
  • `tests/test_config.py` — verifies `merge_sphinx_config` raises `ExtensionError` when a legacy extension is re-introduced alongside its replacement, and reports all collisions in a single error
  • Manual: deep-link `?example=rust` on `/packages/sphinx-ux-tabs/examples/` pre-selects the Rust tab before first paint (prehydrate)
  • Manual: tab choice persists via localStorage across SPA navigation and full reloads

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.84478% with 62 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.32%. Comparing base (24c0bb4) to head (fe78c4c).

Files with missing lines Patch % Lines
...s/sphinx-ux-grid/src/sphinx_ux_grid/_directives.py 91.60% 24 Missing ⚠️
scripts/ci/package_tools.py 20.00% 12 Missing ⚠️
...s/sphinx-ux-tabs/src/sphinx_ux_tabs/_transforms.py 94.61% 7 Missing ⚠️
...s/sphinx-ux-tabs/src/sphinx_ux_tabs/_directives.py 92.00% 6 Missing ⚠️
...ckages/sphinx-ux-tabs/src/sphinx_ux_tabs/_nodes.py 90.47% 6 Missing ⚠️
...ges/sphinx-ux-tabs/src/sphinx_ux_tabs/_visitors.py 90.47% 4 Missing ⚠️
...s/sphinx-ux-tabs/src/sphinx_ux_tabs/_prehydrate.py 96.55% 2 Missing ⚠️
tests/ext/grid/test_directive_tree.py 99.29% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #38      +/-   ##
==========================================
+ Coverage   91.81%   92.32%   +0.50%     
==========================================
  Files         219      249      +30     
  Lines       17758    19714    +1956     
==========================================
+ Hits        16304    18200    +1896     
- Misses       1454     1514      +60     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tony tony force-pushed the gp-sphinx-design branch from fe78c4c to 2c60f45 Compare May 17, 2026 21:02
tony added 11 commits May 17, 2026 17:58
…the gp-sphinx namespace

why: Provide a first-party `{octicon}` role that ships only the icons
gp-sphinx actually consumes and keeps every emitted class inside the
`gp-sphinx-octicon` namespace.

what:
- Add `sphinx-ux-octicons` workspace package with `OcticonRole`,
  `render_octicon`, and `load_octicons` exposed from the top-level module
- Bundle 18 curated octicons (12 currently in use plus 6 headroom)
  as `_data/octicons.json` audited from `_data/octicons_curated.txt`
- Ship `_static/css/sphinx_ux_octicons.css` under `@layer gp-sphinx`
  using `currentColor` so icons inherit the surrounding text colour
- Add a `scripts/sync_octicons.py` maintainer one-shot that rewrites
  the bundled JSON from an upstream `@primer/octicons` checkout
- Cover the package with render, height-parse, role, and per-icon
  snapshot tests (snapshots stored under `tests/ext/octicons`)
- Wire the package into the workspace: `pyproject.toml`, docs
  package index, redirect map, cluster classification, CI smoke
  runner, and the docs sys.path bootstrap
…y BadgeNode

why: Provide first-party `{bdg-<color>}` and `{bdg-<color>-line}` roles
that route through BadgeNode and the gp-sphinx-* namespace, so the
authoring surface is drop-in while every emitted class stays inside
gp-sphinx-badge.

what:
- Add _roles.py with a programmatic factory and `register_bdg_roles`
  registering both fill and outline variants for the eleven semantic
  colours (primary, secondary, success, info, warning, danger, light,
  muted, dark, white, black)
- Extend sab_palettes.css with semantic colour triples (bg/fg/border)
  plus dark-mode overrides, and bind each `gp-sphinx-badge--color-*`
  class to the shared `--gp-sphinx-badge-{bg,fg,border}` tokens
- Add `SAB.COLOR_*` constants for the eleven colours
- Wire `register_bdg_roles(app)` into `setup()` and re-export it from
  the package's `__all__`
- Cover the new surface with role-registration, factory-invocation,
  and integration-build tests in `tests/ext/badges/test_badges.py`
…} directives

why: Provide a first-party drop-in for sphinx-design's grid markup that
keeps every emitted class inside the `gp-sphinx-grid*` namespace and
drives layout from CSS Grid via inlined CSS custom-property overrides
instead of Bootstrap-derived float classes.

what:
- Add `sphinx-ux-grid` workspace package exposing `GridDirective`,
  `GridItemDirective`, `GridItemCardDirective`, `SUG`, and
  `LinkPassthrough` from the top-level module
- Parse breakpoint column specs ("N" or "xs sm md lg" with each in
  [1..12]) into a four-int tuple and inline them as
  `--gp-sphinx-grid-cols-{xs,sm,md,lg}` style properties; `:gutter:`
  accepts the 0..5 Bootstrap scale (mapped to a fixed CSS length) or a
  raw CSS length, surfaced as `--gp-sphinx-grid-gutter`
- Support every `{grid-item-card}` option the workspace consumes —
  `:link:` / `:link-type:` (url/any/ref/doc) with `addnodes.pending_xref`
  for non-URL targets, `:shadow:` (none/sm/md/lg), `:img-top:`,
  `:img-bottom:`, `:img-background:`, `:width:`, `:text-align:`, and the
  full set of `:class-*:` overrides
- Split card content on `^^^` (header) and `+++` (footer) markers,
  matching the splitter shape consuming docs already use
- Wrap each stretched link in a `LinkPassthrough` text element so the
  HTML5 writer accepts a bare `nodes.reference` / `pending_xref` as a
  card child without tripping its image-only assertion path
- Ship `_static/css/sphinx_ux_grid.css` under `@layer gp-sphinx` driving
  the layout from the inlined custom properties with sensible fallbacks
- Cover the package with option-parsing unit tests, docutils-tree
  directive tests (including stretched-link node-type assertions for
  `url` and `doc` link types), and an integration build asserting
  HTML structure plus internal-doc/external-URL link resolution
- Wire the package into the workspace: `pyproject.toml` (sources,
  dev-deps, isort, testpaths), docs package index, redirect map,
  cluster classification, docs `sys.path` bootstrap, the CI smoke
  runner, and `tests/test_package_reference.py`
…x-inline-tabs + sphinx-design

why: Replace sphinx-inline-tabs and sphinx-design's tab-set/tab-item
with a first-party package whose JS does not collide with spa-nav and
whose CSS stays under the gp-sphinx-* namespace.

what:
- Add sphinx-ux-tabs: directives .. tab:: (with :new-set:), .. tab-set::, .. tab-item::
- Custom nodes TabContainer, TabSetNode, TabItemNode, TabInputNode, TabLabelNode
- Two-pass TabsPostTransform: group consecutive .. tab:: siblings, then expand to radio-input HTML
- CSS-only tab switching under @layer gp-sphinx with tokens for active/inactive states
- SPA-aware sync JS hooked onto gp-sphinx:navigated, idempotent via data-gp-sphinx-tabs-bound guard
- Tests: pure-docutils node tests, transform unit tests, integration build covering both authoring styles
…ons for first-party

why: The first-party sphinx-ux-tabs, sphinx-ux-grid, sphinx-ux-octicons,
and sphinx-ux-badges packages own the directives and roles for {grid},
{grid-item-card}, {bdg-*}, {octicon}, .. tab::, {tab-set}, and {tab-item}
in the workspace docs. Listing them in DEFAULT_EXTENSIONS makes them the
source of truth and removes the {bdg-*} duplicate-role collisions that
arose while both sphinx-design and sphinx-ux-badges were loaded.

what:
- Replace sphinx_inline_tabs and sphinx_design in DEFAULT_EXTENSIONS
  with sphinx_ux_tabs, sphinx_ux_grid, sphinx_ux_octicons, and
  sphinx_ux_badges (the last explicit so the contract is independent
  of which autodoc package happens to also pull it in)
- Update the >>> len(DEFAULT_EXTENSIONS) doctest to 15
- Add _LEGACY_EXTENSION_REPLACEMENTS plus _check_legacy_extension_collisions
  in merge_sphinx_config, raising ExtensionError with a migration message
  when a downstream consumer's extra_extensions reinstates a legacy name
  alongside its first-party replacement; all collisions surface in a
  single error
- Cover the validation in tests/test_config.py: rejection for sphinx_design
  and sphinx_inline_tabs individually, multi-collision reporting, no-raise
  on clean merge, and no-raise when a legacy entry replaces the new stack
  via remove_extensions
- Switch the remove_extensions doctest and the existing
  test_merge_sphinx_config_remove_extensions case from sphinx_design to
  sphinx_ux_grid so they exercise an actual default
…dependencies and workarounds

why: First-party sphinx-ux-tabs, sphinx-ux-grid, sphinx-ux-octicons, and
sphinx-ux-badges packages now own the directives that sphinx-inline-tabs
and sphinx-design used to provide. The legacy dependencies and the
remove_tabs_js workaround they required are dead code.

what:
- Remove remove_tabs_js function and its build-finished hook from config.py
- Drop sphinx-inline-tabs and sphinx-design from packages/gp-sphinx/pyproject.toml
- Drop the sphinx_inline_tabs._impl warning filter from the workspace pyproject.toml
- Remove redundant sphinx_ux_badges listing from docs/conf.py extra_extensions
  (now part of DEFAULT_EXTENSIONS)
- Drop the now-unused sphinx_design entry from the FastMCP docs-page test scenario
- Refresh DEFAULT_EXTENSIONS table and remove_extensions example in the docs to
  reflect the current extension stack
- Drop tabs.js removal and sphinx_design from feature lists in README / AGENTS.md
- Regenerate uv.lock
why: sphinx-ux-octicons, sphinx-ux-grid, and sphinx-ux-tabs shipped
with only stub landing pages; every other common-library package in
the workspace carries the full tutorial / how-to / reference /
explanation / examples / dependents tree. Also documents the
{bdg-*} MyST role family on the sphinx-ux-badges reference page.

what:
- Add full docs trees under docs/packages/sphinx-ux-octicons,
  docs/packages/sphinx-ux-grid, docs/packages/sphinx-ux-tabs
- Document the {bdg-*} MyST role family in
  docs/packages/sphinx-ux-badges/reference.md with live colour examples
  for all 11 colours in both filled and outline variants
- Register [tool.gp-sphinx.docs] showcase = ["dependents"] in each
  new package's pyproject.toml so the dependents subpage is picked
  up by the package-landing directive's auto-discovery
…d deep-link via URL params

why: sphinx-design and sphinx-inline-tabs both shipped storage-based
persistence and URL query-param pre-selection; the drop-in
replacement should match.

what:
- Add :class-container: option on {tab-item}; propagate to the panel container
- Introduce TabPanelNode so the panel <div> carries data-sync-id /
  data-sync-group HTML attributes
- Persist sync clicks to localStorage under gp-sphinx-tabs.sync.<group>
- Restore selections on script-load and gp-sphinx:navigated
- Accept ?tabs=Label and ?<group>=<id> URL params on first paint;
  URL params win over localStorage and write through so they stick
… add --large size variant

why: The prior styling defined its own colour tokens rather than
using Furo's; the libtmux-mcp installer widget's tab styling
(color-mix background tints, :focus-visible outline, brand-primary
active state) sets a higher bar that travels well to the generic
tab system.

what:
- Drop bespoke --gp-sphinx-tabs-* colour custom properties; use
  Furo's --color-* tokens directly so the light/dark flip travels
  through without per-mode rules
- color-mix tint on the tab container, --color-background-hover
  fallback on hover, :focus-visible outline (no plain :focus ring
  on pointer interactions), brand-primary active state with
  background flip to --color-background-primary
- Active panel paints --color-background-primary to "punch out"
  the label-row tint, so the body reads as a raised surface
- Add .gp-sphinx-tabs--large modifier scaling label padding and
  font size; authors opt in via :class: gp-sphinx-tabs--large on
  a tab-set
- Replace directives.class_option on TabSetDirective.:class:
  with a raw whitespace splitter so BEM modifier syntax (-- in
  gp-sphinx-tabs--large) survives the option round-trip instead
  of getting collapsed to a single dash by nodes.make_id
- Integration test asserts the modifier class survives the
  :class: option round-trip
…on synced tab restore

why: localStorage and URL-driven tab restoration happen after JS
runs; on first paint the user briefly sees the default tab before
the JS swaps to the saved selection. An inline <head> script that
sets <html data-gp-sphinx-tabs-sync-<group>="<id>"> before any
stylesheet loads, combined with a dedicated CSS layer that paints
the matching label and panel directly from those attributes,
eliminates the flash.

what:
- Add _prehydrate.py with _build_style() / _script() / inject_tabs_prehydrate hook
- Collect (sync_group, sync_id) pairs into env.gp_sphinx_tabs_sync_pairs in the post-transform
- Register the html-page-context hook, plus env-purge-doc and env-merge-info for incremental/parallel builds
- Tests cover the generator output, the gated empty-set short-circuit, and an integration build confirming the <head> payload appears for sync'd pages and is absent otherwise
…ep-links, prehydrate

why: Four author-facing capabilities landed without reference docs;
make them discoverable.

what:
- Add :class-container: row to {tab-item} option table
- Add Size variants section to reference.md and how-to.md
- Add Persistence and deep-links section to reference.md and how-to.md
- Add Prehydrate subsection under JavaScript in reference.md
- Examples.md gains side-by-side default-vs-large tab-set and deep-link demo
@tony tony force-pushed the gp-sphinx-design branch from 2c60f45 to da10255 Compare May 17, 2026 23:08
@tony
Copy link
Copy Markdown
Member Author

tony commented May 18, 2026

Code review

Found 1 issue:

  1. gp-sphinx's [project.dependencies] declares no runtime dependency on the four new first-party extensions (sphinx-ux-tabs, sphinx-ux-grid, sphinx-ux-octicons, sphinx-ux-badges) — yet defaults.py adds them to DEFAULT_EXTENSIONS unconditionally. The previous deps list explicitly carried sphinx-inline-tabs and sphinx-design; their first-party replacements were not added back when those lines were removed. Workspace uv.lock masks this locally, but a downstream pip install gp-sphinx from PyPI will fail at Sphinx build time with ExtensionError because the four extensions are not transitively installed.

Deps block (no sphinx-ux-* lines):

dependencies = [
"sphinx>=8.1,<9",
"sphinx-gp-theme==0.0.1a20",
"sphinx-fonts==0.0.1a20",
"myst-parser",
"docutils",
"sphinx-autodoc-typehints-gp==0.0.1a20",
"sphinx-copybutton",
"sphinx-gp-opengraph==0.0.1a20",
"sphinx-gp-sitemap==0.0.1a20",
"sphinxext-rediraffe",
"linkify-it-py",
"gp-libs",
]

DEFAULT_EXTENSIONS (all four enabled by default):

"sphinx.ext.autodoc",
"sphinx_fonts",
"sphinx.ext.intersphinx",
"sphinx_autodoc_typehints_gp",
"sphinx.ext.todo",
"sphinx_ux_tabs",
"sphinx_copybutton",
"sphinx_gp_opengraph",
"sphinx_gp_sitemap",
"sphinxext.rediraffe",
"sphinx_ux_grid",
"sphinx_ux_octicons",
"sphinx_ux_badges",
"myst_parser",
"linkify_issues",
]

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants