docs: rewrite tooling in PHP, drop Python dependency#263
Merged
Conversation
e8fab36 to
93b466c
Compare
Stack on top of #262 (the heading-prefix change). Replaces 1,128 lines of Python tooling with 762 lines of PHP. The toolkit now documents itself using only its own runtime — no Python in CI, no second language to context-switch into when iterating on the docs. Replaces: bin/_docs_components.py (dead-code dicts, 200 lines) bin/_load_catalog.py (frontmatter + section + snippet parser, 370 lines) bin/build-reference.py (docs/reference/<slug>.html generator, 220 lines) bin/run-snippets.py (snippet runner + expected-output checker, 230 lines) bin/serve-docs.py (CORS-enabled local preview server, 50 lines) With: bin/build-reference.php (parser + renderer, 480 lines — also the catalog-loading library, since run-snippets.php requires it) bin/run-snippets.php (runner + expected-output writer, 250 lines) bin/serve-docs.php (php -S router with CORS headers, 50 lines) Behavioural parity: - 87/87 snippets match captured stdout (same expected-output blocks as before; the new parser produces byte-identical normalization and fence handling). - docs/reference/*.html renders byte-equivalent output: same HTML structure, same snippet/fallback/expected-output triples, same pitfall extraction, same see-also rendering. - --update writes captured stdout back into the same expected-output fence in the README via the same slug → directory map. Format change: see_also frontmatter switched from repeated keys (`see_also: a | A | r` × 3) to a proper YAML list: see_also: - a | A | reason - b | B | reason This is standard YAML — readable by any frontmatter-aware tool, and correctly typed as a sequence in GitHub's README renderer. The Python parser never accepted the YAML-list form; the new PHP parser only accepts that form. Workflows simplified: - snippet-tests.yml drops the `actions/setup-python` step. - docs.yml drops `python3 bin/build-reference.py` for `php bin/build-reference.php`. Per the prompt in docs-changes.md ("Change all the markdown-handling python tooling to use PHP. Reuse components from this repo."): the new PHP code uses standard library facilities (preg_*, proc_open) — none of the toolkit components needed any new feature, so no stack-base PR was required.
93b466c to
c09e068
Compare
The bin/build-reference.php, bin/run-snippets.php, and bin/serve-docs.php scripts are tooling that runs in CI on PHP 8.3, not library code. They don't need PHP 7.2 compatibility or WordPress-coding-standards compliance, matching how /bin/build-phar is already excluded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
The toolkit now documents itself using only its own runtime and its own structured-data parsers. No Python in CI; no hand-rolled regex over markdown or HTML.
What changed
bin/_docs_components.py(200 lines, dead-code dicts)bin/_load_catalog.py(370 lines: hand-rolled YAML-subset parser, regex section splitter, regex snippet extractor)bin/build-reference.py(220 lines)bin/build-reference.phpbin/run-snippets.py(230 lines)bin/run-snippets.phpbin/serve-docs.py(50 lines)bin/serve-docs.php(usesphp -Swith router)Parsers
slug,title,install,credit_*,see_also)Webuni\FrontMatter\FrontMatter::parse()— already vendored undercomponents/Markdown/vendor-patched/for the Markdown component. Single-line, multi-line `key:League\CommonMark\Parser\MarkdownParser+ walking the document. Section boundaries =Headingnodes at level 2. Snippets =HtmlBlock(<!-- snippet: -->) →FencedCode(info=php) tuples. Expected-output =HtmlBlock(<!-- expected-output -->) →FencedCodepair. Body content rendered viaHtmlRenderer::renderNodes()so raw HTML round-trips verbatim.<p>Footgun: …</p>)WP_HTML_Tag_Processor— walks tokens, confirms a<p>opener, finds the first inner#textnode, classifies, strips theFootgun:/Gotcha:prefix viaset_modifiable_text(), then slices off the outer<p>...</p>by length (no regex).<p>)Paragraphnode's inline children directly viaHtmlRenderer::renderNodes()instead of slicing afterward.<!-- snippet: filename: x.php\nrunnable: true\n-->)<!--/-->delimiters — no regex.--updatewriting captured stdout back into a READMEBehavioural parity
docs/reference/*.htmlrender correctly: 9<php-snippet>+ 9 fallback + 9 expected-output triples onhtml.html, 4 pitfall callouts (the bold-lead pattern is preserved), see-also list intact.--updateverified end-to-end:--updateinserts a fresh block in the right place; resulting README is byte-identical to one with the block authored manually.Frontmatter format change:
see_alsois a proper YAML listWebuni\FrontMatter\FrontMattercorrectly types it as a sequence; any frontmatter-aware tool reading the README sees the same shape. All 18 component READMEs migrated.Workflows simplified
snippet-tests.ymldrops theactions/setup-pythonstep.docs.ymlswapspython3 bin/build-reference.pyforphp bin/build-reference.php.Remaining
preg_*calls (all on plain text, not HTML)slugify()— heading text → URL-safe slug.normalize()— scrubs noise from snippet stdout (tempfile paths, git hashes, timestamps).require '...autoload.php';line in the snippet's PHP source to inject the local-prelude polyfill.These operate on plain strings, not HTML, so they're not what the "no regex over HTML" rule was about.
Test plan
Verify docs snippetsworkflow passes (87/87).Deploy docs to GitHub Pagesruns cleanly on push to trunk.bash bin/build-docs-bundle.sh && php bin/serve-docs.php— http://localhost:8787 renders all reference pages with snippets.php bin/run-snippets.php --update(no-op, no drift) leaves all READMEs untouched.🤖 Generated with Claude Code