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/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 shouldIgnore(filePath) {
38
- const normalised = normalisePath(filePath);
42
+ function normaliseIgnoreEntry(entry) {
43
+ return normalisePath(String(entry || ""))
44
+ .replace(/^\.\/+/, "")
45
+ .replace(/^\/+|\/+$/g, "");
46
+ }
39
47
 
40
- return [
41
- "node_modules/",
42
- ".git/",
43
- ".nuxt/",
44
- ".next/",
45
- ".output/",
46
- "dist/",
47
- "build/",
48
- "coverage/",
49
- ".cache/",
50
- ".vite/",
51
- ].some(
52
- (part) => normalised.includes("/" + part) || normalised.startsWith(part),
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();