Architektura
TailwindPHP to port 1:1. Baza kodu odwzorowuje własną strukturę TailwindCSS — te same nazwy plików i ten sam układ — a części, których nie da się przenieść bezpośrednio (PHP nie ma Rust ani V8), izoluje w src/_tailwindphp/. Ta strona opisuje potok kompilacji, układ źródeł, ponowną implementację lightningcss oraz konwencję dokumentowania różnic.
Potok przetwarzania
Generowanie CSS to sekwencja etapów. Nie ma osobnego etapu budowania — każde wywołanie tw::generate() uruchamia cały potok.
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
Parsowanie. css-parser.php odczytuje wejście CSS — @import, @theme, @utility, @layer i surowe reguły — do postaci abstrakcyjnego drzewa składniowego z węzłami ast.php (reguły stylów, reguły at i deklaracje). Dyrektywy @import dotyczące modułów wirtualnych (tailwindcss, tailwindcss/preflight, …) oraz ścieżki plików są rozwiązywane i podstawiane na tym etapie.
Budowanie systemu projektowego. theme.php rozwiązuje wartości motywu (kolory, odstępy, punkty przerwania) na podstawie sparsowanych bloków @theme i wartości domyślnych. design-system.php to centralny rejestr łączący motyw z wyszukiwaniem klas użytkowych i wariantów zdefiniowanym w utilities.php oraz variants.php.
Skanowanie treści. candidate.php wyodrębnia kandydatów na nazwy klas z dostarczonej treści (HTML, szablonów) i dzieli każdego na części — bazową klasę użytkową, warianty, modyfikatory, dowolne wartości oraz flagę important.
Kompilacja. compile.php przekształca każdego kandydata w węzły AST, wyszukując go w systemie projektowym i stosując warianty oraz modyfikatory. Kandydaci, którzy nie odpowiadają rzeczywistej klasie użytkowej, są odrzucani.
Serializacja i optymalizacja. ast.php's toCss() przechodzi przez drzewo (z użyciem funkcji pomocniczych z walk.php) i generuje ciąg CSS. Stosowane są przekształcenia równoważne lightningcss z _tailwindphp/LightningCss.php, dzięki czemu wynik odpowiada temu, co generuje TailwindCSS po etapie przetwarzania końcowego Rust.
Minifikacja. Gdy minifikacja minify jest włączona, toCss() generuje zminifikowany CSS podczas serializacji. _tailwindphp/CssMinifier.php obsługuje samodzielny etap przetwarzania ciągu tw::minify(). Zobacz Buforowanie i minifikacja.
Układ źródeł
src/ odwzorowuje TailwindCSS. Jedyna zmiana strukturalna: TailwindCSS's utilities.ts ma 6,000+ wierszy, więc podzielono go na src/utilities/ z osobnym plikiem dla każdej kategorii, aby ułatwić utrzymanie.
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
Odpowiednik lightningcss
TailwindCSS zleca lightningcss, parserowi, transformatorowi i minifikatorowi napisanemu w Rust, przetwarzanie końcowe CSS — obsługę zagnieżdżeń, zapytań medialnych i upraszczanie wartości. PHP nie może załadować biblioteki Rust, dlatego src/_tailwindphp/LightningCss.php ponownie implementuje przekształcenia, z których faktycznie korzysta TailwindPHP, generując identyczny wynik bajt po bajcie dla przypadków objętych zestawem testów.
Potwierdzone przekształcenia obejmują:
| Przekształcenie | Działanie |
|---|---|
| Spłaszczanie zagnieżdżeń | Rozwiązuje selektory & zgodnie z regułami :is(…) referencji i spłaszcza zagnieżdżone reguły (handleNesting() w ast.php, port etapu TailwindCSS); transformNesting obniża poziom zagnieżdżeń pozostających poniżej pierwszego poziomu zawierającego deklaracje |
| Spłaszczanie warunkowych reguł at | Spłaszcza zagnieżdżone @media, @supports, @container i @starting-style w miejscu ich wystąpienia, zachowując kolejność źródłową; łączy tylko bezpośrednio sąsiadujące elementy z identycznymi warunkami |
| Kolejność deklaracji | Zmienia kolejność deklaracji zgodnie z łańcuchem obsługi deklaracji lightningcss, aby właściwości pojawiały się w kolejności referencyjnej (reorderDeclarations) |
Upraszczanie calc() |
Upraszcza wyrażenia calc() (simplifyCalcExpressions) |
| Usuwanie zer wiodących | 0.5 → .5 (normalizeLeadingZeros) |
| Odstępy w funkcjach przekształceń | Normalizuje odstępy wewnątrz funkcji przekształceń (normalizeTransformFunctions) |
| Normalizacja wartości siatki | Dodaje spacje wokół / w wartościach span; zamienia same liczby całkowite na px dla grid-template-* (normalizeGridValues) |
| Normalizacja kolorów | Normalizuje składnię kolorów i oblicza color-mix() do postaci oklab() (normalizeColors, evaluateColorMix) |
| Cytowanie URL | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Prefiksy dostawców | Dodawanie prefiksów równoważne Autoprefixer (addVendorPrefixes) |
Ten plik został celowo odizolowany w _tailwindphp/ i oznaczony jako @port-deviation:replacement — zastępuje zewnętrzną zależność, zamiast przenosić kod źródłowy TailwindCSS.
Oznaczenia różnic w porcie
Każdy plik implementacji zawiera w bloku dokumentacji oznaczenia @port-deviation:*, które wskazują, gdzie i dlaczego implementacja PHP różni się od oryginału TypeScript. Dzięki temu osoba porównująca PHP z kodem źródłowym TailwindCSS nie musi się zastanawiać, czy dana różnica jest zamierzona.
| Oznaczenie | Znaczenie |
|---|---|
@port-deviation:none |
Bezpośredni port 1:1 bez istotnych różnic |
@port-deviation:async |
PHP używa kodu synchronicznego zamiast async/await |
@port-deviation:storage |
Inne struktury danych (tablica PHP zamiast Map/Set JS) |
@port-deviation:types |
Adnotacje PHPDoc zamiast typów TypeScript |
@port-deviation:sourcemaps |
Pominięto śledzenie mapy źródłowej |
@port-deviation:enum |
Stałe PHP zamiast wyliczeń TypeScript |
@port-deviation:errors |
Inne podejście do obsługi błędów |
@port-deviation:replacement |
Implementacja PHP zastępująca zewnętrzną bibliotekę (e.g. lightningcss) |
@port-deviation:helper |
Funkcja pomocnicza specyficzna dla PHP, nieobecna w oryginale |
@port-deviation:performance |
Optymalizacja specyficzna dla PHP, która zachowuje identyczny wynik |
@port-deviation:omitted |
Cały moduł lub funkcja nie zostały przeniesione (poza zakresem) |
Więcej informacji o oznaczeniach @port-deviation:performance i zapewnianiu zgodności znajdziesz w sekcji Wydajność i testowanie.