Runnable docs site: live examples for every component#244
Merged
Conversation
Eighteen pure-PHP libraries deserve docs you can poke at, not just read. Every page on this site embeds <php-snippet> elements that boot WordPress Playground in your browser, unzip the toolkit into it, and run examples against the real library. Click a snippet to edit it; click Run again. The site lives at docs/ and is generated by bin/build-docs.py from a single content catalog. Snippets share one runtime per page via the blueprint mechanism shipped in WordPress/wordpress-playground#3536, so the WASM + WordPress download only happens on the first Run click. Pages have a sticky table-of-contents built from the h2 headings, an editable code area (contenteditable on the rendered <code> as a stopgap until <php-snippet> ships an editable attribute upstream), and GitHub-flavored light/dark styling. GitHub Actions deploys docs/ to Pages on every push to trunk; the workflow rebuilds the toolkit bundle and regenerates pages from trunk's components.
The PHP snippets were rendered through HTML-escape, but <script type= "application/x-php"> content is parsed as raw text — the browser does not decode entities, so <?php and " were ending up in the runner verbatim. Each component page now has an 'All components' list above the page TOC so you can jump between any two pages in one click. Highlighted entry points at the current page.
Each page now ships 5–10 examples ranked simple to complex, drawn from real problems people hit when reaching for these libraries: lazy-loading images and stamping CSP nonces (HTML), building EPUBs and defending against zip-slip (Zip), three-way merging a Markdown folder against a WP database (Merge), parallel HTTP fan-out (HttpClient), syncing an Obsidian vault into WordPress posts (Markdown + DataLiberation), and so on. Real composition between components — Zip into InMemoryFilesystem, Markdown into WXR — shows how the toolkit is designed to compose. Content moved into bin/_docs_components.py so the generator stays small and the catalog is one focused diff to extend.
The runnable-docs site lives under /docs, including a JS bundle that phpcs tries to lint as PHP. Mirror the existing /examples exclusion.
Stacked on top of #244. Wires the docs site into [wordpress-playground#3555](WordPress/wordpress-playground#3555), which added an `expected-output` mechanism to the `<php-snippet>` web component. When a snippet ships its expected output, Run renders that output instantly without booting Playground at all — no PHP/WordPress download, no iframe, no wait. ## How it works `bin/run-snippets.py` runs every PHP snippet in the catalog against the local toolkit and captures stdout: ```sh composer install bin/run-snippets.py --update # regenerates bin/_expected_outputs.json bin/run-snippets.py --check # CI mode: verify outputs match committed JSON ``` The runner rewrites each snippet's `/wordpress/wp-content/php-toolkit/vendor/autoload.php` to the repo's local `vendor/autoload.php` and injects a tiny `parse_blocks()` polyfill so WordPress-specific helpers don't break local runs. Outputs go through a small normalizer that strips temp-file paths, OIDs, and random nonces so the JSON is stable across runs. `bin/build-docs.py` reads the JSON and emits a `<script type="text/expected-output">` child inside any `<php-snippet>` that has a captured output. The component then renders that text directly on first Run. ## Coverage today 80 of the catalog's 84 PHP snippets pre-render. The four that don't are `HttpClient` / `HttpServer` examples that need real network or a listening port — those still boot Playground at click time, same as before. ## Stacked PR A follow-up PR adds a CI workflow that runs `bin/run-snippets.py --check` on every push, so we catch drift the moment a snippet's output changes.
This was referenced May 2, 2026
adamziel
added a commit
that referenced
this pull request
May 3, 2026
## Summary The runnable docs site at https://wordpress.github.io/php-toolkit/ shipped in #244 and the markdown sources behind it landed in #254. This PR makes it easy to find from every place a reader is likely to land. ## What changed **`github.com/WordPress/php-toolkit`** — Repo description and homepage URL are set via API to `https://wordpress.github.io/php-toolkit/`, so the sidebar on the repo page surfaces the docs link. **Root `README.md`** — A "📚 Live, runnable docs" callout sits at the top, a per-component table replaces the bullet list (each row links to both the README and the matching reference page on the live site), and a "Building the docs site" subsection in the dev workflow points at `bin/build-docs-bundle.sh` + `bin/serve-docs.py`. **`components/<Name>/README.md`** — All 18 component READMEs gain an idempotent banner immediately under the H1, deep-linking to that component's reference page. The banner is wrapped in HTML-comment markers so future URL/wording updates can be re-applied with one script: ```html <!-- docs-site-banner --> > 📚 **Runnable examples:** [https://wordpress.github.io/php-toolkit/reference/zip.html](...) > Open the page to edit each snippet in your browser and run it in WordPress Playground. <!-- /docs-site-banner --> ``` **`components/<Name>/composer.json`** — Each per-component package (17 of them; `ToolkitCodingStandards` has no composer.json) gains: - `homepage` → the matching reference page - `support: { issues, source, docs }` → links visible on Packagist - shared `keywords: ["wordpress", "php-toolkit"]` The result: someone who lands on https://packagist.org/packages/wp-php-toolkit/zip sees a "Homepage" link to the runnable docs and a "Documentation" link in the support sidebar. **Root `composer.json`** — The `wp-php-toolkit/php-toolkit` meta-package gets the same homepage + support block, plus a description that names the docs URL ("Browse runnable examples at https://wordpress.github.io/php-toolkit/"). **`examples/create-wp-site/README.md`** — Same docs-site banner under the H1 so readers in the examples folder don't miss the docs site. **`AGENTS.md`** — A `Docs site:` pointer added next to the upstream/branch lines, with a one-liner that `bin/_docs_components/<slug>.md` is where the runnable examples live. ## Test plan - [ ] CI passes (no code changes; 87/87 snippets still match). - [ ] After merge, https://github.com/WordPress/php-toolkit shows the homepage URL on the right sidebar. - [ ] After Packagist re-sync (auto on next release, or manual via the package page), each `wp-php-toolkit/*` page surfaces the docs URL under "Homepage" and "Documentation". - [ ] Component READMEs render the banner cleanly on github.com (HTML-comment markers stay invisible). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What it does
Adds a generated documentation site under
docs/with runnable PHP examples for every PHP Toolkit component. The site includes reference pages, a short learning path, the previous docs preserved underdocs/_legacy/, and GitHub Pages deployment.Each example is represented as a
<php-snippet>block. Snippets can run in WordPress Playground, and stable examples also carry checked-in expected output so readers see useful results before Playground finishes booting.Rationale
The component READMEs document individual APIs, but they do not give readers one consistent place to browse the toolkit or try the code. This adds an executable docs surface and puts the examples under CI so sample code is less likely to drift away from the actual components.
Implementation
bin/_docs_components.pydefines the generated component catalog and examples.bin/build-docs.pyandbin/build-reference.pyrender the learn and reference pages, whilebin/build-docs-bundle.shpackages the current toolkit intodocs/assets/php-toolkit.zipfor Playground.docs/assets/page.jshandles snippet setup, Playground blueprints, editable code blocks, expected-output rendering, and the docs navigation.bin/run-snippets.pyexecutes snippets locally and checks or updatesbin/_expected_outputs.json.The PR also adds
bin/serve-docs.pyfor local preview,.github/workflows/docs.ymlfor GitHub Pages,.github/workflows/snippet-tests.ymlfor snippet CI, and excludes generated docs from PHPCS.Testing instructions
Then open
http://localhost:8787, run a few snippets, and verify that expected output is visible before Playground boots.