Skip to content

fix: render OpenAPI 3.1 in the Tracy panel by moving Swagger UI to 5.32.12 - #17

Open
AdamFiser wants to merge 3 commits into
contributte:masterfrom
AdamFiser:feat/swagger-ui-5-assets
Open

fix: render OpenAPI 3.1 in the Tracy panel by moving Swagger UI to 5.32.12#17
AdamFiser wants to merge 3 commits into
contributte:masterfrom
AdamFiser:feat/swagger-ui-5-assets

Conversation

@AdamFiser

Copy link
Copy Markdown
Contributor

Implements option A of #16: the Tracy panel now renders the OpenAPI 3.1 documents this library produces.

The vendored Swagger UI was 3.24.2 (November 2019), whose version detection accepts the 3.0 series alone, so openapi: 3.1.0 fell through to "Unable to render this definition". Swagger UI renders 3.1 from 5.0.0 on; this moves the copy to 5.32.12.

What is here

tools/update-swagger-ui.php — the update is reproducible instead of folklore. The committed stylesheet is not the distributed one (every selector carries a #tracy-debug scope, or the panel would style the host page around it), and nothing recorded how that was produced. The tool downloads a given swagger-ui-dist release, stores the two scripts verbatim and applies the scope itself:

$ php tools/update-swagger-ui.php 5.32.12
Downloading swagger-ui-dist@5.32.12
  swagger-ui-bundle.js (1 555 039 B)
  swagger-ui-standalone-preset.js (268 471 B)
  swagger-ui.css (178 977 B)
Scoping swagger-ui.css to #tracy-debug
  3095 selectors scoped
  dropped "html.dark-mode" 1x: would repaint the host page
Writing assets

It refuses to guess. A selector it cannot place aborts the run — which is not hypothetical: the first run stopped on the trailing sourceMappingURL comment, and that is the behaviour that will catch the next release reaching outside the panel.

One rule had to be dropped. StandaloneLayout puts .dark-mode on <html> itself:

componentDidMount(){window.matchMedia("(prefers-color-scheme: dark)").matches
  &&(document.documentElement.classList.add("dark-mode"),this.setState({isDarkMode:!0}))}

Paired with html.dark-mode{background:#1c2022}, any developer whose system asks for a dark theme would have found their whole application repainted whenever the bar was on the page. The rule is dropped and the tool says so on every run.

tests/Cases/Tracy/SwaggerUiAssetsTest.php — asserts from the stylesheet that every selector carries the scope, that the scope sits in front of .swagger-ui so Swagger UI's descendant chains survive, and that the bundle is a release which renders 3.1 at all.

tools is now covered by make cs/make phpstan and carries export-ignore.

Verification

Green tests are not the evidence here — a green suite is exactly what let this go unnoticed. So the panel was actually rendered: tests/Cases/Schema/examples/complete-3-1.yaml through OpenApi::fromArray(...)->toArray() (which yields openapi: 3.1.0), passed to the real SwaggerPanel::getPanel(), inside a host page with its own background, in headless Chrome.

rendered operations "Unable to render" node host <html> background
before, 3.24.2 0 present
after, light 9 none rgb(255, 255, 255)
after, dark (--force-dark-mode) 9 none rgb(255, 255, 255)

In the dark run <html class="dark-mode"> is set by Swagger UI, yet the host background is untouched — the dropped rule doing its job. Among the nine rendered operations is the petCreated webhook, a construct that exists only in 3.1, so this is 3.1 being rendered as 3.1 rather than tolerated.

I have the rendered screenshot locally and can attach it here on request — the panel shows the servers block with its variables, the pets and default tag groups across all eight methods, a Webhooks section holding petCreated, and the Pet schema. Note that .docs/misc/tracy-panel.png still shows the older UI; I left it alone rather than replace a screenshot taken in a real application with a staged imitation.

Checks:

$ vendor/bin/tester -s -p php -C tests/Cases
OK (25 tests, 6.5 seconds)

$ vendor/bin/phpstan analyse -c phpstan.neon
[OK] No errors

$ vendor/bin/phpcs --standard=ruleset.xml --extensions="php,phpt" -nsp src tests tools
(no violations)

The scoping test was also confirmed to fail when the scoping is broken — appending html.dark-mode{background:red} to the stylesheet produces Failed: These selectors would style the host page.: ['html.dark-mode'] — and the version test fails when the 3.24.2 bundle is put back.

Cost

The inlined payload grows from ~1.42 MB to ~2.00 MB per page carrying the Tracy bar, since panel.phtml reads all three assets on every render. Worth stating plainly, as #16 does: it buys rendering the versions the library supports, in a development-only tool.

Closes #16 if you take this route. Happy to fold in the version-warning idea (option C) as well, or to change the scoping approach, if you would rather have it another way.

The panel inlines its own copy of Swagger UI, and how that copy was produced was
not recorded anywhere: the committed stylesheet is not the distributed one, because
every selector carries a #tracy-debug scope the panel needs to avoid styling the
host page around it.

The tool downloads a given swagger-ui-dist release, stores the scripts verbatim and
applies that scope itself. It aborts on a selector it cannot place instead of
guessing, so a release that reaches outside the panel in a new way stops the update
rather than reaching an application.

Cover it by the existing checks, and keep it out of the distributed package.
The vendored Swagger UI was 3.24.2, built in November 2019, and its version
detection accepts the 3.0 series alone:

    function s(e){var t=e.get("openapi");return"string"==typeof t&&(t.startsWith("3.0.")&&t.length>4)}

A document declaring openapi: 3.1.0 matched neither that nor the Swagger 2 test, so
the panel rendered "Unable to render this definition" for a document this library
produces, describes and validates. The message blamed the definition for specifying
no valid version field, which sent readers looking in the wrong place.

Swagger UI renders 3.1 from 5.0.0 on. Move to 5.32.12, produced by
tools/update-swagger-ui.php.

The stylesheet gained one rule that would reach past the panel: StandaloneLayout
puts .dark-mode on <html> itself, and html.dark-mode sets a background, so a
developer whose system asks for a dark theme would find the whole application
repainted. That rule is dropped; the remaining 3095 selectors are scoped.
The panel renders inside a host page, so a Swagger UI selector that escapes the
debug bar styles someone's application. Nothing checked that, and the escape a 5.x
stylesheet actually contains - html.dark-mode - takes a browser and a dark system
theme to notice.

Assert it from the stylesheet instead: every selector carries the scope, and the
scope sits in front of .swagger-ui so the descendant chains Swagger UI relies on
survive. Assert too that the bundle is a release which renders 3.1 at all, since
that is the property the panel was failing on.

Document the version the panel carries and how to move it.
@AdamFiser
AdamFiser marked this pull request as ready for review August 11, 2026 07:26
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.

Tracy panel cannot render OpenAPI 3.1 documents the library itself produces (vendored Swagger UI is 3.24.2)

1 participant