Skip to content

Add spec caching, light presets, Swashbuckle preset and theme browser tests - #7

Merged
hlib-zinchenko merged 1 commit into
mainfrom
feature/backlog-leftovers
Nov 11, 2026
Merged

hlib-zinchenko merged 1 commit into
mainfrom
feature/backlog-leftovers

Conversation

@hlib-zinchenko

Copy link
Copy Markdown
Owner

Five items from the backlog: two features on our own host, a preset in core, a Scalar recipe, and browser tests for the adapters' dark theme.

What changed

Hlibz.Redoc.AspNetCore (our host)

  • SpecCacheDuration (opt-in, off by default).
    • Each served spec is generated at most once per period, then sent from memory with an ETag and Cache-Control: private, no-cache, so a returning browser gets a 304.
    • Requests that arrive during a regeneration share it rather than each generating their own.
    • Never applies to a gated document. That includes one gated with ForDocument(...).RequireAuthorization(), which the site can't see at startup, so WriteSpec also checks the endpoint's IAuthorizeData on each request.
    • Throws at startup if no page serves its own spec, rather than silently doing nothing.
  • LightThemePreset: Nord and GitHubLight, the light counterparts of the dark presets.
    • ReDoc 3's light mode is laid out differently from dark: the page background is --color-white, not a slot in the grey scale. So a light preset sets a page colour, eleven greys and an accent, under :root:root:not(.dark).
    • Only PrimaryColor turns off a light preset's accent.
    • There is no light Midnight: that palette is this repo's own, and a light version would be invented.

Hlibz.Redoc.Extensions.Core

  • ReDocDocumentsOptions.SwashbuckleSpecUrlTemplate (/swagger/{documentName}/swagger.json), available in all three packages.

Tests

  • New suite tests/Hlibz.Redoc.Extensions.BrowserTests for the adapters' dark theme, added to CI.
    • Both adapters run in one process, each referenced under an extern alias.
    • It reads the computed colours of every element an override in ReDocDarkThemeDefaults exists for: page, sidebar, scrollbars, section captions, nested-schema wrappers, the selected sample tab, inline code and the control tokens. Computed colours rather than screenshots, because pixel comparisons fail on another OS's font rendering.
    • It asserts them against the palette, checks redoc 2.0.0 and 2.5.4 render identically, and covers the Light/System/Dark selector switching to dark.
  • New conformance test asserting the Swashbuckle constant against Swashbuckle's real UseSwagger() route, on both adapters.

Docs

  • A "Scalar beside ReDoc" recipe in all three package READMEs.
  • CLAUDE.md fixes: ThemePreset now reads DarkThemePreset, and the bundle note covers both the brotli and gzip copies.

For reviewers

  • A known gap the new suite found. A oneOf switch's unselected button is hard-coded white on both redoc 2.0.0 and 2.5.4. The selected button differs only by a generated class name, so CSS can't target one without the other. The probe records the colour (identical on both hosts) without asserting it, and the fix is logged in IDEAS.md. It needs a small script, or giving up the selected button's highlight.
  • Why the extern aliases. The two adapters declare the same public type names, so referencing both is a CS0433 ambiguity. Each host's wiring is its own file that imports only its alias; core stays global.
  • Scalar on our host. The recipe points Scalar at the pages' own served specs with WithOpenApiRoutePattern, so MapOpenApi() stays unmapped and a gated document stays closed. It advises giving Scalar only the public documents, because its sidebar shows the names of every document it was given.

Testing

  • All six suites pass: core 28, both adapters 39 each, host 186, try-it browser 16, theme browser 5.
  • Proving the theme suite catches regressions: with the nested-schema override removed, it failed on both hosts with rgb(255, 255, 255); with the override restored, it passes.
  • Light presets: checked in Sample.Own with a temporary setting (not committed). In light mode the page and sidebar compute to #eceff4 and the text to #2e3440; dark mode keeps --color-white: #000000 and the dark preset. GitHubLight is covered by unit tests only.
  • Scalar recipe: run in a throwaway app on Scalar.AspNetCore 2.18.7. /scalar/ and /scalar/{name} load the host-served specs, /openapi/... stays a 404, and MapScalarApiReference(...).RequireAuthorization(...) compiles. The Swashbuckle route pattern in the adapter READMEs was not run.

🤖 Generated with Claude Code

… tests

- SpecCacheDuration (host): reuse a served spec for a period, sent with
  an ETag and private, no-cache. Never for a gated document, including
  one gated through ForDocument, detected per request.
- LightThemePreset (host): Nord and GitHubLight, the palettes that
  publish a light variant. Sets the page color as well as the ramp,
  since ReDoc 3's light mode paints the page from --color-white.
- ReDocDocumentsOptions.SwashbuckleSpecUrlTemplate (core), asserted
  against Swashbuckle's real UseSwagger route on both adapters.
- tests/Hlibz.Redoc.Extensions.BrowserTests: the adapters' dark theme
  as both hosts render it, by computed color, with the two hosts
  compared. Found the oneOf switch's white unselected button, recorded
  in IDEAS.md.
- Scalar beside ReDoc recipe in every package README, and CLAUDE.md
  fixes (DarkThemePreset name, the brotli bundle).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hlib-zinchenko
hlib-zinchenko merged commit aabb535 into main Nov 11, 2026
1 check passed
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.

1 participant