Přejít k obsahu

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.

Kód
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.

Kód
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í.