qleaner 1.0.29 → 1.0.31
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/bin/cli.js +2 -2
- package/controllers/image.js +24 -17
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -47,7 +47,7 @@ async function loadChalk() {
|
|
|
47
47
|
)
|
|
48
48
|
.option("-t, --table", "Print the results in a table")
|
|
49
49
|
.option("-d, --dry-run", "Show what would be deleted without actually deleting (skips prompt)")
|
|
50
|
-
.option("-C, --clear-cache", "Clear the cache")
|
|
50
|
+
.option("-C, --clear-cache", "Clear the cache recommended after making code changes")
|
|
51
51
|
.action(async (path, options) => {
|
|
52
52
|
if(options.clearCache) {
|
|
53
53
|
clearCache(process.cwd());
|
|
@@ -75,7 +75,7 @@ async function loadChalk() {
|
|
|
75
75
|
)
|
|
76
76
|
.option("-t, --table", "Print the results in a table")
|
|
77
77
|
.option("-d, --dry-run", "Show what would be deleted without actually deleting (skips prompt)")
|
|
78
|
-
.option("-C, --clear-cache", "Clear the cache")
|
|
78
|
+
.option("-C, --clear-cache", "Clear the cache recommended after making code changes")
|
|
79
79
|
.action(async (directory, rootPath, options) => {
|
|
80
80
|
await getUnusedImages(chalk, directory, rootPath, options);
|
|
81
81
|
});
|
package/controllers/image.js
CHANGED
|
@@ -64,11 +64,7 @@ function extractFromJSXStyle(node, file, collected) {
|
|
|
64
64
|
if (!expr || expr.type !== "ObjectExpression") return;
|
|
65
65
|
|
|
66
66
|
expr.properties.forEach((prop) => {
|
|
67
|
-
if (
|
|
68
|
-
prop.type !== "ObjectProperty" ||
|
|
69
|
-
!prop.key ||
|
|
70
|
-
!prop.value
|
|
71
|
-
) return;
|
|
67
|
+
if (prop.type !== "ObjectProperty" || !prop.key || !prop.value) return;
|
|
72
68
|
|
|
73
69
|
const keyName = prop.key.name || prop.key.value;
|
|
74
70
|
|
|
@@ -109,17 +105,30 @@ function extractFromJSXStyle(node, file, collected) {
|
|
|
109
105
|
async function getUnusedImages(chalk, imageDirectory, codeDirectory, options) {
|
|
110
106
|
const used = new Set();
|
|
111
107
|
const unusedImages = [];
|
|
108
|
+
const codePaths = [[`${codeDirectory}/**/*.{js,jsx,ts,tsx}`]];
|
|
112
109
|
|
|
113
110
|
// ---- Collect image files in asset directory ----
|
|
114
|
-
const imageFiles = await fg([
|
|
111
|
+
const imageFiles = await fg([
|
|
112
|
+
`${imageDirectory}/**/*.{png,jpg,jpeg,svg,gif,webp}`,
|
|
113
|
+
]);
|
|
115
114
|
|
|
115
|
+
if (options.excludeDir && options.excludeDir.length > 0) {
|
|
116
|
+
options.excludeDir.forEach((dir) => {
|
|
117
|
+
codePaths.push(`!${dir}/**`);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (options.excludeFile && options.excludeFile.length > 0) {
|
|
121
|
+
options.excludeFile.forEach((file) => {
|
|
122
|
+
codePaths.push(`!${codeDirectory}/**/${file}`);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
116
125
|
// ---- Scan Code Files ----
|
|
117
|
-
const codeFiles = await fg(
|
|
126
|
+
const codeFiles = await fg(codePaths);
|
|
118
127
|
let index = 0;
|
|
119
128
|
for (const file of codeFiles) {
|
|
120
129
|
index++;
|
|
121
130
|
console.clear();
|
|
122
|
-
console.log(
|
|
131
|
+
console.log("Scanning code files...", index, "of", codeFiles.length);
|
|
123
132
|
const code = fs.readFileSync(file, "utf8");
|
|
124
133
|
|
|
125
134
|
const ast = parser.parse(code, {
|
|
@@ -219,9 +228,7 @@ async function getUnusedImages(chalk, imageDirectory, codeDirectory, options) {
|
|
|
219
228
|
|
|
220
229
|
// detect url("...") inside strings (e.g., Tailwind)
|
|
221
230
|
const matches = [...val.matchAll(URL_EXTRACT_REGEX)];
|
|
222
|
-
matches.forEach((m) =>
|
|
223
|
-
used.add(JSON.stringify({ path: m[2], file }))
|
|
224
|
-
);
|
|
231
|
+
matches.forEach((m) => used.add(JSON.stringify({ path: m[2], file })));
|
|
225
232
|
},
|
|
226
233
|
|
|
227
234
|
/**
|
|
@@ -256,7 +263,7 @@ async function getUnusedImages(chalk, imageDirectory, codeDirectory, options) {
|
|
|
256
263
|
for (const entry of used) {
|
|
257
264
|
index++;
|
|
258
265
|
console.clear();
|
|
259
|
-
console.log(
|
|
266
|
+
console.log("Normalizing images...", index, "of", used.size);
|
|
260
267
|
const { path: p } = JSON.parse(entry);
|
|
261
268
|
const normalized = normalize(p, imageDirectory);
|
|
262
269
|
if (normalized) normalizedUsed.add(normalized);
|
|
@@ -267,7 +274,7 @@ async function getUnusedImages(chalk, imageDirectory, codeDirectory, options) {
|
|
|
267
274
|
for (const img of imageFiles) {
|
|
268
275
|
index++;
|
|
269
276
|
console.clear();
|
|
270
|
-
console.log(
|
|
277
|
+
console.log("Determining unused images...", index, "of", imageFiles.length);
|
|
271
278
|
const full = path.resolve(img);
|
|
272
279
|
if (!normalizedUsed.has(full)) {
|
|
273
280
|
unusedImages.push(full);
|
|
@@ -276,7 +283,9 @@ async function getUnusedImages(chalk, imageDirectory, codeDirectory, options) {
|
|
|
276
283
|
// ---- Output table or list ----
|
|
277
284
|
if (options.table) {
|
|
278
285
|
const table = new Table({
|
|
279
|
-
head: options.dryRun
|
|
286
|
+
head: options.dryRun
|
|
287
|
+
? ["Unused Images (Would Delete)"]
|
|
288
|
+
: ["Unused Images"],
|
|
280
289
|
colWidths: [100],
|
|
281
290
|
});
|
|
282
291
|
unusedImages.forEach((img) => table.push([img]));
|
|
@@ -288,9 +297,7 @@ async function getUnusedImages(chalk, imageDirectory, codeDirectory, options) {
|
|
|
288
297
|
// ---- deletion logic ----
|
|
289
298
|
if (options.dryRun) {
|
|
290
299
|
console.log(
|
|
291
|
-
chalk.cyan(
|
|
292
|
-
`\n[DRY RUN] Would delete ${unusedImages.length} file(s)`
|
|
293
|
-
)
|
|
300
|
+
chalk.cyan(`\n[DRY RUN] Would delete ${unusedImages.length} file(s)`)
|
|
294
301
|
);
|
|
295
302
|
} else if (unusedImages.length > 0) {
|
|
296
303
|
askDeleteFiles(unusedImages);
|