Architektura
TailwindPHP je port v poměru 1:1. Struktura kódové základny zrcadlí původní uspořádání TailwindCSS — stejné názvy souborů i členění — a části, které nelze přímo portovat (PHP nemá Rust ani V8), odděluje pod src/_tailwindphp/. Tato stránka popisuje průběh kompilace, uspořádání zdrojových souborů, novou implementaci lightningcss a konvenci pro dokumentování odchylek.
Postup zpracování
Generování CSS probíhá v několika fázích. Samostatný krok sestavení neexistuje — každé volání tw::generate() spustí celý proces.
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
Parsování. css-parser.php načte vstup CSS — @import, @theme, @utility, @layer i nezpracovaná pravidla — do abstraktního syntaktického stromu uzlů ast.php (pravidla stylů, pravidla at, deklarace). V této fázi se vyhodnotí a nahradí direktivy @import pro virtuální moduly (tailwindcss, tailwindcss/preflight, …) i cesty k souborům.
Sestavení návrhového systému. theme.php vyhodnotí hodnoty motivu (barvy, rozestupy, body zlomu) z naparsovaných bloků @theme a výchozích hodnot. design-system.php je centrální registr, který propojuje motiv s vyhledáváním utilit a variant definovaným v utilities.php a variants.php.
Prohledání obsahu. candidate.php z dodaného obsahu (HTML, šablony) získá kandidáty názvů tříd a rozloží každého na části — základní utilitu, varianty, modifikátory, libovolné hodnoty a příznak important.
Kompilace. compile.php převede každého kandidáta na uzly AST tak, že jej vyhledá v návrhovém systému a použije jeho varianty a modifikátory. Kandidáty, které neodpovídají skutečné utilitě, zahodí.
Serializace a optimalizace. toCss() ast.php prochází strom (pomocné funkce v walk.php) a vytváří řetězec CSS. Použijí se transformace odpovídající lightningcss v _tailwindphp/LightningCss.php, aby výstup odpovídal tomu, co vytváří TailwindCSS po průchodu následným zpracováním Rust.
Minifikace. Je-li povoleno minify, toCss() při serializaci vytváří minifikované CSS. _tailwindphp/CssMinifier.php zajišťuje samostatný průchod řetězcem tw::minify(). Viz Ukládání do mezipaměti a minifikace.
Uspořádání zdrojových souborů
src/ zrcadlí TailwindCSS. Jediná strukturální změna: soubor utilities.ts v TailwindCSS má přes 6,000 řádků, proto je kvůli snazší údržbě rozdělen do src/utilities/, s jedním souborem pro každou kategorii.
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
Obdoba lightningcss
TailwindCSS přenechává následné zpracování CSS — vnořování, zpracování mediálních dotazů a zjednodušování hodnot — nástroji lightningcss, parseru, transformátoru a minifikátoru napsanému v Rust. PHP nemůže načítat knihovnu Rust, proto src/_tailwindphp/LightningCss.php znovu implementuje transformace, na které se TailwindPHP skutečně spoléhá; ve scénářích pokrytých testovací sadou tak vytváří bajtově totožný výstup.
Mezi ověřené transformace patří:
| Transformace | Co dělá |
|---|---|
| Zploštění vnoření | Vyhodnotí selektory & podle pravidel :is(…) referenční implementace a zploští vnořená pravidla (handleNesting() v ast.php, port průchodu TailwindCSS); transformNesting převede na nižší verzi vnoření, které zůstalo pod první úrovní nesoucí deklarace |
| Zploštění podmíněných pravidel at | Zploští vnořené @media, @supports, @container a @starting-style na místě, zachová pořadí ve zdroji a sloučí pouze přímo sousedící prvky se stejnými podmínkami |
| Pořadí deklarací | Přeskládá deklarace podle řetězce obslužných funkcí deklarací lightningcss, aby vlastnosti měly pořadí referenční implementace (reorderDeclarations) |
Zjednodušení calc() |
Zjednoduší výrazy calc() (simplifyCalcExpressions) |
| Odstranění úvodní nuly | 0.5 → .5 (normalizeLeadingZeros) |
| Mezery ve transformačních funkcích | Normalizuje mezery uvnitř transformačních funkcí (normalizeTransformFunctions) |
| Normalizace hodnot gridu | Přidá mezery kolem / v hodnotách span, holá celá čísla převede na px pro grid-template-* (normalizeGridValues) |
| Normalizace barev | Normalizuje zápis barev a vyhodnotí color-mix() na oklab() (normalizeColors, evaluateColorMix) |
| Uvozovky v URL | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Prefixy dodavatele | Prefixování odpovídající Autoprefixer (addVendorPrefixes) |
Tento soubor je záměrně izolován pod _tailwindphp/ a označen jako @port-deviation:replacement — zastupuje externí závislost, místo aby portoval zdrojový kód TailwindCSS.
Značky odchylek portu
Každý implementační soubor obsahuje ve svém docblocku značky @port-deviation:*, které uvádějí, kde a proč se implementace PHP odlišuje od původní verze TypeScript. Čtenář porovnávající PHP se zdrojovým kódem TailwindCSS tak nemusí přemýšlet, zda je určitý rozdíl záměrný.
| Značka | Význam |
|---|---|
@port-deviation:none |
Přímý port 1:1 bez významných odchylek |
@port-deviation:async |
PHP používá synchronní kód místo async/await |
@port-deviation:storage |
Odlišné datové struktury (pole PHP oproti Map/Set JS) |
@port-deviation:types |
Anotace PHPDoc místo typů TypeScript |
@port-deviation:sourcemaps |
Sledování zdrojových map vynecháno |
@port-deviation:enum |
Konstanty PHP místo výčtových typů TypeScript |
@port-deviation:errors |
Odlišný přístup ke zpracování chyb |
@port-deviation:replacement |
Implementace PHP nahrazující externí knihovnu (e.g. lightningcss) |
@port-deviation:helper |
Pomocná funkce specifická pro PHP, která v originálu není |
@port-deviation:performance |
Optimalizace specifická pro PHP, která zachovává totožný výstup |
@port-deviation:omitted |
Celý modul/funkce nebyl portován (mimo rozsah) |
Značky @port-deviation:performance a způsob vynucování shody popisuje stránka Výkon a testování.