
# Архитектура

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-rule и объявления). На этом этапе обрабатываются директивы `@import` для виртуальных модулей (`tailwindcss`, `tailwindcss/preflight`, …) и пути к файлам.

**Построение дизайн-системы.** `theme.php` получает значения темы (цвета, отступы, контрольные точки) из разобранных блоков `@theme` и значений по умолчанию. `design-system.php` — это центральный реестр, который связывает тему с поиском утилит и вариантов, определенным в `utilities.php` и `variants.php`.

**Сканирование содержимого.** `candidate.php` извлекает кандидаты имен классов из переданного содержимого (HTML, шаблонов) и разбирает каждый на составляющие: базовую утилиту, варианты, модификаторы, произвольные значения и флаг important.

**Компиляция.** `compile.php` преобразует каждый кандидат в узлы AST, находя его в дизайн-системе и применяя варианты и модификаторы. Кандидаты, не соответствующие существующей утилите, отбрасываются.

**Сериализация и оптимизация.** `toCss()` в составе `ast.php` проходит по дереву (вспомогательные функции находятся в `walk.php`) и формирует строку CSS. Затем применяются преобразования из `_tailwindphp/LightningCss.php`, эквивалентные `lightningcss`, чтобы результат соответствовал выводу TailwindCSS после этапа постобработки Rust.

**Минификация.** Когда включен `minify`, при сериализации `toCss()` формирует минифицированный CSS. Отдельная обработка строки `tw::minify()` выполняется с помощью `_tailwindphp/CssMinifier.php`. См. [Кэширование и минификация](https://tailwindphp.inline0.dev/ru/docs/advanced/caching).

## Структура исходного кода

`src/` повторяет TailwindCSS. Единственное структурное изменение: TailwindCSS`utilities.ts` содержит более 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](https://lightningcss.dev/), парсеру, преобразователю и минификатору, написанному на 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.

## Маркеры отклонений при портировании

Каждый файл реализации содержит в своем docblock маркеры `@port-deviation:*`, которые указывают, где и почему реализация 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` | Отслеживание исходных карт не реализовано |
| `@port-deviation:enum` | Константы PHP вместо перечислений 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` и проверке соответствия см. раздел [Производительность и тестирование](https://tailwindphp.inline0.dev/ru/docs/advanced/performance).
