Architettura
TailwindPHP è una portabilità 1:1. La codebase rispecchia la struttura originale di TailwindCSS: stessi nomi di file e stessa organizzazione; le parti che non possono essere portate direttamente (PHP non ha Rust né V8) sono isolate sotto src/_tailwindphp/. Questa pagina illustra la pipeline di compilazione, l'organizzazione dei sorgenti, la reimplementazione di lightningcss e la convenzione usata per documentare le differenze.
La pipeline
La generazione di CSS è una sequenza di fasi. Non c'è un passaggio di build separato: ogni chiamata a tw::generate() esegue l'intera pipeline.
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
Analisi. css-parser.php legge l'input CSS: @import, @theme, @utility, @layer, regole raw; e lo trasforma in un albero sintattico astratto composto da nodi ast.php (regole di stile, at-rule, dichiarazioni). In questa fase vengono risolte e sostituite le direttive @import per i moduli virtuali (tailwindcss, tailwindcss/preflight, …) e i percorsi dei file.
Costruzione del sistema di design. theme.php risolve i valori del tema (colori, spaziatura, breakpoint) dai blocchi @theme analizzati e dai valori predefiniti. design-system.php è il registro centrale che collega il tema alle definizioni di utilità e varianti in utilities.php e variants.php.
Scansione dei contenuti. candidate.php estrae i candidati per i nomi delle classi dai contenuti forniti (HTML, template) e scompone ciascuno nelle sue parti: utilità di base, varianti, modificatori, valori arbitrari e flag important.
Compilazione. compile.php converte ogni candidato in nodi AST cercandolo nel sistema di design e applicando varianti e modificatori. I candidati che non corrispondono a un'utilità reale vengono scartati.
Serializzazione e ottimizzazione. ast.php percorre l'albero con il suo toCss() (helper in walk.php) e genera la stringa CSS. Vengono applicate in _tailwindphp/LightningCss.php le trasformazioni equivalenti a lightningcss, così l'output corrisponde a quello prodotto da TailwindCSS dopo il passaggio di post-elaborazione Rust.
Minificazione. Quando minify è abilitato, toCss() genera CSS minificato durante la serializzazione. _tailwindphp/CssMinifier.php gestisce il passaggio autonomo sulla stringa tw::minify(). Consultate Cache e minificazione.
Organizzazione dei sorgenti
src/ rispecchia TailwindCSS. L'unica modifica strutturale: TailwindCSSutilities.ts contiene più di 6,000 righe, quindi è suddiviso in src/utilities/, con un file per categoria, per facilitarne la manutenzione.
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
L'equivalente di lightningcss
TailwindCSS delega a lightningcss, un parser/trasformatore/minificatore scritto in Rust, la post-elaborazione di CSS: annidamento, gestione delle media query e semplificazione dei valori. PHP non può caricare una libreria Rust, quindi src/_tailwindphp/LightningCss.php reimplementa le trasformazioni su cui TailwindPHP fa effettivamente affidamento, producendo un output identico byte per byte nei casi coperti dalla suite di test.
Trasformazioni confermate:
| Trasformazione | Cosa fa |
|---|---|
| Appiattimento dell'annidamento | Risolve i selettori & con le regole :is(…) di riferimento e appiattisce le regole annidate (handleNesting() in ast.php, port dell'elaborazione TailwindCSS); transformNesting riduce il livello delle regole annidate rimaste sotto il primo livello che contiene dichiarazioni |
| Appiattimento delle regole at-rule condizionali | Appiattisce sul posto le regole @media, @supports, @container e @starting-style annidate, mantenendo l'ordine del sorgente e unendo solo i fratelli direttamente adiacenti con condizioni identiche |
| Ordinamento delle dichiarazioni | Riordina le dichiarazioni secondo la catena di gestione delle dichiarazioni di lightningcss, così le proprietà seguono l'ordine di riferimento (reorderDeclarations) |
Semplificazione di calc() |
Semplifica le espressioni calc() (simplifyCalcExpressions) |
| Rimozione degli zeri iniziali | 0.5 → .5 (normalizeLeadingZeros) |
| Spaziatura delle funzioni di trasformazione | Normalizza gli spazi all'interno delle funzioni di trasformazione (normalizeTransformFunctions) |
| Normalizzazione dei valori della griglia | Aggiunge spazi intorno a / nei valori span; converte gli interi senza unità in px per grid-template-* (normalizeGridValues) |
| Normalizzazione dei colori | Normalizza la sintassi dei colori e valuta color-mix() in oklab() (normalizeColors, evaluateColorMix) |
| Virgolette per URL | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Prefissi dei vendor | Aggiunge prefissi equivalenti a Autoprefixer (addVendorPrefixes) |
Questo file è intenzionalmente isolato sotto _tailwindphp/ e contrassegnato come @port-deviation:replacement: funge da dipendenza esterna invece di portare il sorgente di TailwindCSS.
Marcatori delle differenze del port
Ogni file di implementazione contiene marcatori @port-deviation:* nel docblock che indicano dove e perché l'implementazione PHP si discosta dall'originale TypeScript. L'obiettivo è consentire a chi confronta PHP con il sorgente di TailwindCSS di capire subito se una differenza è intenzionale.
| Marcatore | Significato |
|---|---|
@port-deviation:none |
Port diretto 1:1 senza differenze significative |
@port-deviation:async |
PHP usa codice sincrono invece di async/await |
@port-deviation:storage |
Strutture dati diverse (array PHP invece di Map/Set JS) |
@port-deviation:types |
Annotazioni PHPDoc invece dei tipi TypeScript |
@port-deviation:sourcemaps |
Tracciamento delle source map omesso |
@port-deviation:enum |
Costanti PHP invece di enum TypeScript |
@port-deviation:errors |
Approccio diverso alla gestione degli errori |
@port-deviation:replacement |
Implementazione PHP che sostituisce una libreria esterna (e.g. lightningcss) |
@port-deviation:helper |
Helper specifico di PHP, non presente nell'originale |
@port-deviation:performance |
Ottimizzazione specifica di PHP che mantiene un output identico |
@port-deviation:omitted |
Modulo/funzionalità non portato/a (fuori ambito) |
Per i marcatori @port-deviation:performance e il modo in cui viene garantita la parità, consultate Prestazioni e test.