emily-css 1.1.1 → 1.2.0
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 +23 -0
- package/README.md +10 -1
- package/bin/emilyui.js +30 -13
- package/package.json +1 -1
- package/src/constants.js +65 -0
- package/src/doctor.js +1 -22
- package/src/generators.js +20 -19
- package/src/index.js +8 -7
- package/src/init.js +2 -36
- package/src/manifest.js +4 -19
- package/src/migrate.js +882 -0
- package/src/purge.js +1 -22
- package/src/reporters/migrationReporter.js +71 -0
- package/src/watch.js +32 -40
package/src/purge.js
CHANGED
|
@@ -2,28 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
-
|
|
6
|
-
const DEFAULT_EXTENSIONS = [
|
|
7
|
-
".html",
|
|
8
|
-
".htm",
|
|
9
|
-
".twig",
|
|
10
|
-
".njk",
|
|
11
|
-
".liquid",
|
|
12
|
-
".hbs",
|
|
13
|
-
".js",
|
|
14
|
-
".jsx",
|
|
15
|
-
".ts",
|
|
16
|
-
".tsx",
|
|
17
|
-
".vue",
|
|
18
|
-
".php",
|
|
19
|
-
".astro",
|
|
20
|
-
".svelte",
|
|
21
|
-
".blade.php",
|
|
22
|
-
".jinja",
|
|
23
|
-
".jinja2",
|
|
24
|
-
".j2",
|
|
25
|
-
".md",
|
|
26
|
-
];
|
|
5
|
+
const { DEFAULT_EXTENSIONS } = require("./constants.js");
|
|
27
6
|
|
|
28
7
|
function getAllFiles(dir, extensions = DEFAULT_EXTENSIONS) {
|
|
29
8
|
let files = [];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function pushListSection(lines, title, items, limit = 20) {
|
|
2
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
lines.push('', `${title}:`);
|
|
7
|
+
items.slice(0, limit).forEach((item) => {
|
|
8
|
+
lines.push(` - ${item}`);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
if (items.length > limit) {
|
|
12
|
+
lines.push(` ...and ${items.length - limit} more`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function formatMigrationReport(report, options = {}) {
|
|
17
|
+
const importColours = options.importColours === true;
|
|
18
|
+
const lines = [
|
|
19
|
+
'',
|
|
20
|
+
'EmilyCSS migration report',
|
|
21
|
+
` Files scanned: ${report.files.length}`,
|
|
22
|
+
` Total classes found: ${report.found.length}`,
|
|
23
|
+
` Supported EmilyCSS classes: ${report.supported.length}`,
|
|
24
|
+
` Known Tailwind classes: ${report.knownTailwind.length}`,
|
|
25
|
+
` Suggested replacements: ${report.replacements.length}`,
|
|
26
|
+
` Unsupported classes: ${report.unsupported.length}`,
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
if (importColours) {
|
|
30
|
+
lines.push(` Migration mode: imported-palettes`);
|
|
31
|
+
lines.push(` Imported palettes detected: ${report.importedPalettes.length}`);
|
|
32
|
+
} else {
|
|
33
|
+
lines.push(` Migration mode: semantic`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pushListSection(
|
|
37
|
+
lines,
|
|
38
|
+
'Suggested replacements',
|
|
39
|
+
report.replacements.map((entry) => `${entry.from} -> ${entry.to}`),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
pushListSection(lines, 'Unsupported classes', report.unsupported);
|
|
43
|
+
pushListSection(lines, 'Unsupported arbitrary value utilities detected', report.arbitraryValueUtilities);
|
|
44
|
+
|
|
45
|
+
if (report.warnings.length > 0) {
|
|
46
|
+
lines.push('', 'Warnings:');
|
|
47
|
+
report.warnings.forEach((warning) => {
|
|
48
|
+
lines.push(` - ${warning}`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (importColours) {
|
|
53
|
+
pushListSection(
|
|
54
|
+
lines,
|
|
55
|
+
'Imported palette colour mappings',
|
|
56
|
+
report.importedPaletteMappings.map((entry) => `${entry.from} -> ${entry.to}`),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
if (report.importedPalettesConfig) {
|
|
60
|
+
lines.push('', 'Suggested importedPalettes config:');
|
|
61
|
+
lines.push(report.importedPalettesConfig);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
lines.push('');
|
|
66
|
+
return lines.join('\n');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
formatMigrationReport,
|
|
71
|
+
};
|
package/src/watch.js
CHANGED
|
@@ -3,6 +3,10 @@ const path = require("path");
|
|
|
3
3
|
const chokidar = require("chokidar");
|
|
4
4
|
const chalk = require("chalk");
|
|
5
5
|
const fg = require("fast-glob");
|
|
6
|
+
const {
|
|
7
|
+
DEFAULT_PURGE_IGNORE,
|
|
8
|
+
DEFAULT_EXTENSIONS,
|
|
9
|
+
} = require("./constants.js");
|
|
6
10
|
|
|
7
11
|
const {
|
|
8
12
|
buildFullFramework,
|
|
@@ -16,6 +20,7 @@ let isRunning = false;
|
|
|
16
20
|
let pendingRun = false;
|
|
17
21
|
let previousClasses = new Set();
|
|
18
22
|
let hasRunOnce = false;
|
|
23
|
+
let activeIgnoreList = DEFAULT_PURGE_IGNORE;
|
|
19
24
|
|
|
20
25
|
function readConfig() {
|
|
21
26
|
const configPath = path.join(process.cwd(), "emily.config.json");
|
|
@@ -34,22 +39,26 @@ function normalisePath(filePath) {
|
|
|
34
39
|
return filePath.replace(/\\/g, "/");
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
function
|
|
38
|
-
|
|
42
|
+
function normaliseIgnoreEntry(entry) {
|
|
43
|
+
return normalisePath(String(entry || ""))
|
|
44
|
+
.replace(/^\.\/+/, "")
|
|
45
|
+
.replace(/^\/+|\/+$/g, "");
|
|
46
|
+
}
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
function shouldIgnore(filePath, ignoreList = DEFAULT_PURGE_IGNORE) {
|
|
49
|
+
if (!filePath) return false;
|
|
50
|
+
|
|
51
|
+
const normalised = normalisePath(filePath);
|
|
52
|
+
const normalisedIgnoreList = (Array.isArray(ignoreList) ? ignoreList : DEFAULT_PURGE_IGNORE)
|
|
53
|
+
.map(normaliseIgnoreEntry)
|
|
54
|
+
.filter(Boolean);
|
|
55
|
+
|
|
56
|
+
return normalisedIgnoreList.some(
|
|
57
|
+
(entry) =>
|
|
58
|
+
normalised === entry ||
|
|
59
|
+
normalised.startsWith(entry + "/") ||
|
|
60
|
+
normalised.includes("/" + entry + "/") ||
|
|
61
|
+
normalised.endsWith("/" + entry),
|
|
53
62
|
);
|
|
54
63
|
}
|
|
55
64
|
|
|
@@ -80,27 +89,7 @@ function getScanFiles(config) {
|
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
const sourceDir = config.purge?.sourceDir || ".";
|
|
83
|
-
const extensions = config.purge?.extensions ||
|
|
84
|
-
".html",
|
|
85
|
-
".htm",
|
|
86
|
-
".twig",
|
|
87
|
-
".njk",
|
|
88
|
-
".liquid",
|
|
89
|
-
".hbs",
|
|
90
|
-
".js",
|
|
91
|
-
".jsx",
|
|
92
|
-
".ts",
|
|
93
|
-
".tsx",
|
|
94
|
-
".vue",
|
|
95
|
-
".php",
|
|
96
|
-
".astro",
|
|
97
|
-
".svelte",
|
|
98
|
-
".blade.php",
|
|
99
|
-
".jinja",
|
|
100
|
-
".jinja2",
|
|
101
|
-
".j2",
|
|
102
|
-
".md",
|
|
103
|
-
];
|
|
92
|
+
const extensions = config.purge?.extensions || DEFAULT_EXTENSIONS;
|
|
104
93
|
|
|
105
94
|
return fg.sync(
|
|
106
95
|
extensions.map((ext) => `${sourceDir.replace(/\/$/, "")}/**/*${ext}`),
|
|
@@ -115,9 +104,10 @@ function getScanFiles(config) {
|
|
|
115
104
|
function collectUsedClasses(config) {
|
|
116
105
|
const files = getScanFiles(config);
|
|
117
106
|
const usedClasses = new Set();
|
|
107
|
+
const ignoreList = config.purge?.ignore || DEFAULT_PURGE_IGNORE;
|
|
118
108
|
|
|
119
109
|
for (const file of files) {
|
|
120
|
-
if (shouldIgnore(file)) continue;
|
|
110
|
+
if (shouldIgnore(file, ignoreList)) continue;
|
|
121
111
|
|
|
122
112
|
try {
|
|
123
113
|
const content = fs.readFileSync(file, "utf8");
|
|
@@ -210,6 +200,7 @@ function runProductionUpdate(filePath) {
|
|
|
210
200
|
|
|
211
201
|
try {
|
|
212
202
|
const config = readConfig();
|
|
203
|
+
activeIgnoreList = config.purge?.ignore || DEFAULT_PURGE_IGNORE;
|
|
213
204
|
const normalisedFilePath = filePath ? normalisePath(filePath) : "";
|
|
214
205
|
const isConfigChange = normalisedFilePath.endsWith("emily.config.json");
|
|
215
206
|
|
|
@@ -244,12 +235,13 @@ function getWatchPaths(config) {
|
|
|
244
235
|
}
|
|
245
236
|
|
|
246
237
|
function queueUpdate(filePath) {
|
|
247
|
-
if (filePath && shouldIgnore(filePath)) return;
|
|
238
|
+
if (filePath && shouldIgnore(filePath, activeIgnoreList)) return;
|
|
248
239
|
runProductionUpdate(filePath);
|
|
249
240
|
}
|
|
250
241
|
|
|
251
242
|
function runWatch() {
|
|
252
243
|
const config = readConfig();
|
|
244
|
+
activeIgnoreList = config.purge?.ignore || DEFAULT_PURGE_IGNORE;
|
|
253
245
|
const watchPaths = getWatchPaths(config);
|
|
254
246
|
|
|
255
247
|
console.log("");
|
|
@@ -270,7 +262,7 @@ function runWatch() {
|
|
|
270
262
|
runProductionUpdate();
|
|
271
263
|
|
|
272
264
|
const watcher = chokidar.watch(watchPaths, {
|
|
273
|
-
ignored: shouldIgnore,
|
|
265
|
+
ignored: (filePath) => shouldIgnore(filePath, activeIgnoreList),
|
|
274
266
|
ignoreInitial: true,
|
|
275
267
|
awaitWriteFinish: {
|
|
276
268
|
stabilityThreshold: 500,
|
|
@@ -288,4 +280,4 @@ function runWatch() {
|
|
|
288
280
|
});
|
|
289
281
|
}
|
|
290
282
|
|
|
291
|
-
runWatch();
|
|
283
|
+
runWatch();
|