emily-css 1.0.21 → 1.0.23
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/CHANGELOG.md +13 -0
- package/bin/emilyui.js +6 -0
- package/package.json +1 -1
- package/src/purge.js +19 -1
- package/src/watch.js +51 -41
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to `emily-css` are documented here.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## v1.0.23 — May 2026
|
|
8
|
+
|
|
9
|
+
**colour system redesign — brand/accent tokens + semantic colours (v1.0.23)**
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- colour system redesign — brand/accent tokens + semantic colours (v1.0.23)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
## v1.0.22 — May 2026
|
|
16
|
+
|
|
17
|
+
**· Improve purge extraction and package robustness tests**
|
|
18
|
+
|
|
19
|
+
---
|
|
7
20
|
## v1.0.21 — May 2026
|
|
8
21
|
|
|
9
22
|
**"Include bundled showcase template**
|
package/bin/emilyui.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
3
5
|
const command = process.argv[2];
|
|
6
|
+
const packageJson = require(path.join(__dirname, "..", "package.json"));
|
|
4
7
|
|
|
5
8
|
if (command === "init") {
|
|
6
9
|
require("../src/init.js");
|
|
@@ -11,6 +14,8 @@ if (command === "init") {
|
|
|
11
14
|
require("../src/watch.js");
|
|
12
15
|
} else if (command === "showcase") {
|
|
13
16
|
require("../src/showcase.js");
|
|
17
|
+
} else if (command === "version" || command === "--version" || command === "-v") {
|
|
18
|
+
console.log(packageJson.version);
|
|
14
19
|
} else if (command === "help") {
|
|
15
20
|
console.log(`
|
|
16
21
|
emily-css — Config-driven CSS framework generator
|
|
@@ -20,6 +25,7 @@ if (command === "init") {
|
|
|
20
25
|
emily-css build Generate production CSS to the configured output path
|
|
21
26
|
emily-css watch Dev mode: watch for changes and rebuild
|
|
22
27
|
emily-css showcase Launch the component showcase in your browser
|
|
28
|
+
emily-css version Show installed version
|
|
23
29
|
emily-css help Show this help text
|
|
24
30
|
|
|
25
31
|
npm scripts (added by init):
|
package/package.json
CHANGED
package/src/purge.js
CHANGED
|
@@ -57,7 +57,7 @@ function getAllFiles(dir, extensions = DEFAULT_EXTENSIONS) {
|
|
|
57
57
|
|
|
58
58
|
function extractClassNames(content) {
|
|
59
59
|
const classNames = new Set();
|
|
60
|
-
const classRegex = /class\s*=\s*["']([^"']+)["']/g;
|
|
60
|
+
const classRegex = /(?:class|className)\s*=\s*["']([^"']+)["']/g;
|
|
61
61
|
let match;
|
|
62
62
|
|
|
63
63
|
while ((match = classRegex.exec(content)) !== null) {
|
|
@@ -76,6 +76,24 @@ function extractClassNames(content) {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
const templateStringRegex = /`([^`]+)`/g;
|
|
80
|
+
|
|
81
|
+
while ((match = templateStringRegex.exec(content)) !== null) {
|
|
82
|
+
const possibleClasses = match[1].split(/\s+/);
|
|
83
|
+
|
|
84
|
+
possibleClasses.forEach((cls) => {
|
|
85
|
+
const cleaned = cls.trim();
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
cleaned &&
|
|
89
|
+
/^[a-zA-Z0-9:_./-]+$/.test(cleaned) &&
|
|
90
|
+
/[-:]/.test(cleaned)
|
|
91
|
+
) {
|
|
92
|
+
classNames.add(cleaned);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
79
97
|
return classNames;
|
|
80
98
|
}
|
|
81
99
|
|
package/src/watch.js
CHANGED
|
@@ -21,7 +21,9 @@ function readConfig() {
|
|
|
21
21
|
const configPath = path.join(process.cwd(), "emily.config.json");
|
|
22
22
|
|
|
23
23
|
if (!fs.existsSync(configPath)) {
|
|
24
|
-
console.error(
|
|
24
|
+
console.error(
|
|
25
|
+
'\n emily-css: No config found. Run "emily-css init" first.\n',
|
|
26
|
+
);
|
|
25
27
|
process.exit(1);
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -46,7 +48,9 @@ function shouldIgnore(filePath) {
|
|
|
46
48
|
"coverage/",
|
|
47
49
|
".cache/",
|
|
48
50
|
".vite/",
|
|
49
|
-
].some(
|
|
51
|
+
].some(
|
|
52
|
+
(part) => normalised.includes("/" + part) || normalised.startsWith(part),
|
|
53
|
+
);
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
function runQuietly(fn) {
|
|
@@ -83,7 +87,9 @@ function getScanFiles(config) {
|
|
|
83
87
|
".njk",
|
|
84
88
|
".liquid",
|
|
85
89
|
".hbs",
|
|
90
|
+
".js",
|
|
86
91
|
".jsx",
|
|
92
|
+
".ts",
|
|
87
93
|
".tsx",
|
|
88
94
|
".vue",
|
|
89
95
|
".php",
|
|
@@ -124,7 +130,9 @@ function collectUsedClasses(config) {
|
|
|
124
130
|
|
|
125
131
|
function getClassDiff(currentClasses) {
|
|
126
132
|
const added = [...currentClasses].filter((cls) => !previousClasses.has(cls));
|
|
127
|
-
const removed = [...previousClasses].filter(
|
|
133
|
+
const removed = [...previousClasses].filter(
|
|
134
|
+
(cls) => !currentClasses.has(cls),
|
|
135
|
+
);
|
|
128
136
|
|
|
129
137
|
previousClasses = new Set(currentClasses);
|
|
130
138
|
|
|
@@ -141,35 +149,24 @@ function formatClassList(classes) {
|
|
|
141
149
|
}
|
|
142
150
|
|
|
143
151
|
function printSummary({ currentClasses, result, added, removed }) {
|
|
144
|
-
const reduction =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
const reduction =
|
|
153
|
+
currentClasses.size === 0
|
|
154
|
+
? "100.0"
|
|
155
|
+
: (
|
|
156
|
+
((result.originalSize - result.outputSize) / result.originalSize) *
|
|
157
|
+
100
|
|
158
|
+
).toFixed(1);
|
|
159
|
+
|
|
160
|
+
const sizeKb =
|
|
161
|
+
currentClasses.size === 0 ? "0.0" : (result.outputSize / 1024).toFixed(1);
|
|
148
162
|
|
|
149
|
-
const sizeKb = (result.outputSize / 1024).toFixed(1);
|
|
150
163
|
const outputPath = result.outputPath
|
|
151
164
|
? path.relative(process.cwd(), result.outputPath)
|
|
152
165
|
: "emily.min.css";
|
|
153
166
|
|
|
154
167
|
const time = new Date().toLocaleTimeString();
|
|
155
168
|
|
|
156
|
-
|
|
157
|
-
chalk.green("✓ " + time + " updated") +
|
|
158
|
-
chalk.gray(
|
|
159
|
-
" | " +
|
|
160
|
-
currentClasses.size +
|
|
161
|
-
" classes | " +
|
|
162
|
-
sizeKb +
|
|
163
|
-
" KB | " +
|
|
164
|
-
reduction +
|
|
165
|
-
"% reduced | " +
|
|
166
|
-
outputPath,
|
|
167
|
-
),
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
if (!hasRunOnce) return;
|
|
171
|
-
|
|
172
|
-
if (removed.length > 0) {
|
|
169
|
+
if (hasRunOnce && removed.length > 0) {
|
|
173
170
|
console.log(
|
|
174
171
|
chalk.red(
|
|
175
172
|
"− removed " +
|
|
@@ -180,16 +177,27 @@ function printSummary({ currentClasses, result, added, removed }) {
|
|
|
180
177
|
);
|
|
181
178
|
}
|
|
182
179
|
|
|
183
|
-
if (added.length > 0) {
|
|
180
|
+
if (hasRunOnce && added.length > 0) {
|
|
184
181
|
console.log(
|
|
185
182
|
chalk.green(
|
|
186
|
-
"+ added " +
|
|
187
|
-
added.length +
|
|
188
|
-
" class" +
|
|
189
|
-
(added.length === 1 ? "" : "es"),
|
|
183
|
+
"+ added " + added.length + " class" + (added.length === 1 ? "" : "es"),
|
|
190
184
|
) + chalk.gray(" (" + formatClassList(added) + ")"),
|
|
191
185
|
);
|
|
192
186
|
}
|
|
187
|
+
|
|
188
|
+
console.log(
|
|
189
|
+
chalk.green("✓ " + time + " updated") +
|
|
190
|
+
chalk.gray(
|
|
191
|
+
" | " +
|
|
192
|
+
currentClasses.size +
|
|
193
|
+
" classes | " +
|
|
194
|
+
sizeKb +
|
|
195
|
+
" KB | " +
|
|
196
|
+
reduction +
|
|
197
|
+
"% reduced | " +
|
|
198
|
+
outputPath,
|
|
199
|
+
),
|
|
200
|
+
);
|
|
193
201
|
}
|
|
194
202
|
|
|
195
203
|
function runProductionUpdate(filePath) {
|
|
@@ -232,10 +240,7 @@ function runProductionUpdate(filePath) {
|
|
|
232
240
|
}
|
|
233
241
|
|
|
234
242
|
function getWatchPaths(config) {
|
|
235
|
-
return [
|
|
236
|
-
config.purge?.sourceDir || ".",
|
|
237
|
-
"emily.config.json",
|
|
238
|
-
];
|
|
243
|
+
return [config.purge?.sourceDir || ".", "emily.config.json"];
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
function queueUpdate(filePath) {
|
|
@@ -247,14 +252,19 @@ function runWatch() {
|
|
|
247
252
|
const config = readConfig();
|
|
248
253
|
const watchPaths = getWatchPaths(config);
|
|
249
254
|
|
|
250
|
-
console.log("
|
|
251
|
-
console.log(chalk.
|
|
252
|
-
console.log(
|
|
253
|
-
|
|
255
|
+
console.log("");
|
|
256
|
+
console.log(chalk.cyan("👀 EmilyUI is watching..."));
|
|
257
|
+
console.log(
|
|
258
|
+
chalk.gray(" Project: " + (config.purge?.projectType || "Unknown")),
|
|
259
|
+
);
|
|
260
|
+
console.log(
|
|
261
|
+
chalk.gray(" Output: " + (config.output?.css || "dist/emily.min.css")),
|
|
262
|
+
);
|
|
263
|
+
console.log(chalk.gray(" Watching:"));
|
|
254
264
|
|
|
255
|
-
watchPaths.forEach((item) => {
|
|
256
|
-
|
|
257
|
-
});
|
|
265
|
+
watchPaths.forEach((item) => {
|
|
266
|
+
console.log(chalk.gray(" - " + item));
|
|
267
|
+
});
|
|
258
268
|
|
|
259
269
|
runQuietly(() => ensureFullFramework());
|
|
260
270
|
runProductionUpdate();
|