@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 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.7"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.4.7-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
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 | Default value
234
- -------------|---------------------------------------------------------|---------------
235
- `recursive` | Recursively search for nested files if dir path passed. | `true`
236
- `verbose` | Show logging in console/terminal. | `true`
237
- `dotFolders` | Include dotfolders in file search. | `false`
238
- `dotFiles` | Include dotfiles in file search. | `false`
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">**Home**</a> /
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>
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ const o=require("fs"),s=require("path"),n=require("./minify"),r="",t="",l="",e="",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.7",
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://github.com/adamlui/js-utils",
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": "minify.js",
15
- "minify-js": "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://github.com/adamlui/js-utils/issues"
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
- }