Repository navigation
Contributing
HTML.PHP is a small, opinionated codebase β the opinions are the point. Read this before the first PR; it's short and it will save a round trip.
-
Zero runtime dependencies. PSR-shaped contracts ship in-library;
interop happens through adapters (
Psr3Adapter,Psr16Adapter). -
Templates are data. No
eval, no dynamic includes of template-provided code paths, no network I/O triggered by template content. -
Explicit state. No
$GLOBALS, no superglobals, no new statics below the WordPress bridge. Time and request data are injected. -
Two editions, one behaviour.
src/is 8.3-floor;src-8.5/overlays may use newer syntax but must be behaviour-identical (matrix-tested). - Fail loud, degrade soft. Structural errors throw; data errors diagnose with stable codes.
Every one of these is enforced by a test (13_security.test.php scans
tokens for #1β#3). A PR that breaks the constitution needs an RFC issue
first, not a diff.
git clone https://github.com/paulmann/HTML.PHP && cd HTML.PHP
# PHP 8.3 + 8.5 (Debian/Ubuntu via sury):
sudo apt install -y php8.3-cli php8.3-mbstring php8.5-cli php8.5-mbstring
php8.3 tests/run.php # must be green before AND after
php8.3 tools/build.php # regenerate bundles after src/ changes
bash tools/run-matrix.sh # the full matrixNo Composer needed for the core workflow; vendor/ is dev-tooling only.
src/ PSR-4 source (PHP 8.3 floor) β change things here
src-8.5/ whole-file 8.5 overlays β mirror behaviour-critical edits
php83/ php85/ built bundles β never edit by hand (CI drift gate)
tests/ runner + bootstrap + cases + WP stubs
tools/ build.php Β· bench.php Β· run-matrix.sh Β· check-wiki-links.php Β· publish-wiki.sh
wordpress/ plugin scaffold
docs/ canonical specs (versioned with code)
wiki/ tutorial/reference layer (published to the GitHub wiki)
examples/ runnable tours
bin/htmlphp CLI
Docs rule: behaviour changes update docs/ in the same PR; user-facing
narrative updates wiki/ in the same PR. The wiki drifts, CI can't check
prose β reviewers do.
-
declare(strict_types=1);everywhere (test-enforced),finalby default,readonlywherever possible, enums for policies. - PER-CS2.0 via
.php-cs-fixer.dist.php; alpha-sorted imports; no unused imports. - PHPStan level 6 clean over the full
src/tree; the baseline is empty by policy β fix findings in code. - Docblocks:
@param/@returnwith real types (list<string>,array<string, mixed>β the linter-level 6 iterable rules bite otherwise). - Diagnostics: reuse existing codes; new codes go in
Diagnostics+ the troubleshooting table. - Events:
htmlphp.<area>[.<detail>]tags; document payloads in API-Reference β Events. - Exceptions: pick the narrowest existing class; context arrays, not message-interpolated data.
A filter
-
Template\Filters::BUILTIN+ amatcharm inbuiltin()(mixed in, scalar/array out; escape-producing filters go inSubstitution::ESCAPING_FILTERS). - Tests in
07_variables_filters.test.php. - Row in
docs/TEMPLATE-SYNTAX.md+ wiki syntax table.
An SSI directive
Host-side: implement Ssi\DirectiveInterface and register β no library
change needed. Library-side (parity with mod_include only): add to
Scanner::dispatch + Linter known list + docs/SSI.md + tests in
05/06.
A cache/log driver
Implement Contracts\CacheInterface / Log\LoggerInterface; wire into the
matching factory + CacheDriver/LogDriver enum + config docs. Extension-
guarded drivers must fall back with a diagnostic (see ApcuCache).
A catalogue format
Catalog::load() extension sniff + a from*() constructor + merge
semantics via mergeFrom + tests (see the in-test MO builder in
09_i18n.test.php for fixture style).
An 8.5 overlay
Copy the src file into src-8.5/ (same relative path), apply the language
feature at a genuine seam, keep behaviour identical, note it in
docs/ARCHITECTURE.md's overlay table. The matrix runs both bundles β
overlays are not exempt from any test.
Labeled π’ on the ROADMAP: linter --fix rules, RenderOptions
named constructors, XLIFF I/O, CLDR sync tool, bench --profile, the VS Code
grammar, doc fixes. Each is scoped to β€ a few hundred lines with tests.
-
php8.3 tests/run.phpgreen Β· new behaviour has new assertions -
php tools/build.phpran;--checkclean (bundles committed) - PHPStan level 6 clean;
phpstan-baseline.neonstill empty -
docs/(+wiki/if user-facing narrative) updated in the same PR - No new globals/statics/superglobals/eval (the scanner will tell you)
- CHANGELOG entry under
Unreleased - Security-relevant? β a
13_securitycase proving the guard, and mention it in the PR description
-
Bugs: issue with
version()banner, minimal template + data, expected vs actual, diagnostics dump. A failing test snippet is a fast lane. - Ideas: Discussions β Ideas; accepted items move onto the ROADMAP with a label.
- Security: private report only β see Security β Reporting.
- Conduct: be excellent to each other; critique code, not people.
HTML.PHP 5.0.0 Β· MIT Β© Mikhail Deynekin Β· Repository Β· Releases Β· Report a security issue
Wiki pages mirror docs/ β found a mistake? Edit the page or open an issue.
π Home Problem Domain Getting Started
Template Syntax Expressions & Math SSI Guide I18n Guide WordPress Integration CLI
Configuration API Cheatsheet Diagnostics & Troubleshooting
Architecture Security Model Testing & CI
πΊοΈ ROADMAP Migration 4.x β 5.0 Migration 3.x β 4.0 Contributing Repository β