Архитектура
TailwindPHP е порт 1:1. Структурата на кодовата база отразява тази на TailwindCSS – същите имена и организация на файловете – а частите, които не могат да бъдат пренесени директно (PHP няма Rust и V8), са изолирани в src/_tailwindphp/. Тази страница описва процеса на компилиране, подредбата на изходния код, повторната реализация на lightningcss и конвенцията за документиране на отклоненията.
Конвейерът
Генерирането на CSS преминава през поредица от етапи. Няма отделна стъпка за изграждане – всяко извикване на tw::generate() изпълнява целия процес.
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
Анализиране. css-parser.php чете входа CSS – @import, @theme, @utility, @layer и необработени правила – и го преобразува в абстрактно синтактично дърво от възли ast.php (стилови правила, at-правила, декларации). На този етап се разрешават и заместват директивите @import за виртуални модули (tailwindcss, tailwindcss/preflight, …) и файловите пътища.
Изграждане на системата за дизайн. theme.php разрешава стойностите на темата (цветове, отстояния, точки на прекъсване) от анализираните блокове @theme и стойностите по подразбиране. design-system.php е централният регистър, който свързва темата с търсенето на помощни класове и варианти, дефинирано в utilities.php и variants.php.
Сканиране на съдържанието. candidate.php извлича възможните имена на класове от подаденото съдържание (HTML, шаблони) и разделя всяко на съставните му части – базов помощен клас, варианти, модификатори, произволни стойности и флаг за важно правило.
Компилиране. compile.php преобразува всеки кандидат във възли на AST, като го търси в системата за дизайн и прилага вариантите и модификаторите му. Кандидатите, които не съответстват на реален помощен клас, се отхвърлят.
Сериализиране и оптимизиране. toCss() на ast.php обхожда дървото (с помощни функции от walk.php) и извежда низа CSS. Прилагат се преобразуванията, еквивалентни на lightningcss, от _tailwindphp/LightningCss.php, за да съответства резултатът на генерирания от TailwindCSS след неговия етап на последваща обработка Rust.
Минифициране. Когато minify е включено, toCss() генерира минифициран CSS при сериализирането. _tailwindphp/CssMinifier.php осигурява самостоятелната обработка на низа tw::minify(). Вижте Кеширане и минифициране.
Подредба на изходния код
src/ отразява TailwindCSS. Единствената структурна промяна: utilities.ts на TailwindCSS съдържа над 6,000 реда и затова е разделен на src/utilities/ с по един файл за категория, за по-лесна поддръжка.
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
TailwindCSS възлага последващата обработка на CSS – влагане, обработка на медийни заявки, опростяване на стойности – на lightningcss, анализатор/преобразувател/минимизатор, написан на Rust. PHP не може да зарежда библиотека Rust, затова src/_tailwindphp/LightningCss.php реализира отново преобразуванията, на които разчита TailwindPHP, и генерира побайтово идентичен резултат за случаите, обхванати от тестовия набор.
Потвърдените преобразувания включват:
| Преобразуване | Какво прави |
|---|---|
| Сплескване на влагането | Разрешава селекторите & според правилата :is(…) на еталонната реализация и сплесква вложените правила (handleNesting() в ast.php, порт на етапа TailwindCSS); transformNesting преобразува вложените правила, останали под първото ниво с декларации, за по-стари версии |
| Сплескване на условните at-правила | Сплесква вложените @media, @supports, @container и @starting-style на място, запазва реда в източника и обединява само непосредствено съседни елементи с еднакви условия |
| Подреждане на декларациите | Подрежда декларациите според веригата от обработчици на декларации на lightningcss, така че свойствата да излизат в реда на еталонната реализация (reorderDeclarations) |
Опростяване на calc() |
Опростява изразите calc() (simplifyCalcExpressions) |
| Премахване на водещи нули | 0.5 → .5 (normalizeLeadingZeros) |
| Интервали във функциите за трансформация | Нормализира интервалите във функциите за трансформация (normalizeTransformFunctions) |
| Нормализиране на стойностите на мрежата | Добавя интервали около / в стойностите span; преобразува цели числа без единица в px за grid-template-* (normalizeGridValues) |
| Нормализиране на цветовете | Нормализира синтаксиса на цветовете и изчислява color-mix() до oklab() (normalizeColors, evaluateColorMix) |
| Кавички в URL | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Префикси за доставчици | Префиксиране, еквивалентно на Autoprefixer (addVendorPrefixes) |
Този файл умишлено е поставен под карантина в _tailwindphp/ и е маркиран като @port-deviation:replacement – той служи като заместител на външна зависимост, вместо да пренася изходния код на TailwindCSS.
Маркери за отклонения в порта
Всеки файл с реализация съдържа маркери @port-deviation:* в docblock, които указват къде и защо реализацията PHP се различава от оригинала TypeScript. Целта е читателят, който сравнява PHP с изходния код TailwindCSS, да не се чуди дали дадена разлика е умишлена.
| Маркер | Значение |
|---|---|
@port-deviation:none |
Директен порт 1:1 без съществени отклонения |
@port-deviation:async |
PHP използва синхронен код вместо async/await |
@port-deviation:storage |
Различни структури от данни (масив PHP спрямо Map/Set JS) |
@port-deviation:types |
Анотации PHPDoc вместо типове TypeScript |
@port-deviation:sourcemaps |
Проследяването на source map е пропуснато |
@port-deviation:enum |
Константи PHP вместо enum-и TypeScript |
@port-deviation:errors |
Различен подход за обработка на грешки |
@port-deviation:replacement |
Реализация PHP заместваща външна библиотека (e.g. lightningcss) |
@port-deviation:helper |
Помощна функция, специфична за PHP, която липсва в оригинала |
@port-deviation:performance |
Оптимизация, специфична за PHP, която запазва идентичен резултат |
@port-deviation:omitted |
Целият модул/функционалност не е пренесен (извън обхвата) |
За маркерите @port-deviation:performance и начина, по който се гарантира съответствието, вижте Производителност и тестване.