@adamlui/minify.js 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,10 @@
6
6
  </picture>
7
7
  &nbsp;English |
8
8
  <a href="https://github.com/adamlui/js-utils/tree/main/minify.js/docs/zh-cn#readme">简体中文</a> |
9
- <a href="https://github.com/adamlui/js-utils/tree/main/minify.js/docs/zh-tw#readme">繁體中文</a>
9
+ <a href="https://github.com/adamlui/js-utils/tree/main/minify.js/docs/zh-tw#readme">繁體中文</a> |
10
+ <a href="https://github.com/adamlui/js-utils/tree/main/minify.js/docs/hi#readme">हिंदी</a> |
11
+ <a href="https://github.com/adamlui/js-utils/tree/main/minify.js/docs/bn#readme">বাংলা</a> |
12
+ <a href="https://github.com/adamlui/js-utils/tree/main/minify.js/docs/mr#readme">मराठी</a>
10
13
  </h6>
11
14
  </div>
12
15
 
@@ -16,7 +19,7 @@
16
19
 
17
20
  <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&logoColor=white&labelColor=464646&style=for-the-badge"></a>
18
21
  <a href="#%EF%B8%8F-mit-license"><img height=31 src="https://img.shields.io/badge/License-MIT-red.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
19
- <a href="https://www.npmjs.com/package/@adamlui/minify.js?activeTab=versions"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.3.0-fc7811.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
22
+ <a href="https://www.npmjs.com/package/@adamlui/minify.js?activeTab=versions"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.4.0-fc7811.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
20
23
  <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>
21
24
  <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>
22
25
 
@@ -34,12 +37,18 @@ As a **global utility**:
34
37
  npm install -g @adamlui/minify.js
35
38
  ```
36
39
 
37
- As a **dev dependency**, from your project root:
40
+ As a **dev dependency** (e.g. for build scripts), from your project root:
38
41
 
39
42
  ```
40
43
  npm install -D @adamlui/minify.js
41
44
  ```
42
45
 
46
+ As a **runtime dependency** (e.g. for on-the-fly minification), from your project root:
47
+
48
+ ```
49
+ npm install @adamlui/minify.js
50
+ ```
51
+
43
52
  ## 💻 Command line usage
44
53
 
45
54
  The basic **global command** is:
@@ -58,10 +67,10 @@ To specify **input/output** paths:
58
67
  minify-js [input_path] [output_path]
59
68
  ```
60
69
 
61
- - `[input_path]`: Path to JS file or directory containing JS files to be minified, relative to the current working directory.
70
+ - `[input_path]`: Path to JS file or directory containing JS files to be minified, relative to the current working directory.
62
71
  - `[output_path]`: Path to file or directory where minified files will be stored, relative to original file location (if not provided, `min/` is used).
63
72
 
64
- **💡 Note:** If folders are passed, files will be processed recursively.
73
+ **💡 Note:** If folders are passed, files will be processed recursively unless `-R` or `--no-recursion` is passed.
65
74
 
66
75
  #
67
76
 
@@ -76,21 +85,6 @@ To use as a **package script**, in your project's `package.json`:
76
85
  Replace `<minify-js-cmd>` with `minify-js` + optional args. Then, `npm run build:js` can be used to run the command.
77
86
  <br><br>
78
87
 
79
- ### Command line options
80
-
81
- ```
82
- Config options:
83
- -n, --dry-run Don't actually minify the file(s), just show
84
- if they will be processed.
85
- -d, --include-dotfolders Include dotfolders in file search.
86
- -D, --include-dotfiles Include dotfiles in file search.
87
- -q, --quiet Suppress all logging except errors.
88
-
89
- Info commands:
90
- -h, --help Display help screen.
91
- -v, --version Show version number.
92
- ```
93
-
94
88
  ### Example commands
95
89
 
96
90
  Minify all JavaScript files in the **current directory** (outputs to `min/`):
@@ -117,52 +111,99 @@ Specify both **input and output** directories (outputs to `output_folder/`):
117
111
  minify-js input_folder output_folder
118
112
  ```
119
113
 
120
- ## 🔌 API Reference
114
+ ### Command line options
121
115
 
122
- You can load **minify.js** in your app like this:
116
+ ```
117
+ Config options:
118
+ -n, --dry-run Don't actually minify the file(s), just show
119
+ if they will be processed.
120
+ -d, --include-dotfolders Include dotfolders in file search.
121
+ -D, --include-dotfiles Include dotfiles in file search.
122
+ -R, --no-recursion Disable recursive file searching.
123
+ -M, --no-mangle Disable mangling names.
124
+ -q, --quiet Suppress all logging except errors.
123
125
 
124
- ```js
125
- const minifyJS = require('@adamlui/minify.js');
126
+ Info commands:
127
+ -h, --help Display help screen.
128
+ -v, --version Show version number.
126
129
  ```
127
130
 
128
- There is a single high level function, `minify(input, options)`, which will perform all minification/recursion phases in a configurable manner that adapts to the string input.
131
+ ## 🔌 API reference
129
132
 
130
- ### minify(options)
133
+ You can also import **minify.js** into your app to use its API methods, both as an ECMAScript module or a CommonJS module.
131
134
 
132
- Options are boolean (set to `true` by default) passed as object properties e.g. `minifyJS.minify(input, { option: true })`:
135
+ #### ESM:
133
136
 
137
+ ```js
138
+ import * as minifyJS from '@adamlui/minify.js';
134
139
  ```
135
- recursive Recursively search for nested files if dir path passed.
136
- verbose Show logging in console/terminal.
140
+
141
+ #### CJS:
142
+
143
+ ```js
144
+ const minifyJS = require('@adamlui/minify.js');
137
145
  ```
138
146
 
139
- ### minify(input)
147
+ ### minify(input, options)
140
148
 
141
- Input is a string that represents either source code or a path.
149
+ This function minifies JavaScript code based on the string input supplied.
142
150
 
143
151
  If **source code** is passed, it is directly minified, then an object containing `srcPath` + `code` + `error` is returned:
144
152
 
145
153
  ```js
146
154
  const srcCode = 'function add(first, second) { return first + second; }',
147
- result = minifyJS.minify(srcCode);
148
- console.log(result.error); // runtime error, or `undefined` if no error
149
- console.log(result.code); // minified output: function add(n,d){return n+d}
155
+ minifyResult = minifyJS.minify(srcCode);
156
+ console.log(minifyResult.error); // runtime error, or `undefined` if no error
157
+ console.log(minifyResult.code); // minified output: function add(n,d){return n+d}
150
158
  ```
151
159
 
152
160
  If a **file path** is passed, the file's code is loaded then minified, returning an object like above.
153
161
 
154
- If a **directory path** is passed, JavaScript files are searched for (recursively by default), each is minified, then an array of objects containing `srcPath` + `code` + `error` is returned:
162
+ If a **directory path** is passed, JavaScript files are searched for (recursively by default), each one's code is loaded then minified, then an array of objects containing `srcPath` + `code` + `error` is returned:
155
163
 
156
164
  ```js
157
- const recursiveResults = minifyJS.minify('.');
158
- recursiveResults.forEach(result =>
159
- console.log(result.srcPath) // JS files in all sub-directories
165
+ const results = minifyJS.minify('.');
166
+ results.forEach(result =>
167
+ console.log(result.srcPath) // paths to JS files in working directory + all nested directories
160
168
  );
169
+ console.log(results[1].code) // minified code of 2nd JS file if found, or `undefined` if not found
170
+ ```
161
171
 
162
- const nonRecursiveResults = minifyJS.minify('.', { recursive: false });
163
- nonRecursiveResults.forEach(result =>
164
- console.log(result.srcPath) // JS files in working directory only
165
- );
172
+ Options are boolean, passed as object properties. For example:
173
+
174
+ ```js
175
+ minifyJS.minify(input, { dotFiles: true });
176
+ // returns data object where dotfiles are also processed if `input` is a path
177
+ ```
178
+
179
+ Possible parameters (and their default settings) are:
180
+
181
+ ```
182
+ recursive (true) Recursively search for nested files if dir path passed.
183
+ verbose (true) Show logging in console/terminal.
184
+ dotFolders (false) Include dotfolders in file search.
185
+ dotFiles (false) Include dotfiles in file search.
186
+ mangle (true) Shorten variable names (typically to one character).
187
+ ```
188
+
189
+ ### findJS(searchDir, options)
190
+
191
+ This function searches for all unminified JavaScript files within the `searchDir` string passed (useful for discovering what files [`minify()`](#minifyinput-options) will process) and returns an array containing their filepaths.
192
+
193
+ Options are boolean, passed as object properties. For example:
194
+
195
+ ```js
196
+ minifyJS.findJS(searchDir, { recursive: false });
197
+ // returns array containing filepaths to unminified JS files in exactly `searchDir`
198
+ ```
199
+
200
+ Possible parameters (and their default settings) are:
201
+
202
+ ```
203
+ recursive (true) Recursively search for nested files if dir path passed.
204
+ verbose (false) Show logging in console/terminal.
205
+ dotFolders (false) Include dotfolders in file search.
206
+ dotFiles (false) Include dotfiles in file search.
166
207
  ```
167
208
 
168
209
  <br>
@@ -174,25 +215,13 @@ Please consider [giving a GitHub ⭐](https://github.com/adamlui/js-utils) if th
174
215
 
175
216
  ## 🏛️ MIT License
176
217
 
177
- **Copyright (c) 2023–2024 [Adam Lui](https://github.com/adamlui)**
178
-
179
- Permission is hereby granted, free of charge, to any person obtaining a copy
180
- of this software and associated documentation files (the "Software"), to deal
181
- in the Software without restriction, including without limitation the rights
182
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
183
- copies of the Software, and to permit persons to whom the Software is
184
- furnished to do so, subject to the following conditions:
185
-
186
- The above copyright notice and this permission notice shall be included in all
187
- copies or substantial portions of the Software.
188
-
189
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
190
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
192
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
193
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
194
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
195
- SOFTWARE.
218
+ **Copyright © 2023–2024 [Adam Lui](https://github.com/adamlui)**
219
+
220
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
221
+
222
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
223
+
224
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
196
225
 
197
226
  <br>
198
227
 
package/docs/LICENSE.md CHANGED
@@ -1,21 +1,24 @@
1
- <div align="right">
2
- <h6>
3
- <picture>
4
- <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
5
- <img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
6
- </picture>
7
- &nbsp;English |
8
- <a href="zh-cn/LICENSE.md">简体中文</a> |
9
- <a href="zh-tw/LICENSE.md">繁體中文</a>
10
- </h6>
11
- </div>
12
-
13
- # 🏛️ MIT License
14
-
15
- **Copyright (c) 2023–2024 [Adam Lui](https://github.com/adamlui)**
16
-
17
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
-
19
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
20
-
21
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ <div align="right">
2
+ <h6>
3
+ <picture>
4
+ <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
5
+ <img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
6
+ </picture>
7
+ &nbsp;English |
8
+ <a href="zh-cn/LICENSE.md">简体中文</a> |
9
+ <a href="zh-tw/LICENSE.md">繁體中文</a> |
10
+ <a href="hi/LICENSE.md">हिंदी</a> |
11
+ <a href="bn/LICENSE.md">বাংলা</a> |
12
+ <a href="mr/LICENSE.md">मराठी</a>
13
+ </h6>
14
+ </div>
15
+
16
+ # 🏛️ MIT License
17
+
18
+ **Copyright © 2023–2024 [Adam Lui](https://github.com/adamlui)**
19
+
20
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/docs/SECURITY.md CHANGED
@@ -1,17 +1,20 @@
1
- <div align="right">
2
- <h6>
3
- <picture>
4
- <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
5
- <img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
6
- </picture>
7
- &nbsp;English |
8
- <a href="zh-cn/SECURITY.md">简体中文</a> |
9
- <a href="zh-tw/SECURITY.md">繁體中文</a>
10
- </h6>
11
- </div>
12
-
13
- # 🛡️ Security Policy
14
-
15
- If you find a vulnerability, please open a [draft security advisory](https://github.com/adamlui/js-utils/security/advisories/new).
16
-
17
- Pull requests are also welcome, but for safety reasons, send an email to <adam@kudoai.com> and wait for a response before making it public.
1
+ <div align="right">
2
+ <h6>
3
+ <picture>
4
+ <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/white/icon32.svg">
5
+ <img height=14 src="https://raw.githubusercontent.com/adamlui/js-utils/main/docs/images/earth-icon/black/icon32.svg">
6
+ </picture>
7
+ &nbsp;English |
8
+ <a href="zh-cn/SECURITY.md">简体中文</a> |
9
+ <a href="zh-tw/SECURITY.md">繁體中文</a> |
10
+ <a href="hi/SECURITY.md">हिंदी</a> |
11
+ <a href="bn/SECURITY.md">বাংলা</a> |
12
+ <a href="mr/SECURITY.md">मराठी</a>
13
+ </h6>
14
+ </div>
15
+
16
+ # 🛡️ Security Policy
17
+
18
+ If you find a vulnerability, please open a [draft security advisory](https://github.com/adamlui/js-utils/security/advisories/new).
19
+
20
+ Pull requests are also welcome, but for safety reasons, send an email to <adam@kudoai.com> and wait for a response before making it public.
package/minify.js CHANGED
@@ -1,200 +1,212 @@
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
- // Load FLAGS
9
- const config = require.main !== module ? {} : {
10
- dryRun: process.argv.some(arg => /^--?(?:n|dry-?run)$/.test(arg)),
11
- includeDotFolders: process.argv.some(arg =>
12
- /^--?(?:dd?|(?:include-?)?dot-?(?:folder|dir(?:ector(?:y|ie))?)s?)$/.test(arg)),
13
- includeDotFiles: process.argv.some(arg =>
14
- /^--?(?:df|D|(?:include-?)?dot-?files?)$/.test(arg)),
15
- quietMode: process.argv.some(arg => /^--?q(?:uiet)?$/.test(arg))
16
- };
17
-
18
- // Define MAIN functions
19
-
20
- function findJSfiles(dir, options = { recursive: true, verbose: false }) {
21
- const dirFiles = fs.readdirSync(dir), unminnedJSfiles = [];
22
- dirFiles.forEach(file => {
23
- const filePath = path.resolve(dir, file);
24
- if (fs.statSync(filePath).isDirectory() && file != 'node_modules' &&
25
- (config.includeDotFolders || !file.startsWith('.')) && options.recursive) {
26
- if (options.verbose)
27
- console.info(`Searching for unminified JS files in: ${filePath}...`);
28
- unminnedJSfiles.push( // recursively find unminified JS in eligible dir
29
- ...findJSfiles(filePath));
30
- } else if (/\.js(?<!\.min\.js)$/.test(file) &&
31
- (config.includeDotFiles || !file.startsWith('.')))
32
- unminnedJSfiles.push(filePath); // store eligible unminified JS file for minification
33
- });
34
- return unminnedJSfiles;
35
- }
36
-
37
- function minify(input, options = { recursive: true, verbose: true }) {
38
- if (typeof input !== 'string')
39
- return console.error('minify.js >> ERROR:'
40
- + ' First argument must be a string of source code or filepath');
41
- if (fs.existsSync(input)) { // minify based on path arg
42
- if (input.endsWith('.js')) { // file path passed
43
- if (options.verbose) console.info(`Minifying ${ input }...`);
44
- const result = uglifyJS.minify(fs.readFileSync(input, 'utf8'));
45
- if (result.error) console.error(`ERROR: ${ result.error.message }`);
46
- return { code: result.code, srcPath: input, error: result.error };
47
- } else { // dir path passed
48
- const unminnedJSfiles = findJSfiles(input, { recursive: options.recursive });
49
- const minifiedJSfiles = unminnedJSfiles.map(jsPath => {
50
- if (options.verbose) console.info(`Minifying ${ jsPath }...`);
51
- const srcCode = fs.readFileSync(jsPath, 'utf8'),
52
- result = uglifyJS.minify(srcCode).code;
53
- if (result.error) console.error(`ERROR: ${ result.error.message }`);
54
- return { code: result.code, srcPath: jsPath, error: result.error };
55
- }).filter(file => file !== null); // filter out failed minifications
56
- return minifiedJSfiles;
57
- }
58
- } else { // minify based on src code arg
59
- if (options.verbose) console.info('Minifying passed source code...');
60
- const result = uglifyJS.minify(input);
61
- if (result.error) console.error(`ERROR: ${ result.error.message }`);
62
- return { code: result.code, srcPath: input, error: result.error };
63
- }
64
- }
65
-
66
- // EXPORT functions if script was required
67
- if (require.main !== module) module.exports = { minify, findJSfiles };
68
-
69
- else { // run as CLI tool
70
-
71
- // Init UI colors
72
- const nc = '\x1b[0m', // no color
73
- br = '\x1b[1;91m', // bright red
74
- by = '\x1b[1;33m', // bright yellow
75
- bg = '\x1b[1;92m'; // bright green
76
-
77
- // Show HELP screen if -h or --help passed
78
- if (process.argv.some(arg => /^--?h(?:elp)?$/.test(arg))) {
79
-
80
- printHelp(`\n${by}minify-js [inputPath] [outputPath] [options]${nc}`);
81
- printHelp('\nPath arguments:');
82
- printHelp(' [inputPath] '
83
- + 'Path to JS file or directory containing JS files to be minified,'
84
- + ' relative to the current working directory.');
85
- printHelp(' [outputPath] '
86
- + 'Path to file or directory where minified files will be stored,'
87
- + ' relative to original file location (if not provided, min/ is used).');
88
- printHelp('\nConfig options:');
89
- printHelp(' -n, --dry-run Don\'t actually minify the file(s),'
90
- + ' just show if they will be processed.');
91
- printHelp(' -d, --include-dotfolders Include dotfolders in file search.');
92
- printHelp(' -D, --include-dotfiles Include dotfiles in file search.');
93
- printHelp(' -q, --quiet Suppress all logging except errors.');
94
- printHelp('\nInfo commands:');
95
- printHelp(' -h, --help Display this help screen.');
96
- printHelp(' -v, --version Show version number.');
97
-
98
- // Show VERSION number if -v or --version passed
99
- } else if (process.argv.some(arg => /^--?ve?r?s?i?o?n?$/.test(arg))) {
100
- console.info('v' + require('./package.json').version);
101
-
102
- } else { // run MAIN routine
103
-
104
- // Init I/O args
105
- const [inputArg = '', outputArg = ''] = ( // default to empty strings for error-less handling
106
- process.argv.slice(2) // exclude executable and script paths
107
- .filter(arg => !arg.startsWith('-')) // exclude flags
108
- .map(arg => arg.replace(/^\/*/, '')) // clean leading slashes to avoid parsing system root
109
- );
110
-
111
- // Validate input arg (output arg can be anything)
112
- const inputPath = path.resolve(process.cwd(), inputArg);
113
- if (inputArg && !fs.existsSync(inputPath)) {
114
- console.error(`\n${br}Error: First arg must be an existing file or directory.`
115
- + `\n${ inputPath } does not exist.${nc}`
116
- + `\n\n${bg}Example valid command: \n>> minify-js . output.min.js${nc}`
117
- + `\n\n${by}For all command options: \n>> minify-js --help${nc}`);
118
- process.exit(1);
119
- }
120
-
121
- // Recursively find all eligible JavaScript files or arg-passed file
122
- const unminnedJSfiles = inputArg.endsWith('.js') ? [inputPath] : findJSfiles(inputPath);
123
-
124
- if (unminnedJSfiles.length === 0) { // print nothing found
125
- printIfNotQuiet(`\n${by}No unminified JavaScript files found.${nc}`);
126
-
127
- } else if (config.dryRun) { // print files to be processed
128
- console.info(`\n${by}JS files to be minified:${nc}`);
129
- unminnedJSfiles.forEach(file => console.info(file));
130
-
131
- } else { // actually minify JavaScript files
132
- printIfNotQuiet(''); // line break before first log
133
-
134
- // Build array of minified code
135
- const failedJSpaths = [];
136
- const minifiedJSdata = unminnedJSfiles.map(jsPath => {
137
- const result = minify(jsPath, { verbose: !config.quietMode });
138
- if (result.error) failedJSpaths.push(jsPath);
139
- return result;
140
- }).filter(result => !result.error); // filter out failed minifications
141
-
142
- // Write array data to files
143
- minifiedJSdata.forEach(({ code, srcPath }) => {
144
- const outputDir = path.join(
145
- path.dirname(srcPath), // path of file to be minified
146
- /so?u?rce?$/.test(path.dirname(srcPath)) ? '../min' // + ../min/ if in *(src|source)/
147
- : outputArg.endsWith('.js') ? path.dirname(outputArg) // or path from file output arg
148
- : outputArg || 'min' // or path from folder output arg or min/ if no output arg passed
149
- );
150
- const outputFilename = (
151
- outputArg.endsWith('.js') && inputArg.endsWith('.js')
152
- ? path.basename(outputArg).replace(/(\.min)?\.js$/, '')
153
- : path.basename(srcPath, '.js')
154
- ) + '.min.js';
155
- const outputPath = path.join(outputDir, outputFilename);
156
- if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
157
- fs.writeFileSync(outputPath, code, 'utf8');
158
- });
159
-
160
- // Print final summary
161
- if (minifiedJSdata.length > 0) {
162
- printIfNotQuiet(`\n${bg}Minification complete!${nc}`);
163
- printIfNotQuiet(
164
- `${ minifiedJSdata.length } file${ minifiedJSdata.length > 1 ? 's' : '' } minified.`);
165
- } else printIfNotQuiet(`${by}No unminified JavaScript files processed successfully.${nc}`);
166
- const failedCnt = unminnedJSfiles.length - minifiedJSdata.length;
167
- if (failedCnt > 0) {
168
- printIfNotQuiet(`\n${br + failedCnt} file${ failedCnt > 1 ? 's' : '' } failed to minify:${nc}`);
169
- printIfNotQuiet(failedJSpaths.join(', '));
170
- }
171
- }
172
- }
173
-
174
- // Define LOGGING functions
175
-
176
- function printHelp(msg) { // wrap msg + indent 2nd+ lines (for --help screen)
177
- const terminalWidth = process.stdout.columns || 80,
178
- indentation = 29, lines = [], words = msg.match(/\S+|\s+/g);
179
-
180
- // Split msg into lines of appropriate lengths
181
- let currentLine = '';
182
- words.forEach(word => {
183
- const lineLength = terminalWidth - ( lines.length === 0 ? 0 : indentation );
184
- if (currentLine.length + word.length > lineLength) { // cap/store it
185
- lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
186
- currentLine = '';
187
- }
188
- currentLine += word;
189
- });
190
- lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
191
-
192
- // Print formatted msg
193
- lines.forEach((line, index) => console.info(
194
- index === 0 ? line // print 1st line unindented
195
- : ' '.repeat(indentation) + line // print subsequent lines indented
196
- ));
197
- }
198
-
199
- function printIfNotQuiet(msg) { if (!config.quietMode) console.info(msg); }
200
- }
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
+ const defaultOptions = { recursive: true, verbose: false, dotFolders: false, dotFiles: false };
12
+ options = { ...defaultOptions, ...options };
13
+ const dirFiles = fs.readdirSync(searchDir), jsFiles = [];
14
+ dirFiles.forEach(file => {
15
+ const filePath = path.resolve(searchDir, file);
16
+ if (fs.statSync(filePath).isDirectory() && file != 'node_modules' &&
17
+ (options.dotFolders || !file.startsWith('.')) && options.recursive) {
18
+ if (options.verbose) console.info(`Searching for unminified JS files in: ${filePath}...`);
19
+ jsFiles.push( // recursively find unminified JS in eligible dir
20
+ ...findJS(filePath));
21
+ } else if (/\.js(?<!\.min\.js)$/.test(file) &&
22
+ (options.dotFiles || !file.startsWith('.')))
23
+ jsFiles.push(filePath); // store eligible unminified JS file for minification
24
+ });
25
+ return jsFiles;
26
+ }
27
+
28
+ function minify(input, options = {}) {
29
+ const defaultOptions = {
30
+ recursive: true, verbose: true, dotFolders: false, dotFiles: false, mangle: true };
31
+ options = { ...defaultOptions, ...options };
32
+ if (typeof input !== 'string')
33
+ return console.error('ERROR:'
34
+ + ' First argument must be a string of source code or file/folder path.');
35
+ const minifyOptions = { mangle: options.mangle ? { toplevel: true } : false };
36
+ if (fs.existsSync(input)) { // minify based on path arg
37
+ if (input.endsWith('.js')) { // file path passed
38
+ if (options.verbose) console.info(`Minifying ${ input }...`);
39
+ const minifyResult = uglifyJS.minify(fs.readFileSync(input, 'utf8'), minifyOptions);
40
+ if (minifyResult.error) console.error(`ERROR: ${ minifyResult.error.message }`);
41
+ return { code: minifyResult.code, srcPath: input, error: minifyResult.error };
42
+ } else { // dir path passed
43
+ return findJS(input, { recursive: options.recursive,
44
+ dotFolders: options.dotFolders, dotFiles: options.dotFiles })
45
+ .map(jsPath => { // minify found JS files
46
+ if (options.verbose) console.info(`Minifying ${ jsPath }...`);
47
+ const srcCode = fs.readFileSync(jsPath, 'utf8'),
48
+ minifyResult = uglifyJS.minify(srcCode, minifyOptions);
49
+ if (minifyResult.error) console.error(`ERROR: ${ minifyResult.error.message }`);
50
+ return { code: minifyResult.code, srcPath: jsPath, error: minifyResult.error };
51
+ }).filter(data => !data.error); // filter out failed minifications
52
+ }
53
+ } else { // minify based on src code arg
54
+ if (options.verbose) console.info('Minifying passed source code...');
55
+ const minifyResult = uglifyJS.minify(input, minifyOptions);
56
+ if (minifyResult.error) console.error(`ERROR: ${ minifyResult.error.message }`);
57
+ return { code: minifyResult.code, srcPath: input, error: minifyResult.error };
58
+ }
59
+ }
60
+
61
+ // EXPORT functions if script was required
62
+ if (require.main !== module) module.exports = { minify, findJS };
63
+
64
+ else { // run as CLI tool
65
+
66
+ // Init UI colors
67
+ const nc = '\x1b[0m', // no color
68
+ br = '\x1b[1;91m', // bright red
69
+ by = '\x1b[1;33m', // bright yellow
70
+ bg = '\x1b[1;92m'; // bright green
71
+
72
+ // Load FLAG settings
73
+ const config = {
74
+ dryRun: process.argv.some(arg => /^--?(?:n|dry-?run)$/.test(arg)),
75
+ includeDotFolders: process.argv.some(arg =>
76
+ /^--?(?:dd?|(?:include-?)?dot-?(?:folder|dir(?:ector(?:y|ie))?)s?)$/.test(arg)),
77
+ includeDotFiles: process.argv.some(arg =>
78
+ /^--?(?:df|D|(?:include-?)?dot-?files?)$/.test(arg)),
79
+ noRecursion: process.argv.some(arg =>
80
+ /^--?(?:R|(?:disable|no)-?recursion)$/.test(arg)),
81
+ noMangle: process.argv.some(arg =>
82
+ /^--?(?:M|(?:disable|no)-?mangle)$/.test(arg)),
83
+ quietMode: process.argv.some(arg => /^--?q(?:uiet)?$/.test(arg))
84
+ };
85
+
86
+ // Show HELP screen if -h or --help passed
87
+ if (process.argv.some(arg => /^--?h(?:elp)?$/.test(arg))) {
88
+ printHelp(`\n${by}minify-js [inputPath] [outputPath] [options]${nc}`);
89
+ printHelp('\nPath arguments:');
90
+ printHelp(' [inputPath] '
91
+ + 'Path to JS file or directory containing JS files to be minified,'
92
+ + ' relative to the current working directory.');
93
+ printHelp(' [outputPath] '
94
+ + 'Path to file or directory where minified files will be stored,'
95
+ + ' relative to original file location (if not provided, min/ is used).');
96
+ printHelp('\nConfig options:');
97
+ printHelp(' -n, --dry-run Don\'t actually minify the file(s),'
98
+ + ' just show if they will be processed.');
99
+ printHelp(' -d, --include-dotfolders Include dotfolders in file search.');
100
+ printHelp(' -D, --include-dotfiles Include dotfiles in file search.');
101
+ printHelp(' -R, --no-recursion Disable recursive file searching.');
102
+ printHelp(' -M, --no-mangle Disable mangling names.');
103
+ printHelp(' -q, --quiet Suppress all logging except errors.');
104
+ printHelp('\nInfo commands:');
105
+ printHelp(' -h, --help Display this help screen.');
106
+ printHelp(' -v, --version Show version number.');
107
+
108
+ // Show VERSION number if -v or --version passed
109
+ } else if (process.argv.some(arg => /^--?ve?r?s?i?o?n?$/.test(arg))) {
110
+ console.info('v' + require('./package.json').version);
111
+
112
+ } else { // run MAIN routine
113
+
114
+ // Init I/O args
115
+ const [inputArg = '', outputArg = ''] = ( // default to empty strings for error-less handling
116
+ process.argv.slice(2) // exclude executable and script paths
117
+ .filter(arg => !arg.startsWith('-')) // exclude flags
118
+ .map(arg => arg.replace(/^\/*/, '')) // clean leading slashes to avoid parsing system root
119
+ );
120
+
121
+ // Validate input arg (output arg can be anything)
122
+ const inputPath = path.resolve(process.cwd(), inputArg);
123
+ if (inputArg && !fs.existsSync(inputPath)) {
124
+ console.error(`\n${br}Error: First argument must be an existing file or directory.`
125
+ + `'\n${ inputPath }' does not exist.${nc}`
126
+ + `\n\n${bg}Example valid command: \n>> minify-js . output.min.js${nc}`
127
+ + `\n\n${by}For all command options: \n>> minify-js --help${nc}`);
128
+ process.exit(1);
129
+ }
130
+
131
+ // Find all eligible JavaScript files or arg-passed file
132
+ const unminnedJSfiles = inputArg.endsWith('.js') ? [inputPath]
133
+ : findJS(inputPath, { recursive: !config.noRecursion });
134
+
135
+ if (unminnedJSfiles.length === 0) { // print nothing found
136
+ printIfNotQuiet(`\n${by}No unminified JavaScript files found.${nc}`);
137
+
138
+ } else if (config.dryRun) { // print files to be processed
139
+ console.info(`\n${by}JS files to be minified:${nc}`);
140
+ unminnedJSfiles.forEach(file => console.info(file));
141
+
142
+ } else { // actually minify JavaScript files
143
+ printIfNotQuiet(''); // line break before first log
144
+
145
+ // Build array of minification data
146
+ const failedPaths = [];
147
+ const minifyData = unminnedJSfiles.map(jsPath => {
148
+ const minifyResult = minify(jsPath, { verbose: !config.quietMode, mangle: !config.noMangle });
149
+ if (minifyResult.error) failedPaths.push(jsPath);
150
+ return minifyResult;
151
+ }).filter(minifyResult => !minifyResult.error); // filter out failed minifications
152
+
153
+ // Write array data to files
154
+ minifyData.forEach(({ code, srcPath }) => {
155
+ const outputDir = path.join(
156
+ path.dirname(srcPath), // path of file to be minified
157
+ /so?u?rce?$/.test(path.dirname(srcPath)) ? '../min' // + ../min/ if in *(src|source)/
158
+ : outputArg.endsWith('.js') ? path.dirname(outputArg) // or path from file output arg
159
+ : outputArg || 'min' // or path from folder output arg or min/ if no output arg passed
160
+ );
161
+ const outputFilename = (
162
+ outputArg.endsWith('.js') && inputArg.endsWith('.js')
163
+ ? path.basename(outputArg).replace(/(\.min)?\.js$/, '')
164
+ : path.basename(srcPath, '.js')
165
+ ) + '.min.js';
166
+ const outputPath = path.join(outputDir, outputFilename);
167
+ if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
168
+ fs.writeFileSync(outputPath, code, 'utf8');
169
+ });
170
+
171
+ // Print final summary
172
+ if (minifyData.length > 0) {
173
+ printIfNotQuiet(`\n${bg}Minification complete!${nc}`);
174
+ printIfNotQuiet(
175
+ `${ minifyData.length } file${ minifyData.length > 1 ? 's' : '' } minified.`);
176
+ } else printIfNotQuiet(`${by}No unminified JavaScript files processed successfully.${nc}`);
177
+ if (failedPaths.length > 0) {
178
+ printIfNotQuiet(`\n${br}`
179
+ + `${ failedPaths.length } file${ failedPaths.length > 1 ? 's' : '' }`
180
+ + ` failed to minify:${nc}`);
181
+ failedPaths.forEach(path => printIfNotQuiet(path));
182
+ }
183
+ }
184
+ }
185
+
186
+ // Define LOGGING functions
187
+
188
+ function printHelp(msg) { // wrap msg + indent 2nd+ lines (for --help screen)
189
+ const terminalWidth = process.stdout.columns || 80,
190
+ indentation = 29, lines = [], words = msg.match(/\S+|\s+/g);
191
+
192
+ // Split msg into lines of appropriate lengths
193
+ let currentLine = '';
194
+ words.forEach(word => {
195
+ const lineLength = terminalWidth - ( lines.length === 0 ? 0 : indentation );
196
+ if (currentLine.length + word.length > lineLength) { // cap/store it
197
+ lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
198
+ currentLine = '';
199
+ }
200
+ currentLine += word;
201
+ });
202
+ lines.push(lines.length === 0 ? currentLine : currentLine.trimStart());
203
+
204
+ // Print formatted msg
205
+ lines.forEach((line, index) => console.info(
206
+ index === 0 ? line // print 1st line unindented
207
+ : ' '.repeat(indentation) + line // print subsequent lines indented
208
+ ));
209
+ }
210
+
211
+ function printIfNotQuiet(msg) { if (!config.quietMode) console.info(msg); }
212
+ }
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
- {
2
- "name": "@adamlui/minify.js",
3
- "version": "1.3.0",
4
- "description": "Recursively minify all JavaScript files",
5
- "author": {
6
- "name": "Adam Lui",
7
- "email": "adam@kudoai.com",
8
- "url": "https://github.com/adamlui"
9
- },
10
- "homepage": "https://github.com/adamlui/js-utils",
11
- "license": "MIT",
12
- "main": "minify.js",
13
- "bin": {
14
- "minifyjs": "minify.js",
15
- "minify-js": "minify.js"
16
- },
17
- "scripts": {
18
- "test": "bash utils/test/minify.test.sh",
19
- "bump:patch": "bash utils/bump.sh patch",
20
- "bump:minor": "bash utils/bump.sh minor",
21
- "bump:major": "bash utils/bump.sh major",
22
- "publish:patch": "bash utils/bump.sh patch --publish",
23
- "publish:minor": "bash utils/bump.sh minor --publish",
24
- "publish:major": "bash utils/bump.sh major --publish"
25
- },
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/adamlui/js-utils.git"
29
- },
30
- "keywords": [
31
- "javascript",
32
- "js",
33
- "js-utils",
34
- "utils",
35
- "utilities",
36
- "minifier"
37
- ],
38
- "bugs": {
39
- "url": "https://github.com/adamlui/js-utils/issues"
40
- },
41
- "dependencies": {
42
- "uglify-js": "^3.17.4"
43
- },
44
- "funding": {
45
- "type": "github",
46
- "url": "https://github.com/sponsors/adamlui"
47
- }
48
- }
1
+ {
2
+ "name": "@adamlui/minify.js",
3
+ "version": "1.4.0",
4
+ "description": "Recursively minify all JavaScript files",
5
+ "author": {
6
+ "name": "Adam Lui",
7
+ "email": "adam@kudoai.com",
8
+ "url": "https://github.com/adamlui"
9
+ },
10
+ "homepage": "https://github.com/adamlui/js-utils",
11
+ "license": "MIT",
12
+ "main": "minify.js",
13
+ "bin": {
14
+ "minifyjs": "minify.js",
15
+ "minify-js": "minify.js"
16
+ },
17
+ "scripts": {
18
+ "test": "bash utils/test/minify.test.sh",
19
+ "bump:patch": "bash utils/bump.sh patch",
20
+ "bump:minor": "bash utils/bump.sh minor",
21
+ "bump:major": "bash utils/bump.sh major",
22
+ "publish:patch": "bash utils/bump.sh patch --publish",
23
+ "publish:minor": "bash utils/bump.sh minor --publish",
24
+ "publish:major": "bash utils/bump.sh major --publish"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/adamlui/js-utils.git"
29
+ },
30
+ "keywords": [
31
+ "javascript",
32
+ "js",
33
+ "js-utils",
34
+ "utils",
35
+ "utilities",
36
+ "minifier"
37
+ ],
38
+ "bugs": {
39
+ "url": "https://github.com/adamlui/js-utils/issues"
40
+ },
41
+ "dependencies": {
42
+ "uglify-js": "^3.17.4"
43
+ },
44
+ "funding": {
45
+ "type": "github",
46
+ "url": "https://github.com/sponsors/adamlui"
47
+ }
48
+ }