qleaner 1.0.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.
Binary file
package/AssetInCode.js ADDED
@@ -0,0 +1,90 @@
1
+ const fs = require("fs");
2
+ const fg = require("fast-glob");
3
+ const parser = require("@babel/parser");
4
+ const traverse = require("@babel/traverse").default;
5
+
6
+ async function getAssetInCode() {
7
+ const usedImages = new Set();
8
+
9
+ const imageRegex = /\.(png|jpg|jpeg|svg|gif|webp)$/i;
10
+
11
+ const codeFiles = await fg([
12
+ "src/**/*.{tsx,ts,js,jsx}"
13
+ ]);
14
+ console.log(codeFiles);
15
+ for (const file of codeFiles) {
16
+ const code = fs.readFileSync(file, "utf8");
17
+ const ast = parser.parse(code, {
18
+ sourceType: "module",
19
+ plugins: ["jsx", "typescript"],
20
+ });
21
+
22
+ traverse(ast, {
23
+ // <img src="...">
24
+ JSXAttribute(path) {
25
+ if (path.node.name.name !== "src") return;
26
+
27
+ const value = path.node.value;
28
+
29
+ if (value.type === "StringLiteral") {
30
+ if (imageRegex.test(value.value)) {
31
+ usedImages.add(value.value);
32
+ }
33
+ }
34
+
35
+ if (value.type === "JSXExpressionContainer") {
36
+ const expr = value.expression;
37
+
38
+ if (expr.type === "StringLiteral" && imageRegex.test(expr.value)) {
39
+ usedImages.add(expr.value);
40
+ }
41
+
42
+ if (expr.type === "TemplateLiteral") {
43
+ expr.quasis.forEach((q) => {
44
+ if (imageRegex.test(q.value.raw)) {
45
+ usedImages.add(q.value.raw);
46
+ }
47
+ });
48
+ }
49
+ }
50
+ },
51
+
52
+ // String literals anywhere in code
53
+ StringLiteral(path) {
54
+ if (imageRegex.test(path.node.value)) {
55
+ usedImages.add(path.node.value);
56
+ }
57
+ },
58
+
59
+ // Template literals: `/images/${name}.png`
60
+ TemplateLiteral(path) {
61
+ path.node.quasis.forEach((quasi) => {
62
+ if (imageRegex.test(quasi.value.raw)) {
63
+ usedImages.add(quasi.value.raw);
64
+ }
65
+ });
66
+ },
67
+
68
+ // Arrays: ["img/a.png", "img/b.png"]
69
+ ArrayExpression(path) {
70
+ path.node.elements.forEach((el) => {
71
+ if (el?.type === "StringLiteral" && imageRegex.test(el.value)) {
72
+ usedImages.add(el.value);
73
+ }
74
+ });
75
+ },
76
+
77
+ // Objects: { image: "img/a.png" }
78
+ ObjectProperty(path) {
79
+ const val = path.node.value;
80
+ if (val.type === "StringLiteral" && imageRegex.test(val.value)) {
81
+ usedImages.add(val.value);
82
+ }
83
+ },
84
+ });
85
+ }
86
+ console.log(Array.from(usedImages));
87
+ }
88
+
89
+ getAssetInCode();
90
+
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # react-cleaner
package/assets.js ADDED
@@ -0,0 +1,37 @@
1
+ const fg = require('fast-glob');
2
+ const fs = require('fs');
3
+ const parser = require('@babel/parser');
4
+ const traverse = require('@babel/traverse').default;
5
+
6
+ async function getFiles() {
7
+ const assets = [];
8
+ const files = await fg([ "src/**/*.{png,jpg,jpeg,svg,gif,webp}",
9
+ "public/**/*.{png,jpg,jpeg,svg,gif,webp}",]);
10
+ const codeFiles = await fg([ "src/**/*.{js,jsx,ts,tsx}",
11
+ "src/**/*.css",
12
+ "src/**/*.json"]);
13
+
14
+ for (const file of codeFiles) {
15
+ const code = fs.readFileSync(file, 'utf8');
16
+ const ast = parser.parse(code, {
17
+ sourceType: 'module',
18
+ plugins: ['jsx', 'typescript'],
19
+ });
20
+ traverse(ast, {
21
+ ImportDeclaration: ({ node }) => {
22
+ if(typeof node.source.value === 'string' && /\.(png|jpg|jpeg|svg|gif|webp)$/.test(node.source.value)){
23
+ assets.push(node.source.value);
24
+ }
25
+ },
26
+ CallExpression: ({ node }) => {
27
+ if(node.callee.name === 'require' && typeof node.arguments[0].value === 'string' && /\.(png|jpg|jpeg|svg|gif|webp)$/.test(node.arguments[0].value)){
28
+ assets.push(node.arguments[0].value);
29
+ }
30
+ },
31
+ });
32
+ }
33
+ console.log(assets);
34
+ console.log(files);
35
+ }
36
+
37
+ getFiles();
package/bin/cli.js ADDED
@@ -0,0 +1,13 @@
1
+ const {Command} = require('commander');
2
+ const getFiles = require('../command');
3
+
4
+ const program = new Command();
5
+
6
+ program.name('qleaner').description('A tool to clean up your React code').version('1.0.0');
7
+
8
+ program.command('qlean').description('List all the imports in the project').action(async () => {
9
+ const imports = await getFiles();
10
+ console.log(imports);
11
+ });
12
+
13
+ program.parse(process.argv);
package/command.js ADDED
@@ -0,0 +1,55 @@
1
+ const fg = require("fast-glob");
2
+ const fs = require("fs");
3
+ const parser = require("@babel/parser");
4
+ const traverse = require("@babel/traverse").default;
5
+
6
+
7
+ module.exports = async function getFiles() {
8
+ const files = await fg(["app/**/*.{tsx,ts,js,jsx}"]);
9
+ const imports = [];
10
+ for (const file of files) {
11
+ const code = fs.readFileSync(file, "utf8");
12
+ const ast = parser.parse(code, {
13
+ sourceType: "module",
14
+ plugins: [
15
+ "jsx",
16
+ "typescript",
17
+ ],
18
+ });
19
+
20
+ traverse(ast, {
21
+ ImportDeclaration: ({ node }) => {
22
+ imports.push({
23
+ from: node.source.value,
24
+ file: file,
25
+ line: node.loc.start.line,
26
+ column: node.loc.start.column,
27
+
28
+ });
29
+ },
30
+
31
+ });
32
+
33
+ // ExportNamedDeclaration: ({ node }) => {
34
+ // if (node.declaration.declarations && node.declaration.declarations[0].id && node.declaration.declarations[0].id.name) {
35
+ // exports.push(node.declaration.declarations[0].id.name);
36
+ // }
37
+ // },
38
+ // FunctionDeclaration: ({ node }) => {
39
+ // console.log('FunctionDeclaration', node.id);
40
+ // if (node.id && node.id.name) {
41
+ // exports.push(node.id.name);
42
+ // }
43
+ // },
44
+ // });
45
+ }
46
+
47
+ console.log('***************** Files *****************');
48
+ files.forEach((file) => {
49
+ console.log(file);
50
+ })
51
+ console.log('***************** Imports *****************');
52
+ imports.forEach((importStatement) => {
53
+ console.log(`${importStatement.file}:${importStatement.line}:${importStatement.column} ${importStatement.from}`);
54
+ })
55
+ }
package/cssImages.js ADDED
@@ -0,0 +1,33 @@
1
+ const fs = require('fs');
2
+ const fg = require('fast-glob');
3
+
4
+ function extractCssImages(cssContent) {
5
+ const urlRegex = /url\((['"]?)(.*?)\1\)/g;
6
+ const images = new Set();
7
+ let match;
8
+
9
+ while ((match = urlRegex.exec(cssContent)) !== null) {
10
+ const url = match[2];
11
+
12
+ // Only collect image file types
13
+ if (/\.(png|jpg|jpeg|svg|gif|webp)$/i.test(url)) {
14
+ images.add(url);
15
+ }
16
+ }
17
+
18
+ return Array.from(images);
19
+ }
20
+
21
+ async function getCssImages() {
22
+ const cssFiles = await fg([
23
+ "src/**/*.{css,scss}",
24
+ ]);
25
+ for (const file of cssFiles) {
26
+ const css = fs.readFileSync(file, "utf-8");
27
+ const images = extractCssImages(css);
28
+ console.log(images);
29
+ }
30
+ }
31
+
32
+ getCssImages();
33
+
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "qleaner",
3
+ "packageManager": "yarn@4.6.0",
4
+ "version": "1.0.0",
5
+ "main": "command.js",
6
+ "bin": "./bin/cli.js",
7
+ "scripts": {
8
+ "start": "node bin/cli.js"
9
+ },
10
+ "devDependencies": {
11
+ "@types/node": "^20.10.5",
12
+ "typescript": "^5.3.3"
13
+ },
14
+ "dependencies": {
15
+ "@babel/parser": "^7.28.5",
16
+ "@babel/traverse": "^7.28.5",
17
+ "chalk": "^5.6.2",
18
+ "commander": "^14.0.2",
19
+ "fast-glob": "^3.3.3"
20
+ }
21
+ }