emily-css 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -111
- package/bin/emilyui.js +7 -4
- package/package.json +7 -4
- package/src/index.js +2 -2
- package/src/init.js +15 -10
- package/src/purge-cmd.js +55 -0
- package/dist/emily.purged.css +0 -840
- package/dist/emily.purged.min.css +0 -1
package/README.md
CHANGED
|
@@ -1,107 +1,159 @@
|
|
|
1
|
-
#
|
|
1
|
+
# EmilyUI
|
|
2
2
|
|
|
3
|
-
A config-driven
|
|
3
|
+
A config-driven utility CSS framework. Define your brand once, generate the CSS.
|
|
4
|
+
|
|
5
|
+
**EmilyUI** is the ecosystem name. `emily-css` is the utility layer published on npm — it's both the package you install and the CLI you use to generate and purge CSS. More packages coming.
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **No build pipeline required** — Generate CSS, use it directly in your project
|
|
9
|
+
- **Works anywhere** - Generate static CSS and drop it into any project, no build pipeline required.
|
|
10
|
+
- **Config-driven** - Entire framework configured via `emily.config.json`
|
|
11
|
+
- **Utility-first** - Composable utilities for layout, spacing, typography and colour
|
|
12
|
+
- **Responsive ready** - All utilities work with responsive prefixes (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`)
|
|
13
|
+
- **State variants** - `hover:`, `focus-visible:`, `active:`, `disabled:` built-in
|
|
14
|
+
- **Accessibility first** - WCAG 2.2 AA compliance in core utilities (focus rings, contrast, motion)
|
|
15
|
+
- **Purge system** - Remove unused CSS automatically for production
|
|
15
16
|
|
|
16
17
|
## Quick Start
|
|
17
18
|
|
|
18
19
|
### 1. Install
|
|
20
|
+
|
|
19
21
|
```bash
|
|
20
|
-
npm install emily-
|
|
21
|
-
emily-ui init
|
|
22
|
+
npm install emily-css
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
### 2. Create your config
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx emily-css init
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This walks you through:
|
|
32
|
+
|
|
25
33
|
- Project name
|
|
26
34
|
- Brand colours (primary, secondary, success, warning, error, neutral)
|
|
27
35
|
- Font families
|
|
28
36
|
- Base spacing unit
|
|
37
|
+
- Source directory (used by the purge command)
|
|
38
|
+
|
|
39
|
+
It then generates `emily.config.json` and runs your first build automatically.
|
|
40
|
+
|
|
41
|
+
### 3. Link the CSS in your project
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<link rel="stylesheet" href="./dist/emily.css">
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 4. Use the utility classes
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<button class="px-4 py-2 rounded-md bg-primary-80 text-white hover:bg-primary-90 focus-visible:ring-2 focus-visible:ring-primary-50">
|
|
51
|
+
Button
|
|
52
|
+
</button>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Colours, spacing and typography all come from your config.
|
|
56
|
+
|
|
57
|
+
### 5. Purge unused CSS for production
|
|
29
58
|
|
|
30
|
-
### 2. Build CSS
|
|
31
59
|
```bash
|
|
32
|
-
emily-
|
|
60
|
+
npx emily-css purge
|
|
33
61
|
```
|
|
34
62
|
|
|
63
|
+
Scans your template files, keeps only the utilities you actually use.
|
|
64
|
+
|
|
35
65
|
Output:
|
|
36
|
-
- `dist/emily.css`
|
|
37
|
-
- `dist/emily.min.css`
|
|
66
|
+
- `dist/emily.purged.css` - Purged CSS
|
|
67
|
+
- `dist/emily.purged.min.css` - Minified version
|
|
68
|
+
|
|
69
|
+
Use the purged file in production:
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<link rel="stylesheet" href="./dist/emily.purged.min.css">
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
38
76
|
|
|
39
|
-
### 2b. Run Tests (Optional)
|
|
40
77
|
```bash
|
|
41
|
-
|
|
78
|
+
npx emily-css init # Create emily.config.json and run first build
|
|
79
|
+
npx emily-css build # Regenerate CSS after config changes
|
|
80
|
+
npx emily-css purge # Remove unused utilities for production
|
|
81
|
+
npm test # Run test suite (if working on EmilyUI itself)
|
|
42
82
|
```
|
|
43
|
-
*(Run from inside the emily-ui project folder)*
|
|
44
83
|
|
|
45
|
-
|
|
84
|
+
## How Purge Works
|
|
46
85
|
|
|
47
|
-
|
|
48
|
-
Open `showcase.html` in your browser to see 8 production components (button, input, textarea, select, checkbox, radio, card, alert). Copy the HTML, paste into your project.
|
|
86
|
+
EmilyUI scans your template files for class names and removes any utilities you are not using.
|
|
49
87
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
88
|
+
For example:
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<div class="p-4 bg-primary-80 rounded-lg">Content</div>
|
|
53
92
|
```
|
|
54
93
|
|
|
55
|
-
|
|
94
|
+
EmilyUI keeps `.p-4`, `.bg-primary-80`, `.rounded-lg` and removes everything else.
|
|
56
95
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
96
|
+
Supported file types: `.html`, `.twig`, `.njk`, `.liquid`, `.hbs`, `.jsx`, `.tsx`, `.vue`, `.php`, `.astro`, `.svelte`, `.blade.php` (configurable via `extensions` in `emily.config.json`)
|
|
97
|
+
|
|
98
|
+
**Note:** Class names must exist as plain text in your files. Dynamically constructed class names will not be detected:
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
// This will be missed by purge:
|
|
102
|
+
const colour = 'primary-80'
|
|
103
|
+
const cls = `bg-${colour}`
|
|
104
|
+
|
|
105
|
+
// This will be detected:
|
|
106
|
+
const cls = 'bg-primary-80'
|
|
107
|
+
```
|
|
60
108
|
|
|
61
|
-
|
|
109
|
+
If you use dynamic classes, either keep them as plain strings or manually safelist them in your config.
|
|
62
110
|
|
|
63
|
-
|
|
111
|
+
## File Size
|
|
64
112
|
|
|
65
|
-
|
|
66
|
-
- **Tailwind v2** (purge-based): 2.4–8MB unpurged → <10KB purged
|
|
67
|
-
- **Emily v1** (purge-based): 1.1MB unpurged → 10–50KB purged
|
|
68
|
-
- **Tailwind v3/v4** (JIT): Generates only what you use, no purge step needed
|
|
113
|
+
EmilyUI uses a purge-based approach (generate all utilities, then remove unused).
|
|
69
114
|
|
|
70
|
-
|
|
115
|
+
| | Unpurged | Purged |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| Tailwind v2 | 2.4-8MB | under 10KB |
|
|
118
|
+
| EmilyUI v1 | 1.1MB | 10-50KB |
|
|
119
|
+
| Tailwind v3/v4 (JIT) | generates on demand | - |
|
|
120
|
+
|
|
121
|
+
EmilyUI's unpurged file is roughly half the size of Tailwind v2. Post-purge sizes are comparable. JIT-style generation is planned for v2.
|
|
71
122
|
|
|
72
123
|
## File Structure
|
|
73
124
|
|
|
74
125
|
```
|
|
75
|
-
emily-
|
|
126
|
+
emily-css/
|
|
76
127
|
├── src/
|
|
77
|
-
│ ├── index.js
|
|
78
|
-
│ ├── generators.js
|
|
79
|
-
│ ├── purge.js
|
|
80
|
-
│
|
|
128
|
+
│ ├── index.js - Main build script
|
|
129
|
+
│ ├── generators.js - Utility generation functions
|
|
130
|
+
│ ├── purge.js - Purge system
|
|
131
|
+
│ ├── purge-cmd.js - Purge CLI command
|
|
132
|
+
│ └── init.js - Interactive setup
|
|
81
133
|
├── dist/
|
|
82
|
-
│ ├── emily.css
|
|
83
|
-
│ ├── emily.min.css
|
|
84
|
-
│ ├── emily.purged.css
|
|
134
|
+
│ ├── emily.css - Generated CSS
|
|
135
|
+
│ ├── emily.min.css - Minified CSS
|
|
136
|
+
│ ├── emily.purged.css - Purged CSS
|
|
85
137
|
│ └── emily.purged.min.css
|
|
86
|
-
├── showcase.html
|
|
87
|
-
├── emily.config.json
|
|
138
|
+
├── showcase.html - Example components
|
|
139
|
+
├── emily.config.json - Your config
|
|
88
140
|
├── package.json
|
|
89
141
|
└── README.md
|
|
90
142
|
```
|
|
91
143
|
|
|
92
144
|
## Configuration
|
|
93
145
|
|
|
94
|
-
Edit `emily.config.json` to
|
|
146
|
+
Edit `emily.config.json` to customise:
|
|
95
147
|
|
|
96
148
|
```json
|
|
97
149
|
{
|
|
98
150
|
"name": "My Brand",
|
|
99
151
|
"description": "Design system",
|
|
100
|
-
|
|
152
|
+
|
|
101
153
|
"baseUnit": "8px",
|
|
102
154
|
"baseFontSize": "16px",
|
|
103
155
|
"fontFamily": "system-ui",
|
|
104
|
-
|
|
156
|
+
|
|
105
157
|
"colours": {
|
|
106
158
|
"primary": "#0077b6",
|
|
107
159
|
"secondary": "#006d9e",
|
|
@@ -110,7 +162,7 @@ Edit `emily.config.json` to customize:
|
|
|
110
162
|
"error": "#b20000",
|
|
111
163
|
"neutral": "#6b7280"
|
|
112
164
|
},
|
|
113
|
-
|
|
165
|
+
|
|
114
166
|
"breakpoints": {
|
|
115
167
|
"sm": "640px",
|
|
116
168
|
"md": "768px",
|
|
@@ -118,55 +170,43 @@ Edit `emily.config.json` to customize:
|
|
|
118
170
|
"xl": "1280px",
|
|
119
171
|
"2xl": "1536px"
|
|
120
172
|
},
|
|
121
|
-
|
|
122
|
-
"spacing": {
|
|
123
|
-
"scale": { "0": "0px", "1": "0.25rem", ... },
|
|
124
|
-
"borderRadius": { "sm": "4px", "base": "8px", "lg": "16px", ... }
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
"typography": {
|
|
128
|
-
"fontWeights": { "light": 300, "normal": 400, ... },
|
|
129
|
-
"fontSizes": [ { "name": "sm", "value": "14px" }, ... ]
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
"shadows": { ... },
|
|
133
|
-
"transitions": { ... },
|
|
134
|
-
"zIndex": { ... },
|
|
135
|
-
"opacity": [ ... ],
|
|
136
|
-
|
|
173
|
+
|
|
137
174
|
"purge": {
|
|
138
|
-
"
|
|
175
|
+
"sourceDir": "./src",
|
|
176
|
+
"extensions": [".html", ".jsx", ".tsx", ".vue"]
|
|
139
177
|
}
|
|
140
178
|
}
|
|
141
179
|
```
|
|
142
180
|
|
|
143
181
|
After editing, rebuild:
|
|
182
|
+
|
|
144
183
|
```bash
|
|
145
|
-
emily-
|
|
184
|
+
npx emily-css build
|
|
146
185
|
```
|
|
147
186
|
|
|
148
187
|
## Utilities
|
|
149
188
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
- **Display**
|
|
153
|
-
- **Spacing**
|
|
154
|
-
- **Sizing**
|
|
155
|
-
- **Positioning**
|
|
156
|
-
- **Flexbox**
|
|
157
|
-
- **Grid**
|
|
158
|
-
- **Colours**
|
|
159
|
-
- **Typography**
|
|
160
|
-
- **Borders**
|
|
161
|
-
- **Shadows**
|
|
162
|
-
- **Opacity**
|
|
163
|
-
- **Accessibility**
|
|
164
|
-
- **State variants**
|
|
165
|
-
- **Responsive variants**
|
|
189
|
+
EmilyUI generates utilities across these categories:
|
|
190
|
+
|
|
191
|
+
- **Display** - block, inline, flex, grid, hidden
|
|
192
|
+
- **Spacing** - margin (`m-`), padding (`p-`), gap (`gap-`)
|
|
193
|
+
- **Sizing** - width (`w-`), height (`h-`), max-width, min-height
|
|
194
|
+
- **Positioning** - absolute, relative, fixed, sticky, top, right, bottom, left
|
|
195
|
+
- **Flexbox** - flex, flex-direction, justify-content, align-items, flex-wrap
|
|
196
|
+
- **Grid** - grid, grid-cols, grid-rows, grid-gap
|
|
197
|
+
- **Colours** - background (`bg-`), text, borders, accent for form controls
|
|
198
|
+
- **Typography** - font-size, font-weight, line-height, text-align
|
|
199
|
+
- **Borders** - border-width, border-style, border-colour, border-radius
|
|
200
|
+
- **Shadows** - box-shadow, text-shadow
|
|
201
|
+
- **Opacity** - opacity levels
|
|
202
|
+
- **Accessibility** - sr-only, focus-visible, motion-safe, forced-colors
|
|
203
|
+
- **State variants** - `hover:`, `focus-visible:`, `active:`, `disabled:`
|
|
204
|
+
- **Responsive variants** - `sm:`, `md:`, `lg:`, `xl:`, `2xl:`
|
|
166
205
|
|
|
167
206
|
## Examples
|
|
168
207
|
|
|
169
208
|
### Button
|
|
209
|
+
|
|
170
210
|
```html
|
|
171
211
|
<button class="px-4 py-2 rounded-md bg-primary-80 text-white hover:bg-primary-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-50">
|
|
172
212
|
Click me
|
|
@@ -174,6 +214,7 @@ Emily generates utilities across these categories:
|
|
|
174
214
|
```
|
|
175
215
|
|
|
176
216
|
### Responsive Card
|
|
217
|
+
|
|
177
218
|
```html
|
|
178
219
|
<div class="w-full md:w-96 p-4 md:p-6 rounded-lg bg-neutral-10 border-1 border-neutral-30 shadow-md">
|
|
179
220
|
<h2 class="text-lg font-semibold text-neutral-90">Title</h2>
|
|
@@ -182,11 +223,12 @@ Emily generates utilities across these categories:
|
|
|
182
223
|
```
|
|
183
224
|
|
|
184
225
|
### Accessible Form Input
|
|
226
|
+
|
|
185
227
|
```html
|
|
186
228
|
<label for="email" class="block text-sm font-medium text-neutral-80">
|
|
187
229
|
Email
|
|
188
230
|
</label>
|
|
189
|
-
<input
|
|
231
|
+
<input
|
|
190
232
|
id="email"
|
|
191
233
|
type="email"
|
|
192
234
|
class="mt-1 w-full px-3 py-2 border-1 border-neutral-40 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-50"
|
|
@@ -197,52 +239,50 @@ Emily generates utilities across these categories:
|
|
|
197
239
|
|
|
198
240
|
All utilities are built with WCAG 2.2 AA in mind:
|
|
199
241
|
|
|
200
|
-
- **Focus rings**
|
|
201
|
-
- **Colour contrast**
|
|
202
|
-
- **Motion**
|
|
203
|
-
- **
|
|
204
|
-
- **
|
|
205
|
-
- **Forced colours** — Utilities respect Windows High Contrast mode
|
|
242
|
+
- **Focus rings** - Focus-visible states include proper colour contrast
|
|
243
|
+
- **Colour contrast** - All colour scales meet AA contrast ratios
|
|
244
|
+
- **Motion** - `motion-safe` and `motion-reduce` utilities for users with vestibular disorders
|
|
245
|
+
- **Screen reader support** - `.sr-only` utility for screen-reader-only content
|
|
246
|
+
- **Forced colours** - Utilities respect Windows High Contrast mode
|
|
206
247
|
|
|
207
|
-
##
|
|
248
|
+
## Testing
|
|
208
249
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
- Pre-built component tier — deferred to v2
|
|
250
|
+
```bash
|
|
251
|
+
npm test
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
66 automated tests covering colour generation, utilities, variants, config integrity, and build output. All passing.
|
|
215
255
|
|
|
216
256
|
## Troubleshooting
|
|
217
257
|
|
|
218
258
|
### Styles not applying?
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
259
|
+
|
|
260
|
+
1. Check the responsive prefix: `.md\:flex` not `.md:flex`
|
|
261
|
+
2. Verify class name spelling
|
|
262
|
+
3. Clear browser cache and rebuild: `npx emily-css build`
|
|
222
263
|
|
|
223
264
|
### File size too large?
|
|
224
|
-
|
|
265
|
+
|
|
225
266
|
```bash
|
|
226
|
-
emily-
|
|
267
|
+
npx emily-css purge
|
|
227
268
|
```
|
|
228
269
|
|
|
229
270
|
### Config not applying?
|
|
271
|
+
|
|
230
272
|
1. Edit `emily.config.json`
|
|
231
|
-
2. Run `
|
|
232
|
-
3. No cache invalidation needed
|
|
273
|
+
2. Run `npx emily-css build`
|
|
274
|
+
3. No cache invalidation needed
|
|
233
275
|
|
|
234
276
|
## CDN
|
|
235
277
|
|
|
236
|
-
Use emily-ui directly without npm via jsDelivr:
|
|
237
|
-
|
|
238
278
|
```html
|
|
239
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/emily-
|
|
279
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/emily-css/dist/emily.css">
|
|
240
280
|
```
|
|
241
281
|
|
|
242
282
|
## Support
|
|
243
283
|
|
|
244
|
-
|
|
245
|
-
https://github.com/andyjterry/emily-ui
|
|
284
|
+
- Website: https://www.emilyui.com
|
|
285
|
+
- GitHub: https://github.com/andyjterry/emily-ui
|
|
246
286
|
|
|
247
287
|
## License
|
|
248
288
|
|
package/bin/emilyui.js
CHANGED
|
@@ -6,12 +6,15 @@ if (command === "init") {
|
|
|
6
6
|
require("../src/init.js");
|
|
7
7
|
} else if (command === "build") {
|
|
8
8
|
require("../src/index.js");
|
|
9
|
+
} else if (command === "purge") {
|
|
10
|
+
require("../src/purge-cmd.js");
|
|
9
11
|
} else {
|
|
10
12
|
console.log(`
|
|
11
|
-
emily-
|
|
13
|
+
emily-css - Config-driven CSS framework generator
|
|
12
14
|
|
|
13
15
|
Usage:
|
|
14
|
-
emily-
|
|
15
|
-
emily-
|
|
16
|
+
emily-css init Set up a new project
|
|
17
|
+
emily-css build Generate emily.css from your config
|
|
18
|
+
emily-css purge Remove unused utilities for production
|
|
16
19
|
`);
|
|
17
|
-
}
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "emily-css",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "A config-driven utility CSS framework. Define your brand once, generate the CSS.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"emily-
|
|
7
|
+
"emily-css": "./bin/emilyui.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
11
|
"src/",
|
|
12
|
-
"dist/",
|
|
12
|
+
"dist/emily.css",
|
|
13
|
+
"dist/emily.min.css",
|
|
14
|
+
"dist/emily.demo.css",
|
|
15
|
+
"dist/emily.demo.min.css",
|
|
13
16
|
"fonts/",
|
|
14
17
|
"README.md",
|
|
15
18
|
"LICENSE"
|
package/src/index.js
CHANGED
|
@@ -777,7 +777,7 @@ function addStateVariants(css) {
|
|
|
777
777
|
function build(options = {}) {
|
|
778
778
|
const configPath = path.join(process.cwd(), 'emily.config.json');
|
|
779
779
|
if (!fs.existsSync(configPath)) {
|
|
780
|
-
console.error(`\n emily-
|
|
780
|
+
console.error(`\n emily-css: No config found.\n Expected: ${configPath}\n Run "emily-css init" to create one.\n`);
|
|
781
781
|
process.exit(1);
|
|
782
782
|
}
|
|
783
783
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
@@ -786,7 +786,7 @@ function build(options = {}) {
|
|
|
786
786
|
const { purgeCSS } = require('./purge.js');
|
|
787
787
|
const cssPath = path.join(process.cwd(), 'dist/emily.css');
|
|
788
788
|
if (!fs.existsSync(cssPath)) {
|
|
789
|
-
console.error(' emily-
|
|
789
|
+
console.error(' emily-css: Run "emily-css build" first.');
|
|
790
790
|
process.exit(1);
|
|
791
791
|
}
|
|
792
792
|
console.log(`Purging unused utilities from ${options.purge}...`);
|
package/src/init.js
CHANGED
|
@@ -23,16 +23,16 @@ function isValidHex(hex) {
|
|
|
23
23
|
|
|
24
24
|
// Default colours
|
|
25
25
|
const defaultColours = {
|
|
26
|
-
primary: '#
|
|
27
|
-
secondary: '#
|
|
26
|
+
primary: '#DB2777',
|
|
27
|
+
secondary: '#2563EB',
|
|
28
28
|
success: '#017F65',
|
|
29
29
|
warning: '#ffc107',
|
|
30
30
|
error: '#b20000',
|
|
31
|
-
neutral: '#
|
|
31
|
+
neutral: '#57534E'
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
// Default config template - matches emily.config.json structure
|
|
35
|
-
function createDefaultConfig(name, colours, fonts, baseUnit) {
|
|
35
|
+
function createDefaultConfig(name, colours, fonts, baseUnit, sourceDir) {
|
|
36
36
|
return {
|
|
37
37
|
name,
|
|
38
38
|
description: `${name} design system`,
|
|
@@ -206,10 +206,15 @@ async function init() {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
// 5.
|
|
210
|
-
|
|
209
|
+
// 5. Source directory for purge
|
|
210
|
+
console.log('\nSource directory for purge (where your templates/HTML live):');
|
|
211
|
+
let sourceDir = await prompt(' Source directory [./src]: ');
|
|
212
|
+
sourceDir = sourceDir.trim() || './src';
|
|
211
213
|
|
|
212
|
-
// 6.
|
|
214
|
+
// 6. Create config
|
|
215
|
+
const config = createDefaultConfig(name, colours, fonts, baseUnit, sourceDir);
|
|
216
|
+
|
|
217
|
+
// 7. Write config file to the user's project directory
|
|
213
218
|
const configPath = path.join(process.cwd(), 'emily.config.json');
|
|
214
219
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
215
220
|
|
|
@@ -219,13 +224,13 @@ async function init() {
|
|
|
219
224
|
console.log(` Base unit: ${baseUnit}px`);
|
|
220
225
|
console.log(`\n📝 Config saved: ${configPath}`);
|
|
221
226
|
|
|
222
|
-
//
|
|
227
|
+
// 8. Run build
|
|
223
228
|
console.log('\n🔨 Building CSS...\n');
|
|
224
229
|
rl.close();
|
|
225
230
|
|
|
226
231
|
// Spawn build process
|
|
227
232
|
const { spawn } = require('child_process');
|
|
228
|
-
const build = spawn('npx', ['emily-
|
|
233
|
+
const build = spawn('npx', ['emily-css', 'build'], {
|
|
229
234
|
cwd: process.cwd(),
|
|
230
235
|
stdio: 'inherit'
|
|
231
236
|
});
|
|
@@ -237,7 +242,7 @@ async function init() {
|
|
|
237
242
|
console.log(' 1. Open showcase.html in your browser to see components');
|
|
238
243
|
console.log(' 2. Copy component code into your project');
|
|
239
244
|
console.log(' 3. Update emily.config.json to customize colours/fonts');
|
|
240
|
-
console.log(' 4. Run:
|
|
245
|
+
console.log(' 4. Run: emily-css purge (to remove unused CSS for production)');
|
|
241
246
|
} else {
|
|
242
247
|
console.log('\n❌ Build failed');
|
|
243
248
|
}
|
package/src/purge-cmd.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function runPurge() {
|
|
5
|
+
const configPath = path.join(process.cwd(), 'emily.config.json');
|
|
6
|
+
|
|
7
|
+
if (!fs.existsSync(configPath)) {
|
|
8
|
+
console.error('\n emily-css: No config found. Run "emily-css init" first.\n');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
13
|
+
const sourceDir = config.purge && config.purge.sourceDir;
|
|
14
|
+
|
|
15
|
+
if (!sourceDir) {
|
|
16
|
+
console.error('\n emily-css: No purge sourceDir in emily.config.json.');
|
|
17
|
+
console.error(' Add: "purge": { "sourceDir": "./src" }\n');
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const cssPath = path.join(process.cwd(), 'dist/emily.css');
|
|
22
|
+
|
|
23
|
+
if (!fs.existsSync(cssPath)) {
|
|
24
|
+
console.error('\n emily-css: No CSS found. Run "emily-css build" first.\n');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { purgeCSS } = require('./purge.js');
|
|
29
|
+
|
|
30
|
+
console.log('\nPurging unused utilities from ' + sourceDir + '...');
|
|
31
|
+
|
|
32
|
+
const css = fs.readFileSync(cssPath, 'utf8');
|
|
33
|
+
const purged = purgeCSS(css, sourceDir);
|
|
34
|
+
const minified = purged
|
|
35
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
36
|
+
.replace(/\s+/g, ' ')
|
|
37
|
+
.replace(/\s?\{/g, '{')
|
|
38
|
+
.replace(/\s?\}/g, '}')
|
|
39
|
+
.replace(/;\s/g, ';')
|
|
40
|
+
.trim();
|
|
41
|
+
|
|
42
|
+
fs.writeFileSync(path.join(process.cwd(), 'dist/emily.purged.css'), purged);
|
|
43
|
+
fs.writeFileSync(path.join(process.cwd(), 'dist/emily.purged.min.css'), minified);
|
|
44
|
+
|
|
45
|
+
const original = Buffer.byteLength(css, 'utf8');
|
|
46
|
+
const purgedSize = Buffer.byteLength(purged, 'utf8');
|
|
47
|
+
const reduction = Math.round((1 - purgedSize / original) * 100);
|
|
48
|
+
|
|
49
|
+
console.log('\n\u2713 Purged CSS written:');
|
|
50
|
+
console.log(' dist/emily.purged.css');
|
|
51
|
+
console.log(' dist/emily.purged.min.css');
|
|
52
|
+
console.log('\n ' + Math.round(original / 1024) + 'KB -> ' + Math.round(purgedSize / 1024) + 'KB (' + reduction + '% reduction)\n');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
runPurge();
|