
# 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](https://tailwindphp.inline0.dev/nl/docs/advanced/caching).

## Bronindeling

`src/` weerspiegelt TailwindCSS. De enige structurele wijziging: de TailwindCSS`utilities.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](https://lightningcss.dev/), 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](https://tailwindphp.inline0.dev/nl/docs/advanced/performance) voor de `@port-deviation:performance`-markeringen en hoe pariteit wordt afgedwongen.
