Architectuur
TailwindPHP is een 1:1-port. De codebase volgt de eigen structuur van TailwindCSS: dezelfde bestandsnamen en indeling. Onderdelen die niet rechtstreeks kunnen worden geporteerd (PHP heeft geen Rust en geen V8) zijn ondergebracht in src/_tailwindphp/. Op deze pagina komen de compilatiepipeline, de bronindeling, de herimplementatie van lightningcss en de conventie voor het documenteren van afwijkingen aan bod.
De pipeline
Het genereren van CSS verloopt in meerdere fasen. Er is geen afzonderlijke buildstap: elke aanroep van tw::generate() voert de volledige pipeline uit.
CSS input (@import "tailwindcss"; @theme { … })
│
▼
┌──────────────┐
│ Parse CSS │ css-parser.php → ast.php nodes
└──────┬───────┘
▼ design system (theme, utilities, variants)
┌──────────────┐
│ Scan content │ candidate.php — extract class names from HTML
└──────┬───────┘
▼ candidates
┌──────────────┐
│ Compile │ compile.php — candidate → AST, via design-system.php
└──────┬───────┘
▼ AST
┌──────────────┐
│ Optimize │ _tailwindphp/LightningCss.php — nesting, @media, calc()
└──────┬───────┘
▼
┌──────────────┐
│ Serialize │ ast.php toCss() (minified when requested)
└──────┬───────┘
▼
CSS output
Parsen. css-parser.php leest de CSS-invoer — @import, @theme, @utility, @layer en ruwe regels — in een abstracte syntaxboom met ast.php-nodes (stijlregels, at-regels en declaraties). @import-directives voor virtuele modules (tailwindcss, tailwindcss/preflight, …) en bestandspaden worden in deze fase opgelost en vervangen.
Het designsysteem opbouwen. theme.php haalt themawaarden (kleuren, tussenruimtes en breekpunten) op uit de geparste blokken van @theme, aangevuld met de standaardwaarden. design-system.php is het centrale register dat het thema koppelt aan de utility- en variantzoekopdrachten die zijn gedefinieerd in utilities.php en variants.php.
Inhoud scannen. candidate.php haalt mogelijke klassennamen op uit de opgegeven inhoud (HTML, templates) en splitst elke kandidaat op in onderdelen: basisutility, varianten, modifiers, willekeurige waarden en belangrijke markering.
Compileren. compile.php zet elke kandidaat om in AST-nodes door die op te zoeken in het designsysteem en de varianten en modifiers toe te passen. Kandidaten die niet overeenkomen met een bestaande utility worden verwijderd.
Serialiseren en optimaliseren. De toCss() van ast.php doorloopt de boom (met helpers in walk.php) en genereert de CSS-tekenreeks. De transforms in _tailwindphp/LightningCss.php die overeenkomen met lightningcss worden toegepast, zodat de uitvoer overeenkomt met die van TailwindCSS na de Rust-nabehandeling.
Minificeren. Wanneer minify is ingeschakeld, genereert toCss() tijdens het serialiseren geminificeerde CSS. _tailwindphp/CssMinifier.php verwerkt de zelfstandige passage over tw::minify()-tekenreeksen. Zie Caching en minificatie.
Bronindeling
src/ weerspiegelt TailwindCSS. De enige structurele wijziging: de TailwindCSSutilities.ts telt 6,000+ regels en is daarom opgesplitst in src/utilities/, met één bestand per categorie voor beter onderhoud.
src/
├── _tailwindphp/ # PHP-specific — NOT part of the TailwindCSS port
│ ├── LightningCss.php # CSS transforms (lightningcss Rust library equivalent)
│ ├── CssMinifier.php # CSS minification
│ └── lib/ # Companion library ports (TailwindPHP\Lib\*)
│ ├── clsx/ # clsx port
│ ├── tailwind-merge/ # tailwind-merge port
│ └── cva/ # CVA port
│
├── plugin/ # Plugin system
│ └── plugins/
│ ├── typography-plugin.php # @tailwindcss/typography port
│ └── forms-plugin.php # @tailwindcss/forms port
│
├── utilities/ # Split from TailwindCSS utilities.ts (one file per category)
│ ├── accessibility.php # sr-only, forced-colors
│ ├── backgrounds.php # bg-*, gradient-*, from-*, via-*, to-*
│ ├── borders.php # border-*, rounded-*, divide-*, outline-*
│ ├── effects.php # shadow-*, opacity-*, mix-blend-*
│ ├── filters.php # blur-*, brightness-*, contrast-*, …
│ ├── flexbox.php # flex-*, grid-*, gap-*, justify-*, align-*
│ ├── interactivity.php # cursor-*, scroll-*, touch-*, select-*
│ ├── layout.php # display, position, z-*, overflow-*, …
│ ├── masks.php # mask-linear-*, mask-radial-*, mask-conic-*
│ ├── sizing.php # w-*, h-*, min-*, max-*, size-*
│ ├── spacing.php # m-*, p-*, space-*
│ ├── svg.php # fill-*, stroke-*
│ ├── tables.php # border-collapse, table-layout
│ ├── transforms.php # translate-*, rotate-*, scale-*, skew-*
│ ├── transitions.php # transition-*, duration-*, ease-*, delay-*
│ └── typography.php # font-*, text-*, leading-*, tracking-*
│
├── utils/ # Helper functions (ported from utils/)
│
├── index.php # Main entry — compile(), cn(), variants(), merge(), join()
├── ast.php # AST nodes and toCss()
├── candidate.php # Candidate parsing (class name → parts)
├── compile.php # Candidate to CSS compilation
├── css-functions.php # theme(), --theme(), --spacing(), --alpha()
├── css-parser.php # CSS parsing
├── design-system.php # Central registry for utilities/variants
├── plugin.php # Plugin system (PluginInterface, PluginAPI, PluginManager)
├── theme.php # Theme value resolution
├── utilities.php # Utility registration and lookup
├── value-parser.php # CSS value parsing
├── variants.php # Variant handling (hover, focus, responsive, …)
└── walk.php # AST traversal
Het lightningcss-equivalent
TailwindCSS delegeert de nabewerking van CSS — nesting, verwerking van mediaquery's en vereenvoudiging van waarden — aan lightningcss, een parser/transformer/minifier geschreven in Rust. PHP kan geen bibliotheek in Rust laden, dus src/_tailwindphp/LightningCss.php implementeert de transformaties waarop TailwindPHP daadwerkelijk vertrouwt opnieuw. Voor de gevallen die de testsuite dekt, levert dat byte-identieke uitvoer op.
Bevestigde transformaties zijn onder andere:
| Transformatie | Wat deze doet |
|---|---|
| Nesting afvlakken | Lost &-selectors op met de :is(…)-regels van de referentie en vlakt geneste regels af (handleNesting() in ast.php, een port van de TailwindCSS-pass); transformNesting zet de nesting die onder het eerste niveau met declaraties overblijft om naar een lager niveau |
| Conditionele at-rule's afvlakken | Vlakt geneste @media, @supports, @container en @starting-style ter plekke af, behoudt de bronvolgorde en voegt alleen direct aangrenzende broers met identieke voorwaarden samen |
| Declaraties ordenen | Herordent declaraties volgens de declaration-handler-keten van lightningcss, zodat eigenschappen in de volgorde van de referentie verschijnen (reorderDeclarations) |
calc()-vereenvoudiging |
Vereenvoudigt calc()-expressies (simplifyCalcExpressions) |
| Voorloopnullen verwijderen | 0.5 → .5 (normalizeLeadingZeros) |
| Spatiëring van transform-functies | Normaliseert de spatiëring binnen transform-functies (normalizeTransformFunctions) |
| Grid-waarden normaliseren | Voegt spaties toe rond / in span-waarden; zet kale gehele getallen om naar px voor grid-template-* (normalizeGridValues) |
| Kleuren normaliseren | Normaliseert kleursyntaxis en evalueert color-mix() naar oklab() (normalizeColors, evaluateColorMix) |
| URL quoten | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Leveranciersprefixen | Prefixen equivalent aan Autoprefixer (addVendorPrefixes) |
Dit bestand is bewust onder _tailwindphp/ afgezonderd en gemarkeerd als @port-deviation:replacement — het staat voor een externe afhankelijkheid en is geen port van de broncode van TailwindCSS.
Markeringen voor afwijkingen in de port
Elk implementatiebestand bevat @port-deviation:*-markeringen in de docblock, die aangeven waar en waarom de PHP-implementatie afwijkt van het origineel van TypeScript. Zo hoeft een lezer die PHP met de bron van TailwindCSS vergelijkt nooit te twijfelen of een verschil opzettelijk is.
| Markering | Betekenis |
|---|---|
@port-deviation:none |
Directe port van 1:1, zonder significante afwijkingen |
@port-deviation:async |
PHP gebruikt synchrone code in plaats van async/await |
@port-deviation:storage |
Andere datastructuren (PHP-array tegenover JS Map/Set) |
@port-deviation:types |
PHPDoc-annotaties in plaats van TypeScript-typen |
@port-deviation:sourcemaps |
Bronkaart-tracking ontbreekt |
@port-deviation:enum |
PHP-constanten in plaats van TypeScript-enum's |
@port-deviation:errors |
Andere aanpak voor foutafhandeling |
@port-deviation:replacement |
PHP-implementatie vervangt een externe bibliotheek (e.g. lightningcss) |
@port-deviation:helper |
Hulpfunctie specifiek voor PHP die niet in het origineel zit |
@port-deviation:performance |
Optimalisatie specifiek voor PHP die identieke uitvoer behoudt |
@port-deviation:omitted |
Volledige module/functie niet geport (valt buiten de scope) |
Zie Prestaties en testen voor de @port-deviation:performance-markeringen en hoe pariteit wordt afgedwongen.