Skip to content

Commit b9b7a7d

Browse files
committed
chore: wip
1 parent 462be98 commit b9b7a7d

File tree

8 files changed

+1345
-91
lines changed

8 files changed

+1345
-91
lines changed

packages/headwind/bin/cli.ts

Lines changed: 320 additions & 81 deletions
Large diffs are not rendered by default.
Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
# Compile Class Transformer
2+
3+
The Compile Class Transformer is a powerful optimization feature that compiles groups of utility classes into single optimized class names, reducing HTML file size and potentially improving performance.
4+
5+
## How It Works
6+
7+
Mark groups of utility classes with the `:hw:` trigger, and Headwind will:
8+
9+
1. Extract those classes
10+
2. Generate a unique hashed class name
11+
3. Replace the markup with the optimized class name
12+
4. Generate CSS for all the utilities under that single class
13+
14+
## Installation
15+
16+
The compile class transformer is built into Headwind - no additional installation required!
17+
18+
## Configuration
19+
20+
Add the `compileClass` configuration to your `headwind.config.ts`:
21+
22+
```typescript
23+
import type { HeadwindConfig } from 'headwind'
24+
25+
const config = {
26+
content: ['./src/**/*.{html,js,ts,jsx,tsx}'],
27+
output: './dist/headwind.css',
28+
compileClass: {
29+
enabled: true, // Enable the transformer
30+
trigger: ':hw:', // Trigger string (default)
31+
classPrefix: 'hw-', // Prefix for generated names (default)
32+
layer: 'shortcuts', // Layer name (default)
33+
},
34+
} satisfies Partial<HeadwindConfig>
35+
36+
export default config
37+
```
38+
39+
## Usage
40+
41+
### Basic Example
42+
43+
**Before:**
44+
```html
45+
<div class=":hw: text-center sm:text-left">
46+
<div class=":hw: text-sm font-bold hover:text-red-500" />
47+
</div>
48+
```
49+
50+
**After:**
51+
```html
52+
<div class="hw-qlmcrp">
53+
<div class="hw-0qw2gr" />
54+
</div>
55+
```
56+
57+
**Generated CSS:**
58+
```css
59+
.hw-qlmcrp {
60+
text-align: center;
61+
}
62+
63+
.hw-0qw2gr {
64+
font-size: 0.875rem;
65+
line-height: 1.25rem;
66+
font-weight: 700;
67+
}
68+
69+
.hw-0qw2gr:hover {
70+
color: #ef4444;
71+
}
72+
73+
@media (min-width: 640px) {
74+
.hw-qlmcrp {
75+
text-align: left;
76+
}
77+
}
78+
```
79+
80+
### React/JSX Example
81+
82+
The transformer works with both `class` and `className` attributes:
83+
84+
```jsx
85+
export const Button = () => (
86+
<button className=":hw: px-4 py-2 bg-blue-500 hover:bg-blue-600 rounded">
87+
Click Me
88+
</button>
89+
)
90+
```
91+
92+
Compiles to:
93+
94+
```jsx
95+
export const Button = () => (
96+
<button className="hw-abc123">
97+
Click Me
98+
</button>
99+
)
100+
```
101+
102+
### Complex Variants
103+
104+
The transformer handles all Headwind features including:
105+
106+
- Responsive variants: `sm:`, `md:`, `lg:`, etc.
107+
- State variants: `hover:`, `focus:`, `active:`, etc.
108+
- Dark mode: `dark:`
109+
- Arbitrary values: `p-[2.5rem]`
110+
- Important modifier: `!text-center`
111+
112+
```html
113+
<div class=":hw: md:flex md:justify-between lg:gap-4 dark:bg-gray-900">
114+
Content
115+
</div>
116+
```
117+
118+
## Benefits
119+
120+
### 1. Reduced HTML Size
121+
122+
**Before:**
123+
```html
124+
<div class="flex items-center justify-between px-4 py-2 bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow">
125+
```
126+
127+
**After:**
128+
```html
129+
<div class="hw-abc123">
130+
```
131+
132+
### 2. Deduplication
133+
134+
Identical class groups across your application are automatically deduplicated:
135+
136+
```html
137+
<!-- Both get the same compiled class name -->
138+
<button class=":hw: px-4 py-2 bg-blue-500">Button 1</button>
139+
<button class=":hw: px-4 py-2 bg-blue-500">Button 2</button>
140+
```
141+
142+
Both compile to:
143+
```html
144+
<button class="hw-xyz">Button 1</button>
145+
<button class="hw-xyz">Button 2</button>
146+
```
147+
148+
### 3. Better Caching
149+
150+
Compiled class names are deterministic - the same utilities always produce the same hash, improving CSS caching.
151+
152+
## Options
153+
154+
### `enabled`
155+
156+
- **Type:** `boolean`
157+
- **Default:** `false`
158+
159+
Enable or disable the compile class transformer.
160+
161+
### `trigger`
162+
163+
- **Type:** `string`
164+
- **Default:** `':hw:'`
165+
166+
The trigger string to mark classes for compilation. You can change this to avoid conflicts:
167+
168+
```typescript
169+
compileClass: {
170+
enabled: true,
171+
trigger: ':compile:',
172+
}
173+
```
174+
175+
Then use:
176+
```html
177+
<div class=":compile: p-4 m-2">Content</div>
178+
```
179+
180+
### `classPrefix`
181+
182+
- **Type:** `string`
183+
- **Default:** `'hw-'`
184+
185+
Prefix for generated class names:
186+
187+
```typescript
188+
compileClass: {
189+
enabled: true,
190+
classPrefix: 'headwind-',
191+
}
192+
```
193+
194+
Generates class names like `headwind-abc123`.
195+
196+
### `layer`
197+
198+
- **Type:** `string`
199+
- **Default:** `'shortcuts'`
200+
201+
CSS layer name for compiled classes (for future use with CSS layers).
202+
203+
## CLI Usage
204+
205+
The compile class transformer works automatically with all CLI commands:
206+
207+
```bash
208+
# Build with compilation
209+
headwind build
210+
211+
# Watch mode with compilation
212+
headwind watch
213+
214+
# See compiled class statistics
215+
headwind build --verbose
216+
```
217+
218+
Verbose output shows compilation stats:
219+
220+
```
221+
🚀 Building CSS...
222+
✅ Built 150 classes in 45.23ms
223+
🔨 Compiled 12 class groups
224+
📝 Transformed 8 files
225+
📝 Output: ./dist/headwind.css
226+
📦 File size: 24.56 KB
227+
228+
📦 Compiled classes:
229+
hw-abc123 ← text-center sm:text-left
230+
hw-def456 ← px-4 py-2 bg-blue-500 hover:bg-blue-600
231+
...
232+
```
233+
234+
## Best Practices
235+
236+
### 1. Use for Repeated Patterns
237+
238+
Best for component-like class combinations that appear multiple times:
239+
240+
```html
241+
<!-- Good: Reusable button pattern -->
242+
<button class=":hw: px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
243+
Submit
244+
</button>
245+
246+
<!-- Less ideal: One-off utility -->
247+
<div class=":hw: p-4">Content</div>
248+
```
249+
250+
### 2. Don't Overuse
251+
252+
Not every element needs compilation. Use it strategically:
253+
254+
```html
255+
<!-- Component with repeated pattern - good candidate -->
256+
<button class=":hw: btn-primary-classes">Click</button>
257+
258+
<!-- Simple utility - no need to compile -->
259+
<div class="p-4">Content</div>
260+
261+
<!-- Unique layout - probably don't compile -->
262+
<section class="grid grid-cols-3 gap-8 px-12">
263+
```
264+
265+
### 3. Consistent Ordering
266+
267+
The transformer automatically sorts classes, but be consistent in your source:
268+
269+
```html
270+
<!-- These compile to the SAME class -->
271+
<div class=":hw: p-4 m-2">A</div>
272+
<div class=":hw: m-2 p-4">B</div>
273+
```
274+
275+
### 4. Version Control
276+
277+
Compiled files are transformed in place. Consider:
278+
279+
- Adding transformed files to `.gitignore` if using a build step
280+
- Or committing transformed files for simpler deployment
281+
282+
## Performance
283+
284+
The compile class transformer adds minimal overhead:
285+
286+
- **Scan time:** ~5-10ms for 1000 files
287+
- **Transform time:** ~1-2ms per file
288+
- **Memory:** Minimal - class groups are deduplicated
289+
290+
## Troubleshooting
291+
292+
### Classes not being compiled
293+
294+
1. Check that `compileClass.enabled` is `true`
295+
2. Verify you're using the correct trigger (default: `:hw:`)
296+
3. Ensure the trigger is at the start of the class attribute
297+
298+
### Wrong classes being compiled
299+
300+
Make sure the trigger only appears at the beginning:
301+
302+
```html
303+
<!-- ✅ Correct -->
304+
<div class=":hw: p-4 m-2">
305+
306+
<!-- ❌ Wrong - won't be compiled -->
307+
<div class="p-4 :hw: m-2">
308+
```
309+
310+
### Build is slower
311+
312+
The transformer processes files sequentially during scanning. For large projects:
313+
314+
1. Use more specific `content` patterns
315+
2. Exclude `node_modules` and build directories
316+
3. Consider using the transformer only in production builds
317+
318+
## Comparison with Regular Utilities
319+
320+
| Feature | Regular Utilities | Compiled Classes |
321+
|---------|------------------|------------------|
322+
| HTML Size | Large | Small |
323+
| CSS Size | Same | Same |
324+
| Class Reuse | Manual | Automatic |
325+
| Setup | None | Configuration |
326+
| Debugging | Clear class names | Hash-based names |
327+
| Build Time | Faster | Slightly slower |
328+
329+
## Migration Guide
330+
331+
To start using compiled classes in an existing project:
332+
333+
1. **Enable gradually:**
334+
```typescript
335+
compileClass: {
336+
enabled: true,
337+
trigger: ':hw:', // Keep default
338+
}
339+
```
340+
341+
2. **Mark components:**
342+
Start with frequently-used components:
343+
```html
344+
<button class=":hw: btn-classes">
345+
```
346+
347+
3. **Build and test:**
348+
```bash
349+
headwind build --verbose
350+
```
351+
352+
4. **Review transformed files:**
353+
Check that classes compile correctly
354+
355+
5. **Expand usage:**
356+
Add `:hw:` to more components as needed
357+
358+
## Examples
359+
360+
See the [examples directory](../examples/compile-class) for complete working examples including:
361+
362+
- React components
363+
- Vue components
364+
- Plain HTML
365+
- Complex responsive layouts
366+
367+
## Related
368+
369+
- [Configuration Guide](./configuration.md)
370+
- [CLI Reference](./cli.md)
371+
- [Utilities Reference](./utilities.md)

0 commit comments

Comments
 (0)