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 CHANGED
@@ -1,6 +1,19 @@
1
1
  # Qleaner
2
2
 
3
- A powerful CLI tool to analyze and clean up your React codebase by finding unused files and images, providing project insights, and analyzing dependencies.
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 dependencies:
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 the dependencies in the project
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, etc.)
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.0.34
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)) {
@@ -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.3",
5
+ "version": "1.1.4",
6
6
  "license": "MIT",
7
7
  "main": "command.js",
8
8
  "bin": "bin/cli.js",
@@ -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 {