This commit is contained in:
Corentin BRINGER 2025-10-02 20:54:32 +01:00 committed by GitHub
commit 2fe17addc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 752 additions and 40 deletions

208
package-lock.json generated
View file

@ -39,6 +39,7 @@
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"jimp": "^0.22.12",
"js-beautify": "^1.15.4",
"js-quantities": "^1.8.0",
"jszip": "^3.10.1",
"lint-staged": "^15.4.3",
@ -75,6 +76,7 @@
"@testing-library/react": "^14.3.1",
"@types/color": "^3.0.6",
"@types/color-rgba": "^2.1.2",
"@types/js-beautify": "^1.14.3",
"@types/node": "^20.12.12",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.3",
@ -1587,7 +1589,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
@ -1604,7 +1605,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
@ -1616,7 +1616,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
@ -2602,6 +2601,12 @@
"node": ">= 8"
}
},
"node_modules/@one-ini/wasm": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
"license": "MIT"
},
"node_modules/@pdf-lib/standard-fonts": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
@ -2624,7 +2629,6 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"optional": true,
"engines": {
"node": ">=14"
@ -3453,6 +3457,13 @@
"integrity": "sha512-qLyqTkp3ZKHsSoX8CNVYcTyTkxlm0aRCUpaUVetgkSlSpiNCdWryOgaYwgbO04tJIfLgBXPcy0tJ3Nl/RagllA==",
"license": "MIT"
},
"node_modules/@types/js-beautify": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/@types/js-beautify/-/js-beautify-1.14.3.tgz",
"integrity": "sha512-FMbQHz+qd9DoGvgLHxeqqVPaNRffpIu5ZjozwV8hf9JAGpIOzuAf4wGbRSo8LNITHqGjmmVjaMggTT5P4v4IHg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/js-quantities": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@types/js-quantities/-/js-quantities-1.6.6.tgz",
@ -3971,6 +3982,15 @@
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
"dev": true
},
"node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/acorn": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz",
@ -4408,8 +4428,7 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64-js": {
"version": "1.5.1",
@ -4465,7 +4484,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
@ -5018,6 +5036,22 @@
"integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==",
"dev": true
},
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"license": "MIT",
"dependencies": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
"node_modules/config-chain/node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"license": "ISC"
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
@ -5602,8 +5636,49 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/editorconfig": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
"integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
"license": "MIT",
"dependencies": {
"@one-ini/wasm": "0.1.1",
"commander": "^10.0.0",
"minimatch": "9.0.1",
"semver": "^7.5.3"
},
"bin": {
"editorconfig": "bin/editorconfig"
},
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/minimatch": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.806",
@ -5614,8 +5689,7 @@
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/encoding": {
"version": "0.1.13",
@ -6511,7 +6585,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
"integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
@ -7826,7 +7899,6 @@
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz",
"integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==",
"dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
@ -7901,6 +7973,71 @@
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
"license": "BSD-3-Clause"
},
"node_modules/js-beautify": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
"integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
"license": "MIT",
"dependencies": {
"config-chain": "^1.1.13",
"editorconfig": "^1.0.4",
"glob": "^10.4.2",
"js-cookie": "^3.0.5",
"nopt": "^7.2.1"
},
"bin": {
"css-beautify": "js/bin/css-beautify.js",
"html-beautify": "js/bin/html-beautify.js",
"js-beautify": "js/bin/js-beautify.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/js-beautify/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-beautify/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/js-quantities": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/js-quantities/-/js-quantities-1.8.0.tgz",
@ -8737,7 +8874,6 @@
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
"integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
}
@ -8910,7 +9046,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
@ -9046,6 +9181,21 @@
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
"dev": true
},
"node_modules/nopt": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"license": "ISC",
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -9391,8 +9541,7 @@
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
"dev": true
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw=="
},
"node_modules/pako": {
"version": "1.0.11",
@ -9526,7 +9675,6 @@
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
@ -10040,6 +10188,12 @@
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="
},
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"license": "ISC"
},
"node_modules/protobufjs": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
@ -10955,7 +11109,6 @@
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
},
@ -11373,7 +11526,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
@ -11391,7 +11543,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -11404,14 +11555,12 @@
"node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/string-width/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
@ -11423,7 +11572,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
@ -11548,7 +11696,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -12678,7 +12825,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
@ -12696,7 +12842,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@ -12712,14 +12857,12 @@
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -12733,7 +12876,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
@ -12745,7 +12887,6 @@
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"engines": {
"node": ">=12"
},
@ -12757,7 +12898,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},

View file

@ -58,6 +58,7 @@
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"jimp": "^0.22.12",
"js-beautify": "^1.15.4",
"js-quantities": "^1.8.0",
"jszip": "^3.10.1",
"lint-staged": "^15.4.3",
@ -94,6 +95,7 @@
"@testing-library/react": "^14.3.1",
"@types/color": "^3.0.6",
"@types/color-rgba": "^2.1.2",
"@types/js-beautify": "^1.14.3",
"@types/node": "^20.12.12",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.3",

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "CSS/JS minimieren",
"description": "Komprimieren Sie Ihren CSS- oder JavaScript-Code, indem Sie überflüssige Leerzeichen, Zeilenumbrüche und Kommentare entfernen.",
"shortDescription": "CSS- und JavaScript-Code minimieren",
"longDescription": "",
"toolInfo": {
"title": "CSS/JS minimieren",
"description": "Dieses Tool minimiert Ihren CSS- oder JavaScript-Code, indem es unnötige Zeichen wie Leerzeichen, Zeilenumbrüche und Kommentare entfernt ohne die Funktionalität zu beeinträchtigen. Ideal zur Optimierung der Webleistung und zur Reduzierung der Dateigröße vor dem Deployment."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Tools zum Arbeiten mit XML-Datenstrukturen Viewer, Beautifier, Validator und vieles mehr",
"title": "XML-Tools"
},
"dev": {
"description": "Unverzichtbare Tools für Entwickler: Code-Formatter, Encoder/Decoder, Vergleichswerkzeuge, UUID-Generatoren und vieles mehr",
"title": "Entwickler-Tools"
}
},
"csv": {

View file

@ -0,0 +1,24 @@
{
"cssJsMinify": {
"title": "Minify CSS/JS",
"description": "Compress your CSS or JavaScript code by removing unnecessary spaces, line breaks, and comments.",
"shortDescription": "Minify CSS and JavaScript code",
"longDescription": "",
"language": "Language",
"toolInfo": {
"title": "Minify CSS/JS",
"description": "This tool minifies your CSS or JavaScript code by removing unnecessary characters like whitespace, line breaks, and comments—without affecting functionality. Ideal for optimizing web performance and reducing file size before deployment."
}
},
"cssJsUnminify": {
"title": "Unminify CSS/JS",
"description": "Beautify or unminify your compressed CSS or JavaScript code for better readability.",
"shortDescription": "Beautify CSS and JavaScript",
"longDescription": "",
"language": "Language",
"toolInfo": {
"title": "Unminify CSS/JS",
"description": "This tool reformats your compressed CSS or JavaScript code by adding appropriate spacing and line breaks. Useful for debugging or inspecting minified code."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Tools for working with XML data structures - viewer, beautifier, validator and much more",
"title": "XML Tools"
},
"dev": {
"description": "Essential utilities for developers: code formatters, encoders/decoders, diff tools, UUID generators, and more",
"title": "Dev Tools"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "Minificar CSS/JS",
"description": "Comprime tu código CSS o JavaScript eliminando espacios, saltos de línea y comentarios innecesarios.",
"shortDescription": "Minificar código CSS y JavaScript",
"longDescription": "",
"toolInfo": {
"title": "Minificar CSS/JS",
"description": "Esta herramienta minifica tu código CSS o JavaScript eliminando caracteres innecesarios como espacios en blanco, saltos de línea y comentarios, sin afectar su funcionalidad. Ideal para optimizar el rendimiento web y reducir el tamaño de los archivos antes de su implementación."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Herramientas para trabajar con estructuras de datos XML: visor, embellecedor, validador y mucho más",
"title": "Herramientas XML"
},
"dev": {
"description": "Herramientas esenciales para desarrolladores: formateadores de código, codificadores/decodificadores, herramientas de comparación, generadores de UUID y mucho más",
"title": "Herramientas de desarrollo"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "Minifier CSS/JS",
"description": "Compressez votre code CSS ou JavaScript en supprimant les espaces, sauts de ligne et commentaires inutiles.",
"shortDescription": "Minifier du code CSS et JavaScript",
"longDescription": "",
"toolInfo": {
"title": "Minifier CSS/JS",
"description": "Cet outil minifie votre code CSS ou JavaScript en supprimant les caractères superflus comme les espaces, les sauts de ligne et les commentaires — sans altérer le fonctionnement du code. Idéal pour optimiser les performances web et réduire la taille des fichiers avant mise en production."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Outils pour travailler avec des structures de données XML - visualiseur, embellisseur, validateur et bien plus encore",
"title": "Outils XML"
},
"dev": {
"description": "Outils essentiels pour les développeurs : formateurs de code, encodeurs/décodeurs, outils de comparaison, générateurs d'UUID et bien plus encore",
"title": "Outils de développement"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "CSS/JS को संक्षिप्त करें",
"description": "अनावश्यक स्पेस, लाइन ब्रेक और टिप्पणियाँ हटाकर अपने CSS या JavaScript कोड को संक्षिप्त करें।",
"shortDescription": "CSS और JavaScript कोड को मिनिफाई करें",
"longDescription": "",
"toolInfo": {
"title": "CSS/JS को संक्षिप्त करें",
"description": "यह टूल आपके CSS या JavaScript कोड से अनावश्यक वर्ण जैसे स्पेस, लाइन ब्रेक और टिप्पणियाँ हटाकर उसे संक्षिप्त करता है, बिना कार्यक्षमता को प्रभावित किए। यह वेब प्रदर्शन को बेहतर बनाने और परिनियोजन से पहले फ़ाइल का आकार कम करने के लिए आदर्श है।"
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "XML डेटा संरचनाओं के साथ काम करने के लिए टूल्स - व्यूअर, ब्यूटिफायर, वैलिडेटर और बहुत कुछ",
"title": "XML टूल्स"
},
"dev": {
"description": "डेवलपर्स के लिए आवश्यक उपकरण: कोड फ़ॉर्मैटर, एन्कोडर/डिकोडर, तुलना उपकरण, UUID जनरेटर और बहुत कुछ",
"title": "डेव टूल्स"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "CSS/JSの最小化",
"description": "不要なスペース、改行、コメントを削除してCSSまたはJavaScriptコードを圧縮します。",
"shortDescription": "CSSおよびJavaScriptコードを最小化",
"longDescription": "",
"toolInfo": {
"title": "CSS/JSの最小化",
"description": "このツールは、不要な文字空白、改行、コメントなどを削除することで、CSSまたはJavaScriptコードを最小化します。機能を損なうことなく、Webパフォーマンスを最適化し、デプロイ前のファイルサイズを削減するのに最適です。"
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "XML データ構造を操作するためのツール - ビューア、ビューティファイア、バリデータなど",
"title": "XMLツール"
},
"dev": {
"description": "開発者のための必須ツール:コードフォーマッター、エンコーダー/デコーダー、差分ツール、UUIDジェネレーターなど",
"title": "開発ツール"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "CSS/JS verkleinen",
"description": "Comprimeer je CSS- of JavaScript-code door overbodige spaties, regeleinden en opmerkingen te verwijderen.",
"shortDescription": "CSS- en JavaScript-code verkleinen",
"longDescription": "",
"toolInfo": {
"title": "CSS/JS verkleinen",
"description": "Deze tool verkleint je CSS- of JavaScript-code door onnodige tekens zoals spaties, regeleinden en opmerkingen te verwijderen — zonder de functionaliteit aan te tasten. Ideaal om de webprestaties te optimaliseren en de bestandsgrootte vóór deployment te verkleinen."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Hulpmiddelen voor het werken met XML-datastructuren - viewer, beautifier, validator en nog veel meer",
"title": "XML-hulpmiddelen"
},
"dev": {
"description": "Essentiële hulpmiddelen voor ontwikkelaars: codeformatters, encoders/decoders, vergelijkingstools, UUID-generators en meer",
"title": "Ontwikkelaarstools"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "Minificar CSS/JS",
"description": "Comprime seu código CSS ou JavaScript removendo espaços, quebras de linha e comentários desnecessários.",
"shortDescription": "Minificar código CSS e JavaScript",
"longDescription": "",
"toolInfo": {
"title": "Minificar CSS/JS",
"description": "Esta ferramenta minifica seu código CSS ou JavaScript removendo caracteres desnecessários, como espaços em branco, quebras de linha e comentários — sem afetar a funcionalidade. Ideal para otimizar o desempenho da web e reduzir o tamanho dos arquivos antes da implantação."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Ferramentas para trabalhar com estruturas de dados XML - visualizador, embelezador, validador e muito mais",
"title": "Ferramentas XML"
},
"dev": {
"description": "Ferramentas essenciais para desenvolvedores: formatadores de código, codificadores/decodificadores, ferramentas de comparação, geradores de UUID e muito mais",
"title": "Ferramentas de desenvolvimento"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "Минификация CSS/JS",
"description": "Сожмите ваш CSS или JavaScript код, удалив ненужные пробелы, разрывы строк и комментарии.",
"shortDescription": "Минифицировать CSS и JavaScript код",
"longDescription": "",
"toolInfo": {
"title": "Минификация CSS/JS",
"description": "Этот инструмент минимизирует ваш CSS или JavaScript код, удаляя лишние символы, такие как пробелы, переносы строк и комментарии — без потери функциональности. Идеально подходит для оптимизации производительности сайта и уменьшения размера файлов перед развертыванием."
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "Инструменты для работы с XML-структурами данных — просмотрщик, улучшитель, валидатор и многое другое",
"title": "XML-инструменты"
},
"dev": {
"description": "Необходимые инструменты для разработчиков: форматеры кода, энкодеры/декодеры, инструменты сравнения, генераторы UUID и многое другое",
"title": "Инструменты разработчика"
}
},
"csv": {

View file

@ -0,0 +1,12 @@
{
"cssJsMinify": {
"title": "压缩 CSS/JS",
"description": "通过删除不必要的空格、换行和注释来压缩您的 CSS 或 JavaScript 代码。",
"shortDescription": "压缩 CSS 和 JavaScript 代码",
"longDescription": "",
"toolInfo": {
"title": "压缩 CSS/JS",
"description": "该工具通过删除空格、换行符和注释等多余字符来压缩您的 CSS 或 JavaScript 代码,同时不影响功能。非常适合在部署前优化网页性能并减少文件大小。"
}
}
}

View file

@ -71,6 +71,10 @@
"xml": {
"description": "处理 XML 数据结构的工具 - 查看器、美化器、验证器等等",
"title": "XML 工具"
},
"dev": {
"description": "开发者必备工具:代码格式化器、编码器/解码器、差异比较工具、UUID 生成器等",
"title": "开发工具"
}
},
"csv": {

View file

@ -150,7 +150,8 @@ const validNamespaces = [
'audio',
'xml',
'translation',
'image'
'image',
'dev'
];
const isValidI18nNamespace = (value) => {
return validNamespaces.includes(value);

View file

@ -55,7 +55,16 @@ const translationFiles = [
namespace: 'time',
file: '../src/pages/tools/time/i18n/en.json'
},
{ lang: 'en', namespace: 'xml', file: '../src/pages/tools/xml/i18n/en.json' },
{
lang: 'en',
namespace: 'xml',
file: '../src/pages/tools/xml/i18n/en.json'
},
{
lang: 'en',
namespace: 'dev',
file: '../src/pages/tools/dev/i18n/en.json'
},
// Hindi translations
{ lang: 'hi', namespace: 'translation', file: '../src/i18n/hi.json' },

View file

@ -12,6 +12,7 @@ import pdf from '../../public/locales/en/pdf.json';
import audio from '../../public/locales/en/audio.json';
import xml from '../../public/locales/en/xml.json';
import image from '../../public/locales/en/image.json';
import dev from '../../public/locales/en/dev.json';
declare module 'i18next' {
interface CustomTypeOptions {
@ -28,6 +29,7 @@ declare module 'i18next' {
audio: typeof audio;
xml: typeof xml;
image: typeof image;
dev: typeof dev;
};
}
}

View file

@ -15,7 +15,8 @@ export const validNamespaces = [
'audio',
'xml',
'translation',
'image'
'image',
'dev'
] as const satisfies readonly Namespace[];
export type I18nNamespaces = (typeof validNamespaces)[number];

View file

@ -0,0 +1,84 @@
import { describe, it, expect } from 'vitest';
import { minifyCss, minifyJs } from './service';
describe('minifyCss', () => {
it('should remove comments and whitespace', () => {
const input = `
/* Comment */
body {
margin: 0;
padding: 0;
}
`;
const result = minifyCss(input);
expect(result).toBe('body{margin:0;padding:0}');
});
it('should handle nested rules', () => {
const input = `
@media screen and (max-width: 600px) {
body {
background-color: red;
}
}
`;
const result = minifyCss(input);
expect(result).toBe(
'@media screen and (max-width:600px){body{background-color:red}}'
);
});
it('should remove semicolon before closing brace', () => {
const input = `h1 { color: blue; }`;
const result = minifyCss(input);
expect(result).toBe('h1{color:blue}');
});
it('should return empty string for empty input', () => {
expect(minifyCss('')).toBe('');
});
});
describe('minifyJs', () => {
it('should remove line and block comments', () => {
const input = `
// This is a comment
/* Another comment */
function test() {
console.log("Hello");
}
`;
const result = minifyJs(input);
expect(result).toBe('function test(){console.log("Hello")}');
});
it('should remove unnecessary spaces and semicolons', () => {
const input = `
const x = 1 ;
const y = 2 ;
console.log( x + y );
`;
const result = minifyJs(input);
expect(result).toBe('const x=1;const y=2;console.log(x+y);');
});
it('should handle multi-line function with logic', () => {
const input = `
function sum(a, b) {
return a + b;
}
`;
const result = minifyJs(input);
expect(result).toBe('function sum(a,b){return a+b}');
});
it('should return empty string for empty input', () => {
expect(minifyJs('')).toBe('');
});
it('should not crash on malformed JS', () => {
const input = `function {`;
const result = minifyJs(input);
expect(typeof result).toBe('string'); // still returns a string
});
});

View file

@ -0,0 +1,87 @@
import { Box, FormControl, InputLabel, MenuItem, Select } from '@mui/material';
import { useState } from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { useTranslation } from 'react-i18next';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import { CardExampleType } from '@components/examples/ToolExamples';
import { minifyCss, minifyJs } from './service';
const initialValues = {
language: 'css' as 'css' | 'js'
};
type InitialValuesType = typeof initialValues;
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Minify CSS Example',
description: 'This example shows how a simple CSS block is minified.',
sampleText: `body {\n margin: 0;\n padding: 0;\n background-color: white;\n}`,
sampleResult: `body{margin:0;padding:0;background-color:white}`,
sampleOptions: { language: 'css' }
},
{
title: 'Minify JS Example',
description: 'This example demonstrates JavaScript minification.',
sampleText: `function hello(name) {\n console.log("Hello, " + name);\n}`,
sampleResult: `function hello(name){console.log("Hello,"+name)}`,
sampleOptions: { language: 'js' }
}
];
export default function CssJsMinify({ title }: ToolComponentProps) {
const { t } = useTranslation('dev');
const [input, setInput] = useState('');
const [result, setResult] = useState('');
const compute = (values: InitialValuesType, input: string) => {
const minified =
values.language === 'css' ? minifyCss(input) : minifyJs(input);
setResult(minified);
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: t('cssJsMinify.language'),
component: (
<Box mt={1}>
<FormControl fullWidth>
<InputLabel>{t('cssJsMinify.language')}</InputLabel>
<Select
value={values.language}
onChange={(e) =>
updateField('language', e.target.value as 'css' | 'js')
}
>
<MenuItem value="css">CSS</MenuItem>
<MenuItem value="js">JavaScript</MenuItem>
</Select>
</FormControl>
</Box>
)
}
];
return (
<ToolContent
title={title}
input={input}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={<ToolTextResult value={result} />}
initialValues={initialValues}
exampleCards={exampleCards}
getGroups={getGroups}
setInput={setInput}
compute={compute}
toolInfo={{
title: t('cssJsMinify.toolInfo.title'),
description: t('cssJsMinify.toolInfo.description')
}}
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('dev', {
i18n: {
name: 'dev:cssJsMinify.title',
description: 'dev:cssJsMinify.description',
shortDescription: 'dev:cssJsMinify.shortDescription',
longDescription: 'dev:cssJsMinify.longDescription'
},
path: 'css-js-minify',
icon: 'material-symbols:code',
keywords: ['css', 'js', 'minify'],
component: lazy(() => import('./index'))
});

View file

@ -0,0 +1,26 @@
export function minifyCss(input: string): string {
try {
return input
.replace(/\/\*[\s\S]*?\*\//g, '') // remove comments
.replace(/\s*([{}:;,])\s*/g, '$1') // remove spaces around tokens
.replace(/\s+/g, ' ') // collapse whitespace
.replace(/;}/g, '}') // remove unnecessary semicolons
.trim();
} catch {
return '/* CSS minification error */';
}
}
export function minifyJs(input: string): string {
try {
return input
.replace(/\/\/[^\n]*/g, '') // remove line comments
.replace(/\/\*[\s\S]*?\*\//g, '') // remove block comments
.replace(/\s*([=+\-*/{}();,:<>|&!])\s*/g, '$1') // remove spaces around operators
.replace(/\s+/g, ' ') // collapse spaces
.replace(/;\s*}/g, '}') // remove semicolon before }
.trim();
} catch {
return '// JavaScript minification error';
}
}

View file

@ -0,0 +1,42 @@
import { describe, it, expect } from 'vitest';
import { unminifyCss, unminifyJs } from './service';
describe('unminifyCss', () => {
it('should format basic CSS block', () => {
const input = `body{margin:0;padding:0}`;
const result = unminifyCss(input);
expect(result).toContain('body {');
expect(result).toContain('margin: 0');
expect(result).toContain('padding: 0');
});
it('should handle nested media queries', () => {
const input = `@media screen and (max-width:600px){body{color:red}}`;
const result = unminifyCss(input);
expect(result).toContain('@media screen and (max-width:600px) {');
expect(result).toContain('color: red');
});
it('should return empty string on empty input', () => {
expect(unminifyCss('')).toBe('');
});
});
describe('unminifyJs', () => {
it('should format function block', () => {
const input = `function test(){console.log("x")}`;
const result = unminifyJs(input);
expect(result).toContain('function test() {');
expect(result).toContain('console.log("x")');
});
it('should insert newlines at semicolons and braces', () => {
const input = `const x=1;const y=2;`;
const result = unminifyJs(input);
expect(result).toMatch(/const x = 1;\nconst y = 2;/);
});
it('should return empty string on empty input', () => {
expect(unminifyJs('')).toBe('');
});
});

View file

@ -0,0 +1,88 @@
import { Box, FormControl, InputLabel, MenuItem, Select } from '@mui/material';
import { useState } from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { useTranslation } from 'react-i18next';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import { CardExampleType } from '@components/examples/ToolExamples';
import { unminifyCss, unminifyJs } from './service';
const initialValues = {
language: 'css' as 'css' | 'js'
};
type InitialValuesType = typeof initialValues;
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Unminify CSS Example',
description:
'This example shows how a compressed CSS block is reformatted.',
sampleText: `body{margin:0;padding:0}`,
sampleResult: `body {\n margin:0;\n padding:0;\n}`,
sampleOptions: { language: 'css' }
},
{
title: 'Unminify JS Example',
description: 'This example demonstrates JavaScript beautification.',
sampleText: `function test(){console.log("Hello")}`,
sampleResult: `function test() {\nconsole.log("Hello")\n}`,
sampleOptions: { language: 'js' }
}
];
export default function CssJsUnminify({ title }: ToolComponentProps) {
const { t } = useTranslation('dev');
const [input, setInput] = useState('');
const [result, setResult] = useState('');
const compute = (values: InitialValuesType, input: string) => {
const output =
values.language === 'css' ? unminifyCss(input) : unminifyJs(input);
setResult(output);
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: t('cssJsUnminify.language'),
component: (
<Box mt={1}>
<FormControl fullWidth>
<InputLabel>{t('cssJsUnminify.language')}</InputLabel>
<Select
value={values.language}
onChange={(e) =>
updateField('language', e.target.value as 'css' | 'js')
}
>
<MenuItem value="css">CSS</MenuItem>
<MenuItem value="js">JavaScript</MenuItem>
</Select>
</FormControl>
</Box>
)
}
];
return (
<ToolContent
title={title}
input={input}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={<ToolTextResult value={result} />}
initialValues={initialValues}
exampleCards={exampleCards}
getGroups={getGroups}
setInput={setInput}
compute={compute}
toolInfo={{
title: t('cssJsUnminify.toolInfo.title'),
description: t('cssJsUnminify.toolInfo.description')
}}
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('dev', {
i18n: {
name: 'dev:cssJsUnminify.title',
description: 'dev:cssJsUnminify.description',
shortDescription: 'dev:cssJsUnminify.shortDescription',
longDescription: 'dev:cssJsUnminify.longDescription'
},
path: 'css-js-unminify',
icon: 'material-symbols:code',
keywords: ['css', 'js', 'unminify'],
component: lazy(() => import('./index'))
});

View file

@ -0,0 +1,14 @@
import { js as beautifyJs, css as beautifyCss } from 'js-beautify';
export function unminifyJs(input: string): string {
return beautifyJs(input, {
indent_size: 2,
space_in_empty_paren: true
});
}
export function unminifyCss(input: string): string {
return beautifyCss(input, {
indent_size: 2
});
}

View file

@ -0,0 +1,4 @@
import { tool as cssJsMinify } from './css-js-minify/meta';
import { tool as cssJsUnminify } from './css-js-unminify/meta';
export const devTools = [cssJsMinify, cssJsUnminify];

View file

@ -33,7 +33,8 @@ export type ToolCategory =
| 'video'
| 'pdf'
| 'audio'
| 'xml';
| 'xml'
| 'dev';
export interface DefinedTool {
type: ToolCategory;

View file

@ -13,6 +13,7 @@ import { timeTools } from '../pages/tools/time';
import { IconifyIcon } from '@iconify/react';
import { pdfTools } from '../pages/tools/pdf';
import { xmlTools } from '../pages/tools/xml';
import { devTools } from '../pages/tools/dev';
import { TFunction } from 'i18next';
import { FullI18nKey, I18nNamespaces } from '../i18n';
@ -30,7 +31,8 @@ const toolCategoriesOrder: ToolCategory[] = [
'png',
'time',
'xml',
'gif'
'gif',
'dev'
];
export const tools: DefinedTool[] = [
...imageTools,
@ -43,7 +45,8 @@ export const tools: DefinedTool[] = [
...numberTools,
...timeTools,
...audioTools,
...xmlTools
...xmlTools,
...devTools
];
const categoriesConfig: {
type: ToolCategory;
@ -134,6 +137,12 @@ const categoriesConfig: {
icon: 'mdi-light:xml',
value: 'translation:categories.xml.description',
title: 'translation:categories.xml.title'
},
{
type: 'dev',
icon: 'mdi:code-block-braces',
value: 'translation:categories.dev.description',
title: 'translation:categories.dev.title'
}
];
const CATEGORIES_USER_TYPES_MAPPINGS: Partial<Record<ToolCategory, UserType>> =