Pular para o conteúdo

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.

Código
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.

Código
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.