@adamlui/minify.js 1.4.7 → 1.4.9
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 +13 -11
- package/dist/cli.min.js +17 -0
- package/dist/minify.min.js +2 -0
- package/package.json +17 -7
- package/minify.js +0 -282
package/README.md
CHANGED
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
|
|
22
22
|
<a href="https://www.npmjs.com/package/@adamlui/minify.js"><img height=31 src="https://img.shields.io/npm/dt/%40adamlui%2Fminify.js?logo=npm&color=af68ff&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
23
23
|
<a href="#%EF%B8%8F-mit-license"><img height=31 src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
24
|
-
<a href="https://github.com/adamlui/js-utils/releases/tag/minify.js-1.4.
|
|
24
|
+
<a href="https://github.com/adamlui/js-utils/releases/tag/minify.js-1.4.9"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.4.9-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
25
25
|
<a href="https://www.npmjs.com/package/@adamlui/minify.js?activeTab=code"><img height=31 src="https://img.shields.io/npm/unpacked-size/%40adamlui%2Fminify.js?style=for-the-badge&logo=ebox&logoColor=white&labelColor=464646&color=blue"></a>
|
|
26
|
-
<a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils:minify.js/minify.js"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%3Aminify.js%2Fminify.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
|
|
26
|
+
<a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils:minify.js/src/minify.js"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%3Aminify.js%2Fsrc%2Fminify.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
|
|
27
27
|
|
|
28
28
|
<img src="https://github.com/adamlui/js-utils/blob/main/minify.js/media/images/minify.js-docs-demo.png">
|
|
29
29
|
|
|
@@ -145,7 +145,7 @@ Info commands:
|
|
|
145
145
|
|
|
146
146
|
You can also import **minify.js** into your app to use its API methods, both as an ECMAScript module or a CommonJS module.
|
|
147
147
|
|
|
148
|
-
#### ESM
|
|
148
|
+
#### ESM*:
|
|
149
149
|
|
|
150
150
|
```js
|
|
151
151
|
import * as minifyJS from '@adamlui/minify.js';
|
|
@@ -157,6 +157,8 @@ import * as minifyJS from '@adamlui/minify.js';
|
|
|
157
157
|
const minifyJS = require('@adamlui/minify.js');
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
###### _*Node.js version 14 or higher required_
|
|
161
|
+
|
|
160
162
|
#
|
|
161
163
|
|
|
162
164
|
### `minify(input[, options])`
|
|
@@ -170,7 +172,7 @@ const srcCode = 'function add(first, second) { return first + second; }',
|
|
|
170
172
|
minifyResult = minifyJS.minify(srcCode);
|
|
171
173
|
|
|
172
174
|
console.log(minifyResult.error); // outputs runtime error, or `undefined` if no error
|
|
173
|
-
console.log(minifyResult.code); // outputs minified JS: function add(n,d){return n+d}
|
|
175
|
+
console.log(minifyResult.code); // outputs minified JS: 'function add(n,d){return n+d}'
|
|
174
176
|
```
|
|
175
177
|
|
|
176
178
|
If a **file path** is passed, the file's code is loaded then minified, returning an object like above.
|
|
@@ -230,12 +232,12 @@ findJS() » Check returned array.
|
|
|
230
232
|
|
|
231
233
|
Available parameters (and their default settings) are:
|
|
232
234
|
|
|
233
|
-
Name | Desciption
|
|
234
|
-
|
|
235
|
-
`recursive` | Recursively search for nested files
|
|
236
|
-
`verbose` | Show logging in console/terminal.
|
|
237
|
-
`dotFolders` | Include dotfolders in file search.
|
|
238
|
-
`dotFiles` | Include dotfiles in file search.
|
|
235
|
+
Name | Desciption | Default value
|
|
236
|
+
-------------|-----------------------------------------------------------|---------------
|
|
237
|
+
`recursive` | Recursively search for nested files in searchDir passed. | `true`
|
|
238
|
+
`verbose` | Show logging in console/terminal. | `true`
|
|
239
|
+
`dotFolders` | Include dotfolders in file search. | `false`
|
|
240
|
+
`dotFiles` | Include dotfiles in file search. | `false`
|
|
239
241
|
|
|
240
242
|
<br>
|
|
241
243
|
|
|
@@ -255,6 +257,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
255
257
|
|
|
256
258
|
<img height=6px width="100%" src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/aqua-separator.png">
|
|
257
259
|
|
|
258
|
-
<a href="https://github.com/adamlui/js-utils">**
|
|
260
|
+
<a href="https://github.com/adamlui/js-utils">**JavaScript utilities**</a> /
|
|
259
261
|
<a href="https://github.com/adamlui/js-utils/discussions">Discuss</a> /
|
|
260
262
|
<a href="#-minifyjs">Back to top ↑</a>
|
package/dist/cli.min.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const o=require("fs"),s=require("path"),n=require("./minify"),r="[0m",t="[1;91m",l="[1;33m",e="[1;92m",c={},a={dryRun:/^--?(?:n|dry-?run)$/,includeDotFolders:/^--?(?:dd?|(?:include-?)?dot-?(?:folder|dir(?:ector(?:y|ie))?)s?=?(?:true|1)?)$/,includeDotFiles:/^--?(?:df|D|(?:include-?)?dot-?files?=?(?:true|1)?)$/,noRecursion:/^--?(?:R|(?:disable|no)-?recursi(?:on|ve)|recursi(?:on|ve)=(?:false|0))$/,noMangle:/^--?(?:M|(?:disable|no)-?mangle|mangle=(?:false|0))$/,quietMode:/^--?q(?:uiet)?(?:-?mode)?$/,help:/^--?h(?:elp)?$/,version:/^--?ve?r?s?i?o?n?$/};if(process.argv.forEach(i=>{var e;i.startsWith("-")&&((e=Object.keys(a).find(e=>a[e].test(i)))?c[e]=!0:(console.error(`
|
|
3
|
+
${t}ERROR: Arg [${i}] not recognized.`+r),console.info(`
|
|
4
|
+
${l}Valid arguments are below.`+r),d(["configOptions","infoCmds"]),process.exit(1)))}),process.argv.some(e=>a.help.test(e)))d();else if(process.argv.some(e=>a.version.test(e)))console.info("v"+require("./package.json").version);else{const[f="",m=""]=process.argv.slice(2).filter(e=>!e.startsWith("-")).map(e=>e.replace(/^\/*/,"")),u=s.resolve(process.cwd(),f),h=(f&&!o.existsSync(u)&&(console.error(`
|
|
5
|
+
${t}Error: First argument can only be an existing file or directory.`+`
|
|
6
|
+
${u} does not exist.`+r+`
|
|
7
|
+
|
|
8
|
+
${e}Example valid command:
|
|
9
|
+
» minify-js . output.min.js`+r+`
|
|
10
|
+
|
|
11
|
+
${l}For all command options:
|
|
12
|
+
» minify-js --help`+r),process.exit(1)),f.endsWith(".js")?[u]:n.findJS(u,{recursive:!c.noRecursion,verbose:!c.quietMode}));if(c.dryRun)0<h.length?(console.info(`
|
|
13
|
+
${l}JS files to be minified:`+r),h.forEach(e=>console.info(e))):console.info(l+`
|
|
14
|
+
No JS files will be minified.`+r);else{const p=[],g=h.map(e=>{var i=n.minify(e,{verbose:!c.quietMode,mangle:!c.noMangle});return i.error&&p.push(e),i}).filter(e=>!e.error);g?.forEach(({code:e,srcPath:i})=>{var n=s.join(s.dirname(i),(/so?u?rce?$/.test(s.dirname(i))?"../":"")+(m.endsWith(".js")?s.dirname(m):m||"min")),i=(m.endsWith(".js")&&f.endsWith(".js")?s.basename(m).replace(/(\.min)?\.js$/,""):s.basename(i,".js"))+".min.js",i=s.join(n,i);o.existsSync(n)||o.mkdirSync(n,{recursive:!0}),o.writeFileSync(i,e,"utf8")}),0<g?.length?(i(`
|
|
15
|
+
${e}Minification complete!`+r),i(`${g.length} file${1<g.length?"s":""} minified.`)):i(l+"No unminified JavaScript files processed."+r),0<p.length&&(i(`
|
|
16
|
+
`+t+p.length+" file"+(1<p.length?"s":"")+" failed to minify:"+r),p.forEach(e=>i(e)))}}function d(e=["cmdFormat","pathArgs","configOptions","infoCmds"]){const i={cmdFormat:[`
|
|
17
|
+
${l}minify-js [inputPath] [outputPath] [options]`+r],pathArgs:["\nPath arguments:"," [inputPath] Path to JS file or directory containing JS files to be minified, relative to the current working directory."," [outputPath] Path to file or directory where minified files will be stored, relative to original file location (if not provided, min/ is used)."],configOptions:["\nConfig options:"," -n, --dry-run Don't actually minify the file(s), just show if they will be processed."," -d, --include-dotfolders Include dotfolders in file search."," -D, --include-dotfiles Include dotfiles in file search."," -R, --no-recursion Disable recursive file searching."," -M, --no-mangle Disable mangling names."," -q, --quiet Suppress all logging except errors."],infoCmds:["\nInfo commands:"," -h, --help Display help screen."," -v, --version Show version number."]};e.forEach(e=>{i[e]?.forEach(e=>{{const o=process.stdout.columns||80,s=[],i=e.match(/\S+|\s+/g);let n="";i.forEach(e=>{var i=o-(0===s.length?0:29);n.length+e.length>i&&(s.push(0===s.length?n:n.trimStart()),n=""),n+=e}),s.push(0===s.length?n:n.trimStart()),s.forEach((e,i)=>console.info(0===i?e:" ".repeat(29)+e))}})})}function i(e){c.quietMode||console.info(e)}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const a=require("fs"),d=require("path"),f=require("uglify-js");function y(o,i={}){var e={recursive:!0,verbose:!0,dotFolders:!1,dotFiles:!1};if("string"!=typeof o)return console.error("findJS() » ERROR: 1st arg <searchDir> must be a string.");var r=d.resolve(process.cwd(),o);if(a.existsSync(r)){const s=JSON.stringify(e,null,2).replace(/"([^"]+)":/g,"$1:").replace(/"/g,"'").replace(/\n\s*/g," "),t=Object.keys(e).join(", ");var n=()=>{console.info(`findJS() » Valid options: [ ${t} ]`),console.info("findJS() » If omitted, default settings are: "+s)};if("object"==typeof i){for(const f in i){if(!Object.prototype.hasOwnProperty.call(e,f)&&"isRecursing"!==f)return console.error(`findJS() » ERROR: \`${f}\` is an invalid option.`),void n();if("boolean"!=typeof i[f])return console.error(`findJS() » ERROR: [${f}] option can only be \`true\` or \`false\`.`)}i={...e,...i};const l=a.readdirSync(o),c=[];return i.verbose&&!i.isRecursing&&console.info("findJS() » Searching for unminified JS files..."),l.forEach(e=>{var r=d.resolve(o,e);a.statSync(r).isDirectory()&&"node_modules"!=e&&(i.dotFolders||!e.startsWith("."))&&i.recursive?c.push(...y(r,{...i,isRecursing:!0})):!/\.js(?<!\.min\.js)$/.test(e)||!i.dotFiles&&e.startsWith(".")||c.push(r)}),!i.isRecursing&&i.verbose&&(console.info("findJS() » Search complete! "+(0===c.length?"No":c.length)+` file${1<c.length?"s":""} found.`),"minify"===y.caller.name||require.main.filename.endsWith("cli.js")||console.info("findJS() » Check returned array.")),i.isRecursing||0<c.length?c:[]}console.error("findJS() » ERROR: 2nd arg [options] can only be an object of key/values."),console.info("findJS() » Example valid call: findJS('assets/js', { verbose: false, dotFolders: true })"),n()}else console.error("findJS() » ERROR: 1st arg <searchDir> must be an existing directory."),console.error(`findJS() » ${r} does not exist.`)}function e(e,o={}){var r={recursive:!0,verbose:!0,dotFolders:!1,dotFiles:!1,mangle:!0};if("string"!=typeof e)return console.error("minify() » ERROR: 1st arg <input> must be a string.");const i=JSON.stringify(r,null,2).replace(/"([^"]+)":/g,"$1:").replace(/"/g,"'").replace(/\n\s*/g," "),n=Object.keys(r).join(", ");var s,t=()=>{console.info(`minify() » Valid options: [ ${n} ]`),console.info("minify() » If omitted, default settings are: "+i)};if("object"==typeof o){for(const c in o){if(!Object.prototype.hasOwnProperty.call(r,c))return console.error(`minify() » ERROR: \`${c}\` is an invalid option.`),void t();if("boolean"!=typeof o[c])return console.error(`minify() » ERROR: [${c}] option can only be \`true\` or \`false\`.`)}const l={mangle:!!(o={...r,...o}).mangle&&{toplevel:!0}};return a.existsSync(e)?e.endsWith(".js")?(o.verbose&&console.info(`minify() » Minifying ${e}...`),(s=f.minify(a.readFileSync(e,"utf8"),l)).error&&console.error("minify() » ERROR: "+s.error.message),{code:s.code,srcPath:d.resolve(process.cwd(),e),error:s.error}):y(e,{recursive:o.recursive,verbose:o.verbose,dotFolders:o.dotFolders,dotFiles:o.dotFiles})?.map(e=>{o.verbose&&console.info(`minify() » Minifying ${e}...`);var r=a.readFileSync(e,"utf8"),r=f.minify(r,l);return r.error&&console.error("minify() » ERROR: "+r.error.message),{code:r.code,srcPath:e,error:r.error}}).filter(e=>!e.error):(o.verbose&&console.info("minify() » Minifying passed source code..."),(s=f.minify(e,l)).error&&console.error("minify() » ERROR: "+s.error.message),{code:s.code,srcPath:void 0,error:s.error})}console.error("minify() » ERROR: 2nd arg [options] can only be an object of key/values."),console.info("minify() » Example valid call: minify('assets/js', { recursive: false, mangle: false })"),t()}module.exports={minify:e,findJS:y};
|
package/package.json
CHANGED
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adamlui/minify.js",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.9",
|
|
4
4
|
"description": "Recursively minify all JavaScript files",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Adam Lui",
|
|
7
7
|
"email": "adam@kudoai.com",
|
|
8
8
|
"url": "https://github.com/adamlui"
|
|
9
9
|
},
|
|
10
|
-
"homepage": "https://
|
|
10
|
+
"homepage": "https://js-utils.com/minify.js",
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"main": "minify.js",
|
|
12
|
+
"main": "dist/minify.min.js",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"docs/",
|
|
16
|
+
"!docs/*/"
|
|
17
|
+
],
|
|
13
18
|
"bin": {
|
|
14
|
-
"minifyjs": "
|
|
15
|
-
"minify-js": "
|
|
19
|
+
"minifyjs": "dist/cli.min.js",
|
|
20
|
+
"minify-js": "dist/cli.min.js"
|
|
21
|
+
},
|
|
22
|
+
"directories": {
|
|
23
|
+
"lib": ".",
|
|
24
|
+
"doc": "./docs",
|
|
25
|
+
"test": "./utils/test"
|
|
16
26
|
},
|
|
17
27
|
"scripts": {
|
|
18
28
|
"test": "bash utils/test/minify-cli.test.sh",
|
|
29
|
+
"build": "node src/cli src dist",
|
|
19
30
|
"bump:patch": "bash utils/bump.sh patch",
|
|
20
31
|
"bump:minor": "bash utils/bump.sh minor",
|
|
21
32
|
"bump:major": "bash utils/bump.sh major",
|
|
22
|
-
"prepublish": "npm test",
|
|
23
33
|
"publish:patch": "bash utils/bump.sh patch --publish",
|
|
24
34
|
"publish:minor": "bash utils/bump.sh minor --publish",
|
|
25
35
|
"publish:major": "bash utils/bump.sh major --publish"
|
|
@@ -39,7 +49,7 @@
|
|
|
39
49
|
"utils"
|
|
40
50
|
],
|
|
41
51
|
"bugs": {
|
|
42
|
-
"url": "https://
|
|
52
|
+
"url": "https://js-utils.com/issues"
|
|
43
53
|
},
|
|
44
54
|
"dependencies": {
|
|
45
55
|
"uglify-js": "^3.17.4"
|
package/minify.js
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Import LIBS
|
|
4
|
-
const fs = require('fs'),
|
|
5
|
-
path = require('path'),
|
|
6
|
-
uglifyJS = require('uglify-js');
|
|
7
|
-
|
|
8
|
-
// Define MAIN functions
|
|
9
|
-
|
|
10
|
-
function findJS(searchDir, options = {}) {
|
|
11
|
-
|
|
12
|
-
// Init options
|
|
13
|
-
const defaultOptions = { recursive: true, verbose: true, dotFolders: false, dotFiles: false };
|
|
14
|
-
options = { ...defaultOptions, ...options };
|
|
15
|
-
|
|
16
|
-
// Validate searchDir
|
|
17
|
-
if (typeof searchDir !== 'string') return console.error(
|
|
18
|
-
'findJS() » ERROR: 1st arg <searchDir> must be a string.');
|
|
19
|
-
else { // verify searchDir path existence
|
|
20
|
-
const searchPath = path.resolve(process.cwd(), searchDir);
|
|
21
|
-
if (!fs.existsSync(searchPath)) return console.error(
|
|
22
|
-
'findJS() » ERROR: 1st arg <searchDir> must be an existing directory.\n'
|
|
23
|
-
+ `findJS() » ${ searchPath } does not exist.`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Validate options
|
|
27
|
-
for (const key of Object.keys(options)) {
|
|
28
|
-
if (!Object.prototype.hasOwnProperty.call(defaultOptions, key))
|
|
29
|
-
if (key !== 'isRecursing') return console.error(
|
|
30
|
-
`findJS() » ERROR: \`${ key }\` is an invalid option.\n`
|
|
31
|
-
+ `findJS() » Valid options: [ ${ Object.keys(defaultOptions).join(', ') } ]`);
|
|
32
|
-
else if (typeof options[key] !== 'boolean') return console.error(
|
|
33
|
-
`findJS() » ERROR: \`${ key }\` option can only be set to \`true\` or \`false\`.`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Search for unminified JS
|
|
37
|
-
const dirFiles = fs.readdirSync(searchDir), jsFiles = [];
|
|
38
|
-
if (options.verbose && !options.isRecursing) console.info(
|
|
39
|
-
'\nfindJS() » Searching for unminified JS files...');
|
|
40
|
-
dirFiles.forEach(file => {
|
|
41
|
-
const filePath = path.resolve(searchDir, file);
|
|
42
|
-
if (fs.statSync(filePath).isDirectory() && file != 'node_modules'
|
|
43
|
-
&& (options.dotFolders || !file.startsWith('.')) && options.recursive)
|
|
44
|
-
jsFiles.push( // recursively find unminified JS in eligible dir
|
|
45
|
-
...findJS(filePath, { ...options, isRecursing: true }));
|
|
46
|
-
else if (/\.js(?<!\.min\.js)$/.test(file)
|
|
47
|
-
&& (options.dotFiles || !file.startsWith('.')))
|
|
48
|
-
jsFiles.push(filePath); // store eligible unminified JS file for minification
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Log/return final result
|
|
52
|
-
if (!options.isRecursing && options.verbose) console.info(
|
|
53
|
-
'findJS() » Search complete! ' + ( jsFiles.length === 0 ? 'No' : jsFiles.length )
|
|
54
|
-
+ ` file${ jsFiles.length > 1 ? 's' : '' } found.`
|
|
55
|
-
+ ( findJS.caller.name !== 'minify' && require.main !== module ?
|
|
56
|
-
'\nfindJS() » Check returned array.' : '' ));
|
|
57
|
-
return options.isRecursing || jsFiles.length > 0 ? jsFiles : [];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function minify(input, options = {}) {
|
|
61
|
-
|
|
62
|
-
// Init options
|
|
63
|
-
const defaultOptions = {
|
|
64
|
-
recursive: true, verbose: true, dotFolders: false, dotFiles: false, mangle: true };
|
|
65
|
-
options = { ...defaultOptions, ...options };
|
|
66
|
-
|
|
67
|
-
// Validate input
|
|
68
|
-
if (typeof input !== 'string') return console.error(
|
|
69
|
-
'minify() » ERROR: 1st arg <input> must be a string.');
|
|
70
|
-
|
|
71
|
-
// Validate options
|
|
72
|
-
for (const key of Object.keys(options)) {
|
|
73
|
-
if (!Object.prototype.hasOwnProperty.call(defaultOptions, key)) return console.error(
|
|
74
|
-
`minify() » ERROR: \`${ key }\` is an invalid option.\n`
|
|
75
|
-
+ `minify() » Valid options: [ ${ Object.keys(defaultOptions).join(', ') } ]`);
|
|
76
|
-
else if (typeof options[key] !== 'boolean') return console.error(
|
|
77
|
-
`minify() » ERROR: \`${ key }\` option can only be set to \`true\` or \`false\`.`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Minify JS based on input
|
|
81
|
-
const minifyOptions = { mangle: options.mangle ? { toplevel: true } : false };
|
|
82
|
-
if (fs.existsSync(input)) { // minify based on path arg
|
|
83
|
-
if (input.endsWith('.js')) { // file path passed
|
|
84
|
-
if (options.verbose) console.info(`minify() » Minifying ${ input }...`);
|
|
85
|
-
const minifyResult = uglifyJS.minify(fs.readFileSync(input, 'utf8'), minifyOptions);
|
|
86
|
-
if (minifyResult.error) console.error(`minify() » ERROR: ${ minifyResult.error.message }`);
|
|
87
|
-
return { code: minifyResult.code, srcPath: path.resolve(process.cwd(), input),
|
|
88
|
-
error: minifyResult.error };
|
|
89
|
-
} else { // dir path passed
|
|
90
|
-
return findJS(input, { recursive: options.recursive, verbose: options.verbose,
|
|
91
|
-
dotFolders: options.dotFolders, dotFiles: options.dotFiles
|
|
92
|
-
})?.map(jsPath => { // minify found JS files
|
|
93
|
-
if (options.verbose) console.info(`minify() » Minifying ${ jsPath }...`);
|
|
94
|
-
const srcCode = fs.readFileSync(jsPath, 'utf8'),
|
|
95
|
-
minifyResult = uglifyJS.minify(srcCode, minifyOptions);
|
|
96
|
-
if (minifyResult.error) console.error(`minify() » ERROR: ${ minifyResult.error.message }`);
|
|
97
|
-
return { code: minifyResult.code, srcPath: jsPath, error: minifyResult.error };
|
|
98
|
-
}).filter(data => !data.error); // filter out failed minifications
|
|
99
|
-
}
|
|
100
|
-
} else { // minify based on src code arg
|
|
101
|
-
if (options.verbose) console.info('minify() » Minifying passed source code...');
|
|
102
|
-
const minifyResult = uglifyJS.minify(input, minifyOptions);
|
|
103
|
-
if (minifyResult.error) console.error(`minify() » ERROR: ${ minifyResult.error.message }`);
|
|
104
|
-
|
|
105
|
-
return { code: minifyResult.code, srcPath: undefined, error: minifyResult.error };
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// EXPORT main functions if script was required
|
|
110
|
-
if (require.main !== module) module.exports = { minify, findJS };
|
|
111
|
-
|
|
112
|
-
else { // run as CLI utility
|
|
113
|
-
|
|
114
|
-
// Init UI colors
|
|
115
|
-
const nc = '\x1b[0m', // no color
|
|
116
|
-
br = '\x1b[1;91m', // bright red
|
|
117
|
-
by = '\x1b[1;33m', // bright yellow
|
|
118
|
-
bg = '\x1b[1;92m'; // bright green
|
|
119
|
-
|
|
120
|
-
// Load FLAG settings
|
|
121
|
-
const config = {};
|
|
122
|
-
const argRegex = {
|
|
123
|
-
'dryRun': /^--?(?:n|dry-?run)$/,
|
|
124
|
-
'includeDotFolders': /^--?(?:dd?|(?:include-?)?dot-?(?:folder|dir(?:ector(?:y|ie))?)s?=?(?:true|1)?)$/,
|
|
125
|
-
'includeDotFiles': /^--?(?:df|D|(?:include-?)?dot-?files?=?(?:true|1)?)$/,
|
|
126
|
-
'noRecursion': /^--?(?:R|(?:disable|no)-?recursi(?:on|ve)|recursi(?:on|ve)=(?:false|0))$/,
|
|
127
|
-
'noMangle': /^--?(?:M|(?:disable|no)-?mangle|mangle=(?:false|0))$/,
|
|
128
|
-
'quietMode': /^--?q(?:uiet)?(?:-?mode)?$/,
|
|
129
|
-
'help': /^--?h(?:elp)?$/,
|
|
130
|
-
'version': /^--?ve?r?s?i?o?n?$/
|
|
131
|
-
};
|
|
132
|
-
process.argv.forEach(arg => {
|
|
133
|
-
if (!arg.startsWith('-')) return;
|
|
134
|
-
const matchedFlag = Object.keys(argRegex).find(flag => argRegex[flag].test(arg));
|
|
135
|
-
if (matchedFlag) config[matchedFlag] = true;
|
|
136
|
-
else {
|
|
137
|
-
console.error(`\n${br}ERROR: Arg [${ arg }] not recognized.${nc}`);
|
|
138
|
-
console.info(`\n${by}Valid arguments are below.${nc}`);
|
|
139
|
-
printHelpSections(['configOptions', 'infoCmds']);
|
|
140
|
-
process.exit(1);
|
|
141
|
-
}});
|
|
142
|
-
|
|
143
|
-
// Show HELP screen if -h or --help passed
|
|
144
|
-
if (process.argv.some(arg => argRegex.help.test(arg))) printHelpSections();
|
|
145
|
-
|
|
146
|
-
// Show VERSION number if -v or --version passed
|
|
147
|
-
else if (process.argv.some(arg => argRegex.version.test(arg)))
|
|
148
|
-
console.info('v' + require('./package.json').version);
|
|
149
|
-
|
|
150
|
-
else { // run MAIN routine
|
|
151
|
-
|
|
152
|
-
// Init I/O args
|
|
153
|
-
const [inputArg = '', outputArg = ''] = ( // default to empty strings for error-less handling
|
|
154
|
-
process.argv.slice(2) // exclude executable and script paths
|
|
155
|
-
.filter(arg => !arg.startsWith('-')) // exclude flags
|
|
156
|
-
.map(arg => arg.replace(/^\/*/, '')) // clean leading slashes to avoid parsing system root
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// Validate input arg (output arg can be anything)
|
|
160
|
-
const inputPath = path.resolve(process.cwd(), inputArg);
|
|
161
|
-
if (inputArg && !fs.existsSync(inputPath)) {
|
|
162
|
-
console.error(`\n${br}Error: First argument can only be an existing file or directory.`
|
|
163
|
-
+ `\n${ inputPath } does not exist.${nc}`
|
|
164
|
-
+ `\n\n${bg}Example valid command: \n>> minify-js . output.min.js${nc}`
|
|
165
|
-
+ `\n\n${by}For all command options: \n>> minify-js --help${nc}`);
|
|
166
|
-
process.exit(1);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Find all eligible JavaScript files or arg-passed file
|
|
170
|
-
const unminnedJSfiles = inputArg.endsWith('.js') ? [inputPath]
|
|
171
|
-
: findJS(inputPath, { recursive: !config.noRecursion, verbose: !config.quietMode });
|
|
172
|
-
|
|
173
|
-
if (config.dryRun) { // -n or --dry-run passed
|
|
174
|
-
if (unminnedJSfiles.length > 0) { // print files to be processed
|
|
175
|
-
console.info(`\n${by}JS files to be minified:${nc}`);
|
|
176
|
-
unminnedJSfiles.forEach(file => console.info(file));
|
|
177
|
-
} else console.info(`${by}\nNo JS files will be minified.${nc}`);
|
|
178
|
-
|
|
179
|
-
} else { // actually minify JavaScript files
|
|
180
|
-
|
|
181
|
-
// Build array of minification data
|
|
182
|
-
const failedPaths = [];
|
|
183
|
-
const minifyData = unminnedJSfiles.map(jsPath => {
|
|
184
|
-
const minifyResult = minify(jsPath, { verbose: !config.quietMode, mangle: !config.noMangle });
|
|
185
|
-
if (minifyResult.error) failedPaths.push(jsPath);
|
|
186
|
-
return minifyResult;
|
|
187
|
-
}).filter(minifyResult => !minifyResult.error); // filter out failed minifications
|
|
188
|
-
|
|
189
|
-
// Write array data to files
|
|
190
|
-
minifyData?.forEach(({ code, srcPath }) => {
|
|
191
|
-
const outputDir = path.join(
|
|
192
|
-
path.dirname(srcPath), // path of file to be minified
|
|
193
|
-
/so?u?rce?$/.test(path.dirname(srcPath)) ? '../min' // + ../min/ if in *(src|source)/
|
|
194
|
-
: outputArg.endsWith('.js') ? path.dirname(outputArg) // or path from file output arg
|
|
195
|
-
: outputArg || 'min' // or path from folder output arg or min/ if no output arg passed
|
|
196
|
-
);
|
|
197
|
-
const outputFilename = (
|
|
198
|
-
outputArg.endsWith('.js') && inputArg.endsWith('.js')
|
|
199
|
-
? path.basename(outputArg).replace(/(\.min)?\.js$/, '')
|
|
200
|
-
: path.basename(srcPath, '.js')
|
|
201
|
-
) + '.min.js';
|
|
202
|
-
const outputPath = path.join(outputDir, outputFilename);
|
|
203
|
-
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
204
|
-
fs.writeFileSync(outputPath, code, 'utf8');
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// Print final summary
|
|
208
|
-
if (minifyData?.length > 0) {
|
|
209
|
-
printIfNotQuiet(`\n${bg}Minification complete!${nc}`);
|
|
210
|
-
printIfNotQuiet(
|
|
211
|
-
`${ minifyData.length } file${ minifyData.length > 1 ? 's' : '' } minified.`);
|
|
212
|
-
} else printIfNotQuiet(`${by}No unminified JavaScript files processed.${nc}`);
|
|
213
|
-
if (failedPaths.length > 0) {
|
|
214
|
-
printIfNotQuiet(`\n${br}`
|
|
215
|
-
+ `${ failedPaths.length } file${ failedPaths.length > 1 ? 's' : '' }`
|
|
216
|
-
+ ` failed to minify:${nc}`);
|
|
217
|
-
failedPaths.forEach(path => printIfNotQuiet(path));
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Define LOGGING functions
|
|
223
|
-
|
|
224
|
-
function printHelpSections(includeSections = ['cmdFormat', 'pathArgs', 'configOptions', 'infoCmds']) {
|
|
225
|
-
const helpSections = {
|
|
226
|
-
'cmdFormat': [
|
|
227
|
-
`\n${by}minify-js [inputPath] [outputPath] [options]${nc}`
|
|
228
|
-
],
|
|
229
|
-
'pathArgs': [
|
|
230
|
-
'\nPath arguments:',
|
|
231
|
-
' [inputPath] '
|
|
232
|
-
+ 'Path to JS file or directory containing JS files to be minified,'
|
|
233
|
-
+ ' relative to the current working directory.',
|
|
234
|
-
' [outputPath] '
|
|
235
|
-
+ 'Path to file or directory where minified files will be stored,'
|
|
236
|
-
+ ' relative to original file location (if not provided, min/ is used).'
|
|
237
|
-
],
|
|
238
|
-
'configOptions': [
|
|
239
|
-
'\nConfig options:',
|
|
240
|
-
' -n, --dry-run Don\'t actually minify the file(s),'
|
|
241
|
-
+ ' just show if they will be processed.',
|
|
242
|
-
' -d, --include-dotfolders Include dotfolders in file search.',
|
|
243
|
-
' -D, --include-dotfiles Include dotfiles in file search.',
|
|
244
|
-
' -R, --no-recursion Disable recursive file searching.',
|
|
245
|
-
' -M, --no-mangle Disable mangling names.',
|
|
246
|
-
' -q, --quiet Suppress all logging except errors.'
|
|
247
|
-
],
|
|
248
|
-
'infoCmds': [
|
|
249
|
-
'\nInfo commands:',
|
|
250
|
-
' -h, --help Display help screen.',
|
|
251
|
-
' -v, --version Show version number.'
|
|
252
|
-
]
|
|
253
|
-
};
|
|
254
|
-
includeSections.forEach(section => { // print valid arg elems
|
|
255
|
-
helpSections[section]?.forEach(line => printHelpMsg(line)); });
|
|
256
|
-
|
|
257
|
-
function printHelpMsg(msg) { // wrap msg + indent 2nd+ lines (for --help screen)
|
|
258
|
-
const terminalWidth = process.stdout.columns || 80,
|
|
259
|
-
indentation = 29, lines = [], words = msg.match(/\S+|\s+/g);
|
|
260
|
-
|
|
261
|
-
// Split msg into lines of appropriate lengths
|
|
262
|
-
let currentLine = '';
|
|
263
|
-
words.forEach(word => {
|
|
264
|
-
const lineLength = terminalWidth - ( lines.length === 0 ? 0 : indentation );
|
|
265
|
-
if (currentLine.length + word.length > lineLength) { // cap/store it
|
|
266
|
-
lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
|
|
267
|
-
currentLine = '';
|
|
268
|
-
}
|
|
269
|
-
currentLine += word;
|
|
270
|
-
});
|
|
271
|
-
lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
|
|
272
|
-
|
|
273
|
-
// Print formatted msg
|
|
274
|
-
lines.forEach((line, index) => console.info(
|
|
275
|
-
index === 0 ? line // print 1st line unindented
|
|
276
|
-
: ' '.repeat(indentation) + line // print subsequent lines indented
|
|
277
|
-
));
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function printIfNotQuiet(msg) { if (!config.quietMode) console.info(msg); }
|
|
282
|
-
}
|