qleaner 1.1.3 → 1.1.4
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 +46 -14
- package/command.js +2 -8
- package/controllers/image.js +1 -1
- package/controllers/initialize.js +3 -3
- package/package.json +1 -1
- package/qleaner.config.json +4 -4
- package/utils/cache.js +9 -1
package/README.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# Qleaner
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
❌ Afraid to delete files in a React project?
|
|
4
|
+
❌ Unsure what's still used?
|
|
5
|
+
❌ Large repos slowing down devs?
|
|
6
|
+
|
|
7
|
+
**Qleaner answers those questions safely.**
|
|
8
|
+
|
|
9
|
+
Qleaner scans your entire codebase with precision, finding unused files, dead assets, and architectural rot—without the risk. It tells you exactly what's safe to delete, backed by comprehensive dependency analysis.
|
|
10
|
+
|
|
11
|
+
**Developers star tools that:**
|
|
12
|
+
|
|
13
|
+
- **Save them time** — No more manual hunting through imports and references
|
|
14
|
+
- **Reduce fear** — Dry-run mode shows you exactly what would be deleted before you commit
|
|
15
|
+
- **Prevent mistakes** — Smart caching and incremental scans catch everything
|
|
16
|
+
- **Make them look smart at work** — Clean codebases speak volumes
|
|
4
17
|
|
|
5
18
|
## Features
|
|
6
19
|
|
|
@@ -17,6 +30,9 @@ A powerful CLI tool to analyze and clean up your React codebase by finding unuse
|
|
|
17
30
|
- 💾 **Smart caching**: Caches scan results for faster subsequent runs (automatically invalidates on file changes)
|
|
18
31
|
- 🎨 **CSS and styled-components support**: Detects images used in CSS files and styled-components
|
|
19
32
|
- 🔧 **Configuration file**: Use `qleaner init` to create a `qleaner.config.json` file with default settings for your project
|
|
33
|
+
- 🔗 **Dead link detection**: Identifies images referenced in code but not found in the file system
|
|
34
|
+
- 🔥 **File hotspot analysis**: Discover the most imported files and image hotspots in your codebase
|
|
35
|
+
- ⚠️ **Large file warnings**: Automatically flags code files exceeding 100KB for optimization
|
|
20
36
|
|
|
21
37
|
## Installation
|
|
22
38
|
|
|
@@ -45,29 +61,37 @@ This creates a configuration file with default settings for exclusions and image
|
|
|
45
61
|
|
|
46
62
|
### Project Summary
|
|
47
63
|
|
|
48
|
-
Get a comprehensive summary of your project including file counts, unused files/images, and
|
|
64
|
+
Get a comprehensive summary of your project including file counts, unused files/images, dead links, dependencies, and file hotspots:
|
|
49
65
|
|
|
50
66
|
```bash
|
|
51
67
|
qleaner summary [options]
|
|
52
68
|
```
|
|
53
69
|
|
|
54
70
|
**Options:**
|
|
55
|
-
- `-l, --largest-files` - List the largest files in the project
|
|
56
|
-
- `-d, --dependencies` - List
|
|
71
|
+
- `-l, --largest-files` - List the largest files in the project (top 10 code files, top 10 image files, files above 100KB, and total sizes)
|
|
72
|
+
- `-d, --dependencies` - List dependency analysis (heavy/light dependencies, file hotspots, dead/alive image hotspots)
|
|
57
73
|
|
|
58
74
|
**Examples:**
|
|
59
75
|
|
|
60
76
|
```bash
|
|
61
77
|
# Get project summary (default)
|
|
78
|
+
# Shows: total code files, total image files, unused files, unused images, dead image links
|
|
62
79
|
qleaner summary
|
|
63
80
|
|
|
64
81
|
# List the largest files
|
|
82
|
+
# Shows: top 10 largest code files, top 10 largest image files, files above 100KB, total sizes
|
|
65
83
|
qleaner summary --largest-files
|
|
66
84
|
|
|
67
85
|
# List dependencies
|
|
86
|
+
# Shows: files with heavy/light dependencies, file hotspots (most imported files), dead/alive image hotspots
|
|
68
87
|
qleaner summary --dependencies
|
|
69
88
|
```
|
|
70
89
|
|
|
90
|
+
**Summary includes:**
|
|
91
|
+
- **Default summary**: Total code/image files, unused files/images count, dead image links count
|
|
92
|
+
- **Largest files** (`--largest-files`): Top 10 largest code files, top 10 largest image files, code files exceeding 100KB, total code/image sizes
|
|
93
|
+
- **Dependencies** (`--dependencies`): Top 10 files with heavy dependencies, top 10 files with light dependencies, top 10 file hotspots (most imported), top 10 dead/alive image hotspots
|
|
94
|
+
|
|
71
95
|
**Important:** Before viewing the summary, make sure to run a fresh scan with `--clear-cache` to ensure accurate results. The summary reads from the cache, so outdated cache data will show outdated results.
|
|
72
96
|
|
|
73
97
|
### Scan for Unused Files
|
|
@@ -186,13 +210,15 @@ qleaner image public/images src --clear-cache
|
|
|
186
210
|
```
|
|
187
211
|
|
|
188
212
|
**What it detects:**
|
|
189
|
-
- Images imported via `import` statements
|
|
213
|
+
- Images imported via `import` statements (static and dynamic imports)
|
|
190
214
|
- Images required via `require()` calls
|
|
191
|
-
- Images used in JSX `src` attributes
|
|
215
|
+
- Images used in JSX `src` attributes (string literals and expressions)
|
|
192
216
|
- Images in CSS `url()` functions (CSS and SCSS files)
|
|
193
217
|
- Images in styled-components and CSS-in-JS template literals
|
|
194
|
-
- Images in inline styles (backgroundImage,
|
|
195
|
-
- Images referenced in string literals and template literals
|
|
218
|
+
- Images in inline styles (backgroundImage, background, mask, and other image-related properties)
|
|
219
|
+
- Images referenced in string literals and template literals anywhere in code
|
|
220
|
+
- Images in array expressions and spread elements
|
|
221
|
+
- **Dead links**: Images referenced in code but not found in the file system
|
|
196
222
|
|
|
197
223
|
## Output Formats
|
|
198
224
|
|
|
@@ -207,7 +233,7 @@ Qleaner provides two output formats:
|
|
|
207
233
|
2. **Table output**: Formatted tables with organized columns (use `--table` flag)
|
|
208
234
|
- Unused files table shows: Unused file paths with sizes (or "Would Delete" in dry run mode)
|
|
209
235
|
- Unused images table shows: Unused image paths with information about whether they exist and are referenced in code (or "Would Delete" in dry run mode)
|
|
210
|
-
- Summary tables show: Project statistics, largest files, dependencies, and more
|
|
236
|
+
- Summary tables show: Project statistics, largest files, dependencies, file hotspots, dead/alive image hotspots, and more
|
|
211
237
|
|
|
212
238
|
## How It Works
|
|
213
239
|
|
|
@@ -228,12 +254,15 @@ Qleaner provides two output formats:
|
|
|
228
254
|
2. **Code Scanning**: Scans all code files (`.js`, `.jsx`, `.ts`, `.tsx`) for image references
|
|
229
255
|
3. **Image Detection**: Detects images through multiple methods:
|
|
230
256
|
- Import statements (`import img from './image.png'`)
|
|
257
|
+
- Dynamic imports (`import('./image.png')`)
|
|
231
258
|
- Require calls (`require('./image.png')`)
|
|
232
|
-
- JSX src attributes (`<img src="./image.png" />`)
|
|
259
|
+
- JSX src attributes (`<img src="./image.png" />` and expressions)
|
|
233
260
|
- CSS url() functions in CSS/SCSS files
|
|
234
261
|
- Styled-components and CSS-in-JS template literals
|
|
235
|
-
- Inline styles (backgroundImage, etc.)
|
|
236
|
-
- String and template literals containing image paths
|
|
262
|
+
- Inline styles (backgroundImage, background, mask, etc.)
|
|
263
|
+
- String and template literals containing image paths (anywhere in code)
|
|
264
|
+
- Array expressions with image paths (`['/img/a.png', '/img/b.png']`)
|
|
265
|
+
- Spread elements in arrays with image references
|
|
237
266
|
4. **Path Normalization**: Normalizes all detected image paths for consistent matching
|
|
238
267
|
5. **Analysis**: Compares discovered image files with detected references to identify unused images
|
|
239
268
|
6. **Reporting**: Outputs the results in standard or table format
|
|
@@ -265,7 +294,10 @@ Qleaner provides two output formats:
|
|
|
265
294
|
- 📊 **Code analysis**: Understand import patterns and dependencies in your codebase through the summary command
|
|
266
295
|
- 🔍 **Project audit**: Identify orphaned files and assets that may have been forgotten
|
|
267
296
|
- 📦 **Bundle optimization**: Find files and images that can be removed to reduce bundle size
|
|
268
|
-
- 📈 **Project insights**: Analyze largest files, dependency patterns, and project statistics
|
|
297
|
+
- 📈 **Project insights**: Analyze largest files, dependency patterns, file hotspots, and project statistics
|
|
298
|
+
- 🔗 **Dead link detection**: Find broken image references (images in code that don't exist on disk)
|
|
299
|
+
- 🔥 **Architecture insights**: Discover which files are most imported (hotspots) and identify dependency-heavy files
|
|
300
|
+
- ⚠️ **Performance warnings**: Get alerted about large files (100KB+) that may impact performance
|
|
269
301
|
- 🎯 **Maintenance**: Keep your codebase clean and maintainable
|
|
270
302
|
|
|
271
303
|
## Configuration
|
|
@@ -365,4 +397,4 @@ MIT
|
|
|
365
397
|
|
|
366
398
|
## Version
|
|
367
399
|
|
|
368
|
-
Current version: 1.
|
|
400
|
+
Current version: 1.1.3
|
package/command.js
CHANGED
|
@@ -10,7 +10,6 @@ const {
|
|
|
10
10
|
getFileHash,
|
|
11
11
|
needsRebuild,
|
|
12
12
|
saveCache,
|
|
13
|
-
clearCache,
|
|
14
13
|
} = require("./utils/cache");
|
|
15
14
|
const { isExcludedFile, createStepBar } = require("./utils/utils");
|
|
16
15
|
|
|
@@ -114,13 +113,8 @@ async function getFiles(directory = "src", options, chalk) {
|
|
|
114
113
|
|
|
115
114
|
// Initializes the cache by clearing it (if requested) and loading it from disk
|
|
116
115
|
function initializeCache(spinner, options, code = true) {
|
|
117
|
-
if (options.clearCache) {
|
|
118
|
-
spinner.text = "🔍 Clearing cache...";
|
|
119
|
-
clearCache(process.cwd());
|
|
120
|
-
spinner.succeed("Cache cleared successfully");
|
|
121
|
-
}
|
|
122
116
|
spinner.text = "🔍 Loading cache...";
|
|
123
|
-
const cache = loadCache(process.cwd());
|
|
117
|
+
const cache = loadCache(process.cwd(), {code, clearCache: options.clearCache});
|
|
124
118
|
let graph = null;
|
|
125
119
|
let imageGraph = null;
|
|
126
120
|
if (code) {
|
|
@@ -182,7 +176,7 @@ async function extractImportsFromFiles(files, graph, resolver, chalk) {
|
|
|
182
176
|
if (isNeedsRebuild) {
|
|
183
177
|
const ast = parser.parse(code, {
|
|
184
178
|
sourceType: "module",
|
|
185
|
-
plugins: ["jsx", "typescript"],
|
|
179
|
+
plugins: ["jsx", "typescript", "decorators-legacy"],
|
|
186
180
|
});
|
|
187
181
|
// check if file is already in graph
|
|
188
182
|
if (graph.has(filePath)) {
|
package/controllers/image.js
CHANGED
|
@@ -361,7 +361,7 @@ async function scanCodeFilesForImages(
|
|
|
361
361
|
if (needsRebuild(filePath, code, imageGraph)) {
|
|
362
362
|
const ast = parser.parse(code, {
|
|
363
363
|
sourceType: "module",
|
|
364
|
-
plugins: ["jsx", "typescript"],
|
|
364
|
+
plugins: ["jsx", "typescript", "decorators-legacy"],
|
|
365
365
|
});
|
|
366
366
|
if (imageGraph.has(filePath)) {
|
|
367
367
|
const oldFiles = new Set(imageGraph.get(filePath).imports);
|
|
@@ -13,6 +13,8 @@ async function init(chalk) {
|
|
|
13
13
|
excludeExtensions: [
|
|
14
14
|
"test.tsx",
|
|
15
15
|
"test.ts",
|
|
16
|
+
"test.js",
|
|
17
|
+
"test.jsx",
|
|
16
18
|
], // Exclude file extensions from the scan like .test.tsx, .test.ts, .test.js, .test.jsx
|
|
17
19
|
excludeFilePrint: [
|
|
18
20
|
"page.tsx",
|
|
@@ -27,9 +29,7 @@ async function init(chalk) {
|
|
|
27
29
|
"dist",
|
|
28
30
|
"build",
|
|
29
31
|
], // Exclude directories from the code scan
|
|
30
|
-
excludeFileCode: [
|
|
31
|
-
"index.tsx",
|
|
32
|
-
], // Exclude files from the code scan
|
|
32
|
+
excludeFileCode: [], // Exclude files from the code scan
|
|
33
33
|
isRootFolderReferenced: false, // Is the root folder referenced in the image path eg /img/a.png where img is the image root folder
|
|
34
34
|
alias: true, // Is the alias referenced in the image path eg @/assets/images/a.png
|
|
35
35
|
}, null, 2));
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "qleaner",
|
|
3
3
|
"description": "A CLI tool for analyzing and identifying unused files, images, imports, and dead code in React, TypeScript, and JavaScript projects to help optimize bundle size and maintain clean codebases",
|
|
4
4
|
"packageManager": "yarn@4.6.0",
|
|
5
|
-
"version": "1.1.
|
|
5
|
+
"version": "1.1.4",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "command.js",
|
|
8
8
|
"bin": "bin/cli.js",
|
package/qleaner.config.json
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
"excludeFile": [],
|
|
8
8
|
"excludeExtensions": [
|
|
9
9
|
"test.tsx",
|
|
10
|
-
"test.ts"
|
|
10
|
+
"test.ts",
|
|
11
|
+
"test.js",
|
|
12
|
+
"test.jsx"
|
|
11
13
|
],
|
|
12
14
|
"excludeFilePrint": [
|
|
13
15
|
"page.tsx",
|
|
@@ -22,9 +24,7 @@
|
|
|
22
24
|
"dist",
|
|
23
25
|
"build"
|
|
24
26
|
],
|
|
25
|
-
"excludeFileCode": [
|
|
26
|
-
"index.tsx"
|
|
27
|
-
],
|
|
27
|
+
"excludeFileCode": [],
|
|
28
28
|
"isRootFolderReferenced": false,
|
|
29
29
|
"alias": true
|
|
30
30
|
}
|
package/utils/cache.js
CHANGED
|
@@ -46,7 +46,7 @@ function serializeGraph({ parentGraph, imageParentGraph, isCode = true }) {
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function loadCache(rootPath) {
|
|
49
|
+
function loadCache(rootPath, {clearCache, code}) {
|
|
50
50
|
const file = path.join(rootPath, "unused-check-cache.json");
|
|
51
51
|
if (!fs.existsSync(file))
|
|
52
52
|
return {
|
|
@@ -62,6 +62,14 @@ function loadCache(rootPath) {
|
|
|
62
62
|
imageParentGraph: { imageGraph: {}, unusedImages: [] },
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
if(clearCache) {
|
|
66
|
+
if(code) {
|
|
67
|
+
cache.parentGraph = { graph: {}, unusedFiles: [] };
|
|
68
|
+
} else {
|
|
69
|
+
cache.imageParentGraph = { imageGraph: {}, unusedImages: [] };
|
|
70
|
+
}
|
|
71
|
+
fs.writeFileSync(file, JSON.stringify(cache, null, 2));
|
|
72
|
+
}
|
|
65
73
|
return cache;
|
|
66
74
|
} catch {
|
|
67
75
|
return {
|