Skip to content

Commit 63d0176

Browse files
committed
feat: add bun plugin
chore: lint
1 parent 4bbb35e commit 63d0176

12 files changed

Lines changed: 690 additions & 3 deletions

File tree

.github/art/cover.jpg

24.2 KB
Loading

docs/public/images/og-image.png

598 Bytes
Loading

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "headwind",
33
"type": "module",
44
"version": "0.1.1",
5-
"description": "Like our `ts-starter`, but optimized for monorepos.",
5+
"description": "A performant Utility-First CSS framework. Similar to Tailwind or UnoCSS.",
66
"author": "Chris Breuer <chris@stacksjs.org>",
77
"license": "MIT",
88
"homepage": "https://github.com/stacksjs/headwind#readme",
@@ -15,7 +15,6 @@
1515
},
1616
"keywords": [
1717
"monorepo",
18-
"ts-starter",
1918
"headwind",
2019
"template"
2120
],

packages/headwind/PLUGIN.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# Headwind Bun Plugin
2+
3+
A Bun plugin that automatically generates and injects Headwind CSS into your HTML files during the build process.
4+
5+
## Installation
6+
7+
```bash
8+
bun add @stacksjs/headwind
9+
```
10+
11+
## Quick Start
12+
13+
**1. Create your HTML file** (`src/template.html`):
14+
```html
15+
<!DOCTYPE html>
16+
<html>
17+
<head>
18+
<title>My App</title>
19+
</head>
20+
<body>
21+
<div class="flex items-center p-4 bg-blue-500 text-white rounded-lg">
22+
<h1 class="text-2xl font-bold">Hello Headwind!</h1>
23+
</div>
24+
</body>
25+
</html>
26+
```
27+
28+
**2. Import it in your TypeScript** (`src/index.ts`):
29+
```typescript
30+
import template from './template.html'
31+
32+
// The HTML now has Headwind CSS injected
33+
document.body.innerHTML = template
34+
```
35+
36+
**3. Build with the plugin**:
37+
```typescript
38+
import { plugin } from '@stacksjs/headwind'
39+
40+
await Bun.build({
41+
entrypoints: ['./src/index.ts'],
42+
outdir: './dist',
43+
plugins: [plugin()],
44+
})
45+
```
46+
47+
The plugin will automatically:
48+
- Scan the HTML for utility classes
49+
- Generate CSS for those classes
50+
- Inject the CSS into the `<head>` section
51+
52+
## Configuration
53+
54+
### Basic Configuration
55+
56+
```typescript
57+
import { plugin } from '@stacksjs/headwind'
58+
59+
await Bun.build({
60+
entrypoints: ['./src/index.ts'],
61+
outdir: './dist',
62+
plugins: [
63+
plugin({
64+
includePreflight: true, // Include CSS reset (default: true)
65+
}),
66+
],
67+
})
68+
```
69+
70+
### Custom Theme
71+
72+
```typescript
73+
import { plugin } from '@stacksjs/headwind'
74+
75+
await Bun.build({
76+
entrypoints: ['./src/index.ts'],
77+
outdir: './dist',
78+
plugins: [
79+
plugin({
80+
config: {
81+
minify: true,
82+
theme: {
83+
colors: {
84+
primary: '#3b82f6',
85+
secondary: '#10b981',
86+
danger: '#ef4444',
87+
},
88+
spacing: {
89+
18: '4.5rem',
90+
88: '22rem',
91+
},
92+
},
93+
shortcuts: {
94+
btn: 'px-4 py-2 rounded bg-primary text-white hover:bg-blue-600',
95+
card: 'p-6 bg-white rounded-lg shadow-md',
96+
},
97+
},
98+
}),
99+
],
100+
})
101+
```
102+
103+
### Advanced Configuration
104+
105+
```typescript
106+
import { plugin } from '@stacksjs/headwind'
107+
108+
await Bun.build({
109+
entrypoints: ['./src/index.ts'],
110+
outdir: './dist',
111+
plugins: [
112+
plugin({
113+
config: {
114+
minify: true,
115+
safelist: ['bg-red-500', 'text-green-500'], // Always include these
116+
blocklist: ['debug-*'], // Never include these
117+
theme: {
118+
colors: {
119+
brand: {
120+
50: '#f0f9ff',
121+
100: '#e0f2fe',
122+
500: '#0ea5e9',
123+
900: '#0c4a6e',
124+
},
125+
},
126+
},
127+
shortcuts: {
128+
'btn-primary': 'px-4 py-2 rounded bg-brand-500 text-white hover:bg-brand-600',
129+
},
130+
},
131+
includePreflight: true,
132+
}),
133+
],
134+
})
135+
```
136+
137+
## API Reference
138+
139+
### `plugin(options?)`
140+
141+
Creates a Headwind Bun plugin instance.
142+
143+
#### Options
144+
145+
- **`config`** (`Partial<HeadwindConfig>`) - Custom Headwind configuration
146+
- `minify` - Minify the generated CSS
147+
- `theme` - Custom theme (colors, spacing, fonts, etc.)
148+
- `shortcuts` - Utility class shortcuts
149+
- `safelist` - Classes to always include
150+
- `blocklist` - Classes to never include
151+
- `variants` - Enable/disable variants
152+
- And more...
153+
154+
- **`includePreflight`** (`boolean`) - Include preflight CSS (default: `true`)
155+
156+
## How It Works
157+
158+
1. The plugin registers an `onLoad` handler for `.html` files
159+
2. When Bun encounters an HTML import, the plugin intercepts it
160+
3. It extracts all utility classes from the HTML using Headwind's parser
161+
4. It generates CSS for those classes using Headwind's generator
162+
5. The CSS is injected into the `<head>` section
163+
6. The processed HTML is returned to the bundle
164+
165+
## Use Cases
166+
167+
- **SPAs**: Import HTML templates with automatic CSS generation
168+
- **Web Components**: Load component templates with scoped styles
169+
- **Static Sites**: Process HTML pages during build
170+
- **Email Templates**: Generate inline CSS for email HTML
171+
172+
## Examples
173+
174+
See the [examples/plugin](./examples/plugin) directory for a complete working example.
175+
176+
## Comparison with CLI
177+
178+
| Feature | Plugin | CLI |
179+
|---------|--------|-----|
180+
| Automatic CSS generation |||
181+
| Watches files | ✅ (via Bun) ||
182+
| Injects CSS |||
183+
| Separate CSS file |||
184+
| Build integration |||
185+
| Standalone usage |||
186+
187+
## Performance
188+
189+
The plugin is highly performant:
190+
- Processes 1000 utilities in ~7ms
191+
- Minimal overhead in build process
192+
- Lazy loading - only processes imported HTML files
193+
194+
## TypeScript Support
195+
196+
The plugin is fully typed. Import the types:
197+
198+
```typescript
199+
import type { HeadwindPluginOptions } from '@stacksjs/headwind'
200+
201+
const options: HeadwindPluginOptions = {
202+
config: {
203+
minify: true,
204+
},
205+
}
206+
```
207+
208+
## Configuration File
209+
210+
The plugin also respects `headwind.config.ts` in your project root:
211+
212+
```typescript
213+
// headwind.config.ts
214+
import type { HeadwindOptions } from '@stacksjs/headwind'
215+
216+
export default {
217+
minify: true,
218+
theme: {
219+
colors: {
220+
primary: '#3b82f6',
221+
},
222+
},
223+
} satisfies HeadwindOptions
224+
```
225+
226+
The plugin will merge this config with any options passed to it.
227+
228+
## License
229+
230+
MIT
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Headwind Bun Plugin Example
2+
3+
This example demonstrates how to use the Headwind Bun plugin to automatically generate and inject CSS into your HTML files during the build process.
4+
5+
## Project Structure
6+
7+
```
8+
examples/plugin/
9+
├── src/
10+
│ ├── index.ts # TypeScript entrypoint that imports HTML
11+
│ └── index.html # HTML file with utility classes
12+
├── build.ts # Build script
13+
└── README.md
14+
```
15+
16+
## Usage
17+
18+
The plugin works by intercepting HTML imports in your TypeScript/JavaScript code. When you import an HTML file, the plugin:
19+
1. Scans the HTML for Headwind utility classes
20+
2. Generates the corresponding CSS
21+
3. Injects the CSS into the `<head>` section
22+
4. Returns the processed HTML
23+
24+
### Basic Setup
25+
26+
```typescript
27+
import { plugin } from '@stacksjs/headwind'
28+
29+
await Bun.build({
30+
entrypoints: ['./src/index.ts'],
31+
outdir: './dist',
32+
plugins: [plugin()],
33+
})
34+
```
35+
36+
**Your TypeScript file** (`src/index.ts`):
37+
```typescript
38+
import html from './index.html'
39+
40+
// Use the HTML content (it will have CSS injected)
41+
document.body.innerHTML = html
42+
```
43+
44+
### With Custom Configuration
45+
46+
```typescript
47+
import { plugin } from '@stacksjs/headwind'
48+
49+
await Bun.build({
50+
entrypoints: ['./src/index.ts'],
51+
outdir: './dist',
52+
plugins: [
53+
plugin({
54+
config: {
55+
minify: true,
56+
theme: {
57+
colors: {
58+
primary: '#3b82f6',
59+
secondary: '#10b981',
60+
},
61+
},
62+
},
63+
includePreflight: true,
64+
}),
65+
],
66+
})
67+
```
68+
69+
## Running This Example
70+
71+
```bash
72+
# Build the example
73+
bun run build.ts
74+
75+
# The output will be in ./dist/
76+
```
77+
78+
## How It Works
79+
80+
1. The plugin hooks into Bun's module loading system via `onLoad`
81+
2. When a `.html` file is imported, the plugin intercepts the load
82+
3. It extracts utility classes from the HTML using Headwind's parser
83+
4. It generates CSS for those classes using Headwind's generator
84+
5. The generated CSS is injected into the `<head>` section
85+
6. The processed HTML is returned as a string in the bundled output
86+
87+
## Options
88+
89+
### `config`
90+
Custom Headwind configuration to override defaults. This can include:
91+
- `minify`: Minify the generated CSS
92+
- `theme`: Custom theme colors, spacing, fonts, etc.
93+
- `shortcuts`: Define utility class shortcuts
94+
- `safelist`: Classes to always include
95+
- And more...
96+
97+
### `includePreflight`
98+
Whether to include preflight (reset) CSS. Default: `true`
99+
100+
## Use Cases
101+
102+
This plugin is ideal for:
103+
- Single Page Applications (SPAs) that import HTML templates
104+
- Component-based architectures where HTML is imported as strings
105+
- Build processes that need automatic CSS generation from HTML
106+
- Projects using Bun's native bundler with HTML assets
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { plugin } from '@stacksjs/headwind'
2+
3+
// Build with headwind plugin
4+
// The plugin will automatically process HTML files that are imported in your TypeScript/JavaScript code
5+
const result = await Bun.build({
6+
entrypoints: ['./src/index.ts'], // Your TS entrypoint that imports HTML files
7+
outdir: './dist',
8+
plugins: [
9+
plugin({
10+
// Optional: provide custom config
11+
config: {
12+
minify: true,
13+
theme: {
14+
colors: {
15+
primary: '#3b82f6',
16+
secondary: '#10b981',
17+
},
18+
},
19+
},
20+
// Optional: include preflight CSS
21+
includePreflight: true,
22+
}),
23+
],
24+
})
25+
26+
if (result.success) {
27+
console.log('Build complete!')
28+
console.log(`Generated ${result.outputs.length} output(s)`)
29+
}
30+
else {
31+
console.error('Build failed:', result.logs)
32+
}

0 commit comments

Comments
 (0)