Skip to content

Pair gp-sphinx-light with monokai for proper light/dark code blocks#24

Merged
tony merged 5 commits intomainfrom
improved-codeblock-theme
Apr 30, 2026
Merged

Pair gp-sphinx-light with monokai for proper light/dark code blocks#24
tony merged 5 commits intomainfrom
improved-codeblock-theme

Conversation

@tony
Copy link
Copy Markdown
Member

@tony tony commented Apr 30, 2026

Summary

  • Add a new gp-sphinx-light Pygments style (CodeMirror palette: slate-50 bg, purple keywords, yellow strings, blue numbers, slate-500 italic comments) and register it via the pygments.styles entry point in sphinx-gp-theme.
  • Default the workspace theme to gp-sphinx-light (light) + monokai (dark) so Furo's body[data-theme]-scoped pygments overlay actually renders light code blocks in light mode instead of monokai-on-light.
  • Refactor argparse-highlight.css to drive every token color through --gp-sphinx-argparse-* custom properties, with CodeMirror-light defaults at :root and One Dark overrides under body[data-theme="dark"] and the prefers-color-scheme: dark fallback. Drops ~50 hardcoded hex literals and the now-obsolete light-mode headerlink workaround. --argparse-code-background is kept as a back-compat alias.
  • Lock the new pairing into CI with three test layers in tests/test_pygments_style.py: pure-unit token-palette assertions, a syrupy snapshot of HtmlFormatter.get_style_defs(".highlight"), and a @pytest.mark.integration build that asserts both the unscoped light palette and the body[data-theme="dark"] monokai scope are present in the built pygments.css. Suite: 1216 → 1231 passed.

Test plan

  • uv run ruff format .
  • uv run ruff check .
  • uv run mypy src tests
  • uv run pytest
  • uv run pytest tests/test_pygments_style.py -v (new coverage)
  • just build-docs and visually confirm in a browser:
    • Light mode: code blocks render on slate-50 background with purple keywords / yellow strings
    • Dark mode: code blocks render with monokai (cyan keywords on #272822)
    • argparse directives: option/metavar/command tokens recolor correctly when toggling the theme

tony added 4 commits April 30, 2026 17:13
…odeMirror palette

why: Furo emits combined light+dark pygments.css scoped by body[data-theme],
  but the workspace currently only ships dark Pygments styles, so light-mode
  code blocks render as dark-on-light. Need a real light style to feed into
  Furo's pygments_style slot.

what:
- Add GpSphinxLightStyle in sphinx_gp_theme.pygments_styles, derived from
  the Microviz/social-embed CodeMirror light palette (slate-50 background,
  purple keywords, yellow strings, blue numbers, orange built-ins, red
  HTML tags, slate-500 italic comments).
- Map full Pygments token tree (Keyword, Name, String, Number, Generic,
  Operator, Comment subtypes) so lexers emitting any subtype get coloured.
- Annotate styles dict as t.ClassVar[dict[token._TokenType, str]] for
  ruff RUF012 / mypy compliance.
- Register style via [project.entry-points."pygments.styles"] in
  packages/sphinx-gp-theme/pyproject.toml so pygments.styles.get_style_by_name
  resolves "gp-sphinx-light" once the package is installed.
… default

why: Today defaults.py sets pygments_style=monokai for both light and dark
  modes, so Furo renders monokai everywhere — code blocks always look dark
  even when the rest of the page is in light mode. Switching the light slot
  to gp-sphinx-light lets Furo's body[data-theme] scoping do its job.

what:
- gp-sphinx defaults.py: DEFAULT_PYGMENTS_STYLE = "gp-sphinx-light"
  (was "monokai"); DEFAULT_PYGMENTS_DARK_STYLE stays "monokai" so dark mode
  is unchanged. Refresh both docstrings to explain the Furo pairing.
- sphinx-gp-theme theme.conf: pygments_style = gp-sphinx-light (was
  a11y-light) so a Sphinx build using the theme without
  merge_sphinx_config() still picks up the new light style.

Built docs verify the result: .highlight .k now emits #7C3AED (CodeMirror
purple) in the light scope while body[data-theme="dark"] .highlight .k still
emits #66D9EF (monokai cyan).
…data-theme

why: argparse-highlight.css was authored for a dark-only context and hardcoded
  the One Dark palette (e.g. .highlight-argparse .nt { color: #56b6c2 }) plus
  a single :root --argparse-code-background: #272822, so light-mode pages
  rendered dark-on-light option flags and a dark code background under a light
  page chrome. Furo-style data-theme scoping fixes both.

what:
- Lift every token color into a --gp-sphinx-argparse-* custom property
  (option, metavar, command, subcommand, choice, default, punctuation,
  usage-label, section, code-bg, meta-tag-bg, meta-tag-border).
- Default :root values use the CodeMirror light palette
  (--gp-sphinx-argparse-option: #a855f7, --metavar: #ca8a04,
  --command: #7c3aed, --subcommand/--choice: #16a34a, --code-bg: #f1f5f9, …).
- Override the same properties under body[data-theme="dark"] and inside
  @media (prefers-color-scheme: dark) { body:not([data-theme="light"]) … }
  with the historic One Dark hex values.
- Rewrite all .cli-*, .highlight-argparse*, .argparse-usage,
  .argparse-argument-name, .argparse-meta-* selectors to consume
  var(--gp-sphinx-argparse-…) instead of literal #hex colors.
- Drop the body[data-theme="light"] .argparse-argument-name .headerlink
  workaround: the workaround existed because the code background used to be
  dark in light mode; with the new dual-theme bg, the standard
  --color-foreground-secondary already gives the right contrast.
- Keep --argparse-code-background as a back-compat alias of the new
  --gp-sphinx-argparse-code-bg in case any downstream snapshot/template
  references the old name.

CSS file shrinks net 3 lines but consolidates the palette into a single
auditable block at the top of the file, removing ~50 hex literal duplications.
…nd built CSS

why: The gp-sphinx-light/monokai pairing relies on a custom Pygments style
  shipped via entry point AND on Furo's overlay emitting body[data-theme]
  scoped rules. Both are silent failure modes — a missing entry point or a
  Furo upgrade that drops dual-stylesheet support would only show up at
  visual review. Lock both in CI.

what:
- tests/test_pygments_style.py adds three layers:

  Pure unit (no Sphinx, no docutils):
  - test_gp_sphinx_light_resolved_by_name: get_style_by_name returns
    GpSphinxLightStyle with the expected slate-50 background.
  - test_gp_sphinx_light_line_number_palette: gutter colours match the
    slate-100 / slate-500 palette.
  - test_gp_sphinx_light_token_palette: NamedTuple-parametrized table
    (10 cases) asserting per-token expected substrings — Comment, Keyword,
    Operator.Word, String, Number, Name.Builtin, Name.Tag, Name.Attribute,
    Generic.Inserted, Generic.Deleted.

  Snapshot:
  - test_gp_sphinx_light_html_style_defs: locks the full HtmlFormatter
    .get_style_defs(".highlight") output via snapshot_html_fragment so any
    accidental drift in colour or weight surfaces in CI. Initial snapshot
    captured 89 lines of per-token CSS.

  Sphinx integration (@pytest.mark.integration, module-scoped fixture):
  - test_built_pygments_css_contains_light_palette: builds a tiny project
    with html_theme=sphinx-gp-theme + the paired styles, asserts the
    unscoped .highlight block carries CodeMirror purple/yellow/blue and
    background #f8fafc.
  - test_built_pygments_css_contains_dark_scope: asserts Furo emits the
    body[data-theme="dark"] .highlight block with monokai colours
    (#272822 background, #66d9ef keyword cyan).

- Suite now reports 1231 passed (was 1216).
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.15%. Comparing base (dd21b56) to head (0e65586).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #24      +/-   ##
==========================================
+ Coverage   90.07%   90.15%   +0.08%     
==========================================
  Files         162      164       +2     
  Lines       13588    13648      +60     
==========================================
+ Hits        12240    12305      +65     
+ Misses       1348     1343       -5     

☔ 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.

why: Two user-visible changes shipped on this branch warrant changelog
  notes — the new default light/dark Pygments pairing, and the
  argparse-highlight light-mode rendering fix.

what:
- Under the unreleased block, add a What's new entry covering the
  gp-sphinx-light + monokai default pairing (the shipped headline of
  the branch — light mode actually renders light now).
- Add a Bug fixes entry for argparse-highlight: the directive used to
  render dark-on-light in light mode because the palette was hardcoded
  One Dark; tokens now flow through --gp-sphinx-argparse-* custom
  properties with body[data-theme="dark"] overrides.
@tony tony merged commit 48ff9df into main Apr 30, 2026
40 checks passed
tony added a commit that referenced this pull request Apr 30, 2026
why: Cut the next alpha covering the light-mode Pygments default and the
argparse-directive theme scoping fix — both shipped under #24 and visible
in the rendered docs as soon as a downstream project upgrades.

what:
- just bump-version 0.0.1a13: every workspace package's
  pyproject.toml version, every __init__.py / extension.py
  __version__, the workspace pyproject.toml, scripts/ci helpers
  and matching test, and uv.lock all advance to 0.0.1a13.
- CHANGES gains a dated "## gp-sphinx 0.0.1a13 (2026-04-30)"
  release header above the existing What's new / Bug fixes
  content; the "## gp-sphinx 0.0.1 (unreleased)" placeholder +
  maintainer comment stays at the top of the file as the next-
  release insertion point.
@tony tony deleted the improved-codeblock-theme branch April 30, 2026 23:19
tony added a commit that referenced this pull request May 2, 2026
…; clean stray theme.conf conflict markers

why: Post-rebase fix-up after merging onto v0.0.1a13 release on main.
Two issues to clear:

1. Lockstep version policy: main released 0.0.1a13 across all 14
   pre-existing workspace packages, but the rebase brought in
   gp-furo-theme + gp-sphinx-vite at 0.0.1a12 (their initial-creation
   version on this branch). check_versions() in scripts/ci/package_tools.py
   fails the suite when versions diverge across workspace packages.

2. Bad merge during rebase: when resolving the step-9.13 cutover commit's
   theme.conf conflict (sphinx-gp-theme stylesheet swap from styles/furo.css
   to styles/furo-tw.css combined with main's pygments_style change to
   gp-sphinx-light), the Edit-tool race left raw <<<<<<< / ======= /
   >>>>>>> markers committed inside the file. test_pygments_style errored
   on configparser.DuplicateOptionError when reading the conf.

what:
- Bump version 0.0.1a12 -> 0.0.1a13 across:
  - packages/gp-furo-theme/pyproject.toml + src/__init__.py
  - packages/gp-sphinx-vite/pyproject.toml + src/__init__.py
- Bump npm-packaged version 0.0.1-alpha.12 -> 0.0.1-alpha.13:
  - packages/gp-furo-theme/web/package.json
  - packages/gp-furo-tokens/package.json
- packages/sphinx-gp-theme/pyproject.toml dependency pin:
  gp-furo-theme==0.0.1a12 -> ==0.0.1a13
- tests/test_gp_sphinx_vite.py: assert __version__ == "0.0.1a13"
- packages/sphinx-gp-theme/src/sphinx_gp_theme/theme/theme.conf:
  remove conflict markers; final state is what the cutover commit
  intended:
    inherit = gp-furo
    stylesheet = styles/furo-tw.css, css/custom.css, css/argparse-highlight.css
    pygments_style = gp-sphinx-light    (from main's #24)
- uv.lock regenerated via `uv sync --all-packages --all-extras --group dev`

Pre-commit gate: ruff/mypy/pytest 1310 passed/159 skipped/just build-docs
all green.

Suggested follow-up: this commit could be `git rebase -i --autosquash`-ed
into the relevant earlier commits (e.g. theme.conf fix into the cutover
commit `e58795b`, version bumps into the package scaffolds). Left as a
separate commit for now since the user signs off on history-rewriting
operations.
tony added a commit that referenced this pull request May 2, 2026
…; clean stray theme.conf conflict markers

why: Post-rebase fix-up after merging onto v0.0.1a13 release on main.
Two issues to clear:

1. Lockstep version policy: main released 0.0.1a13 across all 14
   pre-existing workspace packages, but the rebase brought in
   gp-furo-theme + gp-sphinx-vite at 0.0.1a12 (their initial-creation
   version on this branch). check_versions() in scripts/ci/package_tools.py
   fails the suite when versions diverge across workspace packages.

2. Bad merge during rebase: when resolving the step-9.13 cutover commit's
   theme.conf conflict (sphinx-gp-theme stylesheet swap from styles/furo.css
   to styles/furo-tw.css combined with main's pygments_style change to
   gp-sphinx-light), the Edit-tool race left raw <<<<<<< / ======= /
   >>>>>>> markers committed inside the file. test_pygments_style errored
   on configparser.DuplicateOptionError when reading the conf.

what:
- Bump version 0.0.1a12 -> 0.0.1a13 across:
  - packages/gp-furo-theme/pyproject.toml + src/__init__.py
  - packages/gp-sphinx-vite/pyproject.toml + src/__init__.py
- Bump npm-packaged version 0.0.1-alpha.12 -> 0.0.1-alpha.13:
  - packages/gp-furo-theme/web/package.json
  - packages/gp-furo-tokens/package.json
- packages/sphinx-gp-theme/pyproject.toml dependency pin:
  gp-furo-theme==0.0.1a12 -> ==0.0.1a13
- tests/test_gp_sphinx_vite.py: assert __version__ == "0.0.1a13"
- packages/sphinx-gp-theme/src/sphinx_gp_theme/theme/theme.conf:
  remove conflict markers; final state is what the cutover commit
  intended:
    inherit = gp-furo
    stylesheet = styles/furo-tw.css, css/custom.css, css/argparse-highlight.css
    pygments_style = gp-sphinx-light    (from main's #24)
- uv.lock regenerated via `uv sync --all-packages --all-extras --group dev`

Pre-commit gate: ruff/mypy/pytest 1310 passed/159 skipped/just build-docs
all green.

Suggested follow-up: this commit could be `git rebase -i --autosquash`-ed
into the relevant earlier commits (e.g. theme.conf fix into the cutover
commit `e58795b`, version bumps into the package scaffolds). Left as a
separate commit for now since the user signs off on history-rewriting
operations.
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