@adamlui/minify.js 1.4.8 → 1.4.10

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