Arkitektur
TailwindPHP er en 1:1-portering. Kodebasen afspejler TailwindCSSs egen struktur — samme filnavne, samme organisering — og isolerer de dele, der ikke kan porteres direkte (PHP har ingen Rust og ingen V8), under src/_tailwindphp/. Denne side gennemgår kompileringspipelinen, kildelayoutet, genimplementeringen af lightningcss og konventionen for dokumentation af afvigelser.
Pipelineforløbet
Generering af CSS består af en række trin. Der er intet separat buildtrin — hvert kald til tw::generate() kører hele pipelinen.
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
Parse. css-parser.php læser CSS-inputtet — @import, @theme, @utility, @layer og rå regler — ind i et abstrakt syntakstræ med ast.php-noder (stilregler, at-regler, deklarationer). @import-direktiver for virtuelle moduler (tailwindcss, tailwindcss/preflight, …) og filstier afklares og indsættes på dette trin.
Byg designsystemet. theme.php afklarer temaværdier (farver, afstande, brudpunkter) fra de fortolkede @theme-blokke plus standardværdierne. design-system.php er det centrale register, der forbinder temaet med opslagene for værktøjer og varianter, som defineres i utilities.php og variants.php.
Scan indhold. candidate.php udtrækker kandidater til klassenavne fra det angivne indhold (HTML, skabeloner) og opdeler hver kandidat i dens dele — basisværktøj, varianter, modifikatorer, vilkårlige værdier og vigtigt-flag.
Kompilér. compile.php omdanner hver kandidat til AST-noder ved at slå den op i designsystemet og anvende dens varianter og modifikatorer. Kandidater, der ikke svarer til et reelt værktøj, kasseres.
Serialisér og optimér. ast.phps toCss() gennemløber træet (hjælpefunktioner i walk.php) og udsender CSS-strengen. Transformationerne svarende til lightningcss i _tailwindphp/LightningCss.php anvendes, så outputtet matcher det, TailwindCSS producerer efter sin efterbehandlingsfase med Rust.
Minificér. Når minify er aktiveret, udsender toCss() minificeret CSS under serialisering. _tailwindphp/CssMinifier.php står bag den selvstændige tw::minify()-strengbehandling. Se Caching og minificering.
Kildelayout
src/ afspejler TailwindCSS. Den eneste strukturelle ændring: TailwindCSSs utilities.ts fylder 6,000+ linjer, så den er opdelt i src/utilities/ med én fil pr. kategori for at lette vedligeholdelsen.
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
lightningcss-ækvivalenten
TailwindCSS overlader sin efterbehandling af CSS — nesting, håndtering af media queries og forenkling af værdier — til lightningcss, en parser/transformer/minificerer skrevet i Rust. PHP kan ikke indlæse et Rust-bibliotek, så src/_tailwindphp/LightningCss.php genimplementerer de transformationer, som TailwindPHP faktisk bruger, og producerer byteidentisk output for de tilfælde, som testsuiten dækker.
Bekræftede transformationer omfatter:
| Transformation | Hvad den gør |
|---|---|
| Udfladning af nesting | Afklarer &-selektorer med referencens :is(…)-regler og udflader indlejrede regler (handleNesting() i ast.php, en portering af passet TailwindCSS); transformNesting nedgraderer den resterende nesting under det første niveau med deklarationer |
| Udfladning af betingede at-regler | Udflader indlejrede @media, @supports, @container og @starting-style på stedet, bevarer kilderækkefølgen og sammenfletter kun direkte tilstødende søskende med identiske betingelser |
| Rækkefølge af deklarationer | Omarrangerer deklarationer efter lightningcss' kæde af deklarationsbehandlere, så egenskaberne følger referencens rækkefølge (reorderDeclarations) |
Forenkling af calc() |
Forenkler calc()-udtryk (simplifyCalcExpressions) |
| Fjernelse af indledende nul | 0.5 → .5 (normalizeLeadingZeros) |
| Afstand i transform-funktioner | Normaliserer mellemrum i transform-funktioner (normalizeTransformFunctions) |
| Normalisering af grid-værdier | Tilføjer mellemrum omkring / i span-værdier, bare heltal → px for grid-template-* (normalizeGridValues) |
| Normalisering af farver | Normaliserer farvesyntaks og evaluerer color-mix() til oklab() (normalizeColors, evaluateColorMix) |
| Citering af URL | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Leverandørpræfikser | Præfiksering svarende til Autoprefixer (addVendorPrefixes) |
Denne fil er bevidst placeret i karantæne under _tailwindphp/ og markeret @port-deviation:replacement — den repræsenterer en ekstern afhængighed i stedet for at portere TailwindCSS-kildekode.
Markører for porteringsafvigelser
Hver implementeringsfil indeholder @port-deviation:*-markører i sin docblock, der angiver, hvor og hvorfor PHP-implementeringen afviger fra originalen i TypeScript. Målet er, at læsere, der sammenligner PHP med TailwindCSS-kildekode, aldrig skal være i tvivl om, hvorvidt en forskel er tilsigtet.
| Markør | Betydning |
|---|---|
@port-deviation:none |
Direkte 1:1-portering uden væsentlige afvigelser |
@port-deviation:async |
PHP bruger synkron kode i stedet for async/await |
@port-deviation:storage |
Forskellige datastrukturer (PHP-array mod JS Map/Set) |
@port-deviation:types |
PHPDoc-annoteringer i stedet for TypeScript-typer |
@port-deviation:sourcemaps |
Sporing af source maps udeladt |
@port-deviation:enum |
PHP-konstanter i stedet for TypeScript-enumtyper |
@port-deviation:errors |
Anderledes fejlhåndtering |
@port-deviation:replacement |
PHP-implementering erstatter et eksternt bibliotek (e.g. lightningcss) |
@port-deviation:helper |
Hjælpefunktion specifik for PHP, som ikke findes i originalen |
@port-deviation:performance |
Optimering specifik for PHP, der bevarer identisk output |
@port-deviation:omitted |
Hele modulet/funktionen er ikke porteret (uden for omfanget) |
Se Ydeevne og test for markørerne @port-deviation:performance og for at se, hvordan paritet håndhæves.