Arquitetura
TailwindPHP é uma implementação 1:1. A base de código reproduz a estrutura própria de TailwindCSS — mesmos nomes de arquivo, mesma organização — e isola em src/_tailwindphp/ as partes que não podem ser uma implementação direta (PHP não tem Rust nem V8). Esta página percorre o fluxo de compilação, a organização do código-fonte, a reimplementação de lightningcss e a convenção usada para documentar as diferenças.
O pipeline
A geração de CSS consiste em uma sequência de etapas. Não há uma etapa de compilação separada: cada chamada a tw::generate() executa o fluxo completo.
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
Análise sintática. css-parser.php lê a entrada CSS — @import, @theme, @utility, @layer, regras brutas — em uma árvore sintática abstrata de nós ast.php (regras de estilo, regras at, declarações). As diretivas @import para módulos virtuais (tailwindcss, tailwindcss/preflight, …) e os caminhos de arquivo são resolvidos e substituídos nesta etapa.
Construção do sistema de design. theme.php resolve os valores do tema (cores, espaçamento, pontos de interrupção) a partir dos blocos @theme analisados e dos padrões. design-system.php é o registro central que conecta o tema às buscas de utilitários e variantes definidas em utilities.php e variants.php.
Varredura do conteúdo. candidate.php extrai candidatos a nomes de classe do conteúdo fornecido (HTML, modelos) e os analisa em partes: utilitário base, variantes, modificadores, valores arbitrários e sinalizador de importância.
Compilação. compile.php transforma cada candidato em nós AST, pesquisando-o no sistema de design e aplicando suas variantes e modificadores. Candidatos que não correspondem a um utilitário real são descartados.
Serialização e otimização. ast.php percorre a árvore com seu toCss() (auxiliares em walk.php) e gera a string CSS. São aplicadas as transformações equivalentes a lightningcss em _tailwindphp/LightningCss.php, para que a saída corresponda ao que TailwindCSS produz após sua etapa de pós-processamento Rust.
Minificação. Quando minify está ativado, toCss() gera CSS minificado durante a serialização. _tailwindphp/CssMinifier.php é usado na etapa independente de processamento de strings tw::minify(). Consulte Cache e minificação.
Organização do código-fonte
src/ espelha TailwindCSS. A única mudança estrutural: o utilities.ts de TailwindCSS tem 6,000+ linhas, então foi dividido em src/utilities/, com um arquivo por categoria para facilitar a manutenção.
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
O equivalente de lightningcss
TailwindCSS delega o pós-processamento de CSS — aninhamento, tratamento de consultas de mídia, simplificação de valores — a lightningcss, um parser/transformador/minificador escrito em Rust. PHP não consegue carregar uma biblioteca Rust, então src/_tailwindphp/LightningCss.php reimplementa as transformações de que TailwindPHP realmente depende, produzindo uma saída idêntica byte a byte nos casos cobertos pelo conjunto de testes.
As transformações confirmadas incluem:
| Transformação | O que faz |
|---|---|
| Achatamento de aninhamento | Resolve seletores & com as regras de :is(…) da referência e achata regras aninhadas (handleNesting() em ast.php, uma adaptação da etapa TailwindCSS); transformNesting converte para uma versão anterior o aninhamento que permanece abaixo do primeiro nível que contém declarações |
| Achatamento de regras at-rule condicionais | Achata @media, @supports, @container e @starting-style aninhados no lugar, preservando a ordem no código-fonte e mesclando apenas elementos irmãos diretamente adjacentes com condições idênticas |
| Ordenação de declarações | Reordena declarações de acordo com a cadeia de manipuladores de declarações do lightningcss, para que as propriedades apareçam na ordem da referência (reorderDeclarations) |
Simplificação de calc() |
Simplifica expressões calc() (simplifyCalcExpressions) |
| Remoção de zeros à esquerda | 0.5 → .5 (normalizeLeadingZeros) |
| Espaçamento em funções de transformação | Normaliza o espaçamento dentro das funções de transformação (normalizeTransformFunctions) |
| Normalização de valores de grade | Adiciona espaços ao redor de / em valores span; converte inteiros sem unidade em px para grid-template-* (normalizeGridValues) |
| Normalização de cores | Normaliza a sintaxe de cores e avalia color-mix() como oklab() (normalizeColors, evaluateColorMix) |
| Aspas em URL | url(./x.jpg) → url("./x.jpg") (normalizeUrlQuoting) |
| Prefixos de fornecedores | Prefixação equivalente à de Autoprefixer (addVendorPrefixes) |
Este arquivo está deliberadamente isolado em _tailwindphp/ e marcado como @port-deviation:replacement — ele representa uma dependência externa, em vez de portar o código-fonte de TailwindCSS.
Marcadores de desvios da adaptação
Cada arquivo de implementação contém marcadores @port-deviation:* em seu docblock que indicam onde e por que a implementação de PHP diverge da versão original de TypeScript. O objetivo é que quem comparar PHP com o código-fonte de TailwindCSS nunca precise se perguntar se uma diferença é intencional.
| Marcador | Significado |
|---|---|
@port-deviation:none |
Adaptação direta de 1:1, sem desvios significativos |
@port-deviation:async |
PHP usa código síncrono em vez de async/await |
@port-deviation:storage |
Estruturas de dados diferentes (array PHP em vez de Map/Set JS) |
@port-deviation:types |
Anotações PHPDoc em vez de tipos TypeScript |
@port-deviation:sourcemaps |
Rastreamento de source maps omitido |
@port-deviation:enum |
Constantes PHP em vez de enums TypeScript |
@port-deviation:errors |
Abordagem diferente para tratamento de erros |
@port-deviation:replacement |
Implementação PHP que substitui uma biblioteca externa (e.g. lightningcss) |
@port-deviation:helper |
Auxiliar específico de PHP que não existe no original |
@port-deviation:performance |
Otimização específica de PHP que preserva uma saída idêntica |
@port-deviation:omitted |
Módulo/recurso inteiro não adaptado (fora do escopo) |
Para ver os marcadores @port-deviation:performance e como a paridade é garantida, consulte Desempenho e testes.