@adamlui/minify.js 2.1.4 → 2.2.1

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,14 +21,14 @@
21
21
 
22
22
  # </> minify.js
23
23
 
24
- ### Recursively minify all JavaScript files.
24
+ ### Recursively minify all JavaScript files
25
25
 
26
26
  <a href="https://www.npmjs.com/package/@adamlui/minify.js">
27
27
  <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>
28
28
  <a href="#%EF%B8%8F-mit-license">
29
29
  <img height=31 src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
30
- <a href="https://github.com/adamlui/minify.js/releases/tag/node-v2.1.4">
31
- <img height=31 src="https://img.shields.io/badge/Latest_Build-2.1.4-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
30
+ <a href="https://github.com/adamlui/minify.js/releases/tag/node-v2.2.1">
31
+ <img height=31 src="https://img.shields.io/badge/Latest_Build-2.2.1-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
32
32
  <a href="https://www.npmjs.com/package/@adamlui/minify.js?activeTab=code">
33
33
  <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>
34
34
  <a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_minify.js:node.js/src/minify.js">
@@ -155,12 +155,41 @@ Parameter options:
155
155
  --ignores="dir/,file1.js,file2.js" Files/directories to exclude from minification.
156
156
  --comment="comment" Prepend header comment to minified code.
157
157
  Separate by line using '\n'.
158
+ --config="path/to/file" Load custom config file.
158
159
 
159
- Info commands:
160
+ Commands:
161
+ --init Create config file (in project root).
160
162
  -h, --help Display help screen.
161
163
  -v, --version Show version number.
162
164
  ```
163
165
 
166
+ #
167
+
168
+ ### Configuration file
169
+
170
+ **minify.js** can be customized using a `minify.config.mjs` or `minify.config.js` placed in your project root.
171
+
172
+ Example defaults:
173
+
174
+ ```js
175
+ export default {
176
+ dryRun: false, // don't actually minify the file(s), just show if they will be processed
177
+ includeDotFolders: false, // include dotfolders in file search
178
+ includeDotFiles: false, // include dotfiles in file search
179
+ noRecursion: false, // disable recursive file searching
180
+ noMangle: false, // disable mangling names
181
+ noFilenameChange: false, // disable changing file extension to .min.js
182
+ rewriteImports: false, // update import paths from .js to .min.js
183
+ copy: false, // copy minified code to clipboard instead of write to file if single file processed
184
+ relativeOutput: false, // output files relative to each src file instead of to input root
185
+ quietMode: false, // suppress all logging except errors
186
+ ignores: '', // files/dirs to exclude from minification
187
+ comment: '' // header comment to prepend to minified code
188
+ }
189
+ ```
190
+
191
+ 💡 Run `minify-js init` to generate a template `minify.config.mjs` in your project root.
192
+
164
193
  <br>
165
194
 
166
195
  <img height=6px width="100%" src="https://assets.minify-js.org/images/separators/aqua-gradient.png?v=ad67551">
@@ -192,7 +221,7 @@ const minifyJS = require('@adamlui/minify.js')
192
221
  If **source code** is passed, it is directly minified, then an object containing `srcPath` + `code` + `error` is returned:
193
222
 
194
223
  ```js
195
- const srcCode = 'function add(first, second) { return first + second; }',
224
+ const srcCode = 'function add(first, second) { return first + second }',
196
225
  minifyResult = minifyJS.minify(srcCode)
197
226
 
198
227
  console.log(minifyResult.error) // outputs runtime error, or `undefined` if no error
@@ -1,22 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * © 2023–2026 Adam Lui & contributors under the MIT license.
4
- * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
5
- * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
3
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
4
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
5
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
6
6
  */
7
- (async()=>{globalThis.env={devMode:__dirname.match(/[\\/]src/)};let i=require("node-clipboardy"),c=require("fs"),{getMsgs:e,getSysLang:o}=require(`./lib/language${env.devMode?"":".min"}.js`),p=require(`../minify${env.devMode?"":".min"}.js`),t=require("path"),l=require(`./lib/print${env.devMode?"":".min"}.js`);if(Object.assign(globalThis.app??={},require(`../${env.devMode?"../":"./data/"}app.json`)),app.urls.docs+="/#-command-line-usage",app.msgs=await e(o()),app.colors={nc:"",br:"",by:"",bg:"",bw:"",blk:"",tlBG:""},app.regex={flags:{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))$/,noFilenameChange:/^--?(?:X|(?:disable|no)-?(?:file)?name-?change|(?:file)?name-?change=(?:false|0))$/,rewriteImports:/^--?(?:i|rewrite-?imports?=?(?:true|1)?)$/,relativeOutput:/^--?(?:r|relative-?output?=?(?:true|1)?)$/,copy:/^--?c(?:opy)?$/,quietMode:/^--?q(?:uiet)?(?:-?mode)?$/},paramOptions:{ignores:/^--?(?:ignores?|(?:ignore|skip|exclude)(?:d?-?files?)?)(?:=.*|$)/,comment:/^--?comments?(?:=.*|$)/},infoCmds:{help:/^--?h(?:elp)?$/,version:/^--?ve?r?s?i?o?n?$/},version:/^[~^>=]?\d+\.\d+\.\d+$/},app.config={},process.argv.forEach(o=>{var e,s,i;o.startsWith("-")&&(e=Object.keys(app.regex.paramOptions).find(e=>app.regex.paramOptions[e].test(o)),i=Object.keys(app.regex.flags).find(e=>app.regex.flags[e].test(o)),s=Object.keys(app.regex.infoCmds).find(e=>app.regex.infoCmds[e].test(o)),i?app.config[i]=!0:e?(/=.+/.test(o)||(console.error(`
8
- ${app.colors.br}${app.msgs.prefix_error}: Arg [--${o.replace(/-/g,"")}] ${app.msgs.error_noEqual}.`+app.colors.nc),l.helpCmdAndDocURL(),process.exit(1)),i=o.split("=")[1],app.config[e]=parseInt(i)||i):s||(console.error(`
9
- ${app.colors.br}${app.msgs.prefix_error}: Arg [${o}] ${app.msgs.error_notRecognized}.`+app.colors.nc),console.info(`
10
- ${app.colors.by}${app.msgs.info_validArgs}.`+app.colors.nc),l.help(["paramOptions","flags","infoCmds"]),process.exit(1)))}),process.argv.some(e=>app.regex.infoCmds.help.test(e)))l.help();else if(process.argv.some(e=>app.regex.infoCmds.version.test(e)))l.version();else{let[n="",a=""]=process.argv.slice(2).filter(e=>!e.startsWith("-")).map(e=>e.replace(/^\/*/,"")),o=t.resolve(process.cwd(),n);n&&!c.existsSync(o)&&(g=o+".js",c.existsSync(g)?o=g:(console.error(`
11
- ${app.colors.br}${app.msgs.prefix_error}: `+app.msgs.error_firstArgNotExist+"."+`
12
- ${o} ${app.msgs.error_doesNotExist}.`+app.colors.nc),console.info(`
13
- ${app.colors.bg}${app.msgs.info_exampleValidCmd}: `+`
14
- » minify-js . output.min.js`+app.colors.nc),l.helpCmdAndDocURL(),process.exit(1)));var r,g=o.endsWith(".js")&&!c.statSync(o).isDirectory()?[o]:p.findJS(o,{recursive:!app.config.noRecursion,verbose:!app.config.quietMode,ignores:(app.config.ignores?.split(",")??[]).map(e=>e.trim())});if(app.config.dryRun)g.length?(console.info(`
15
- ${app.colors.by}${app.msgs.info_filesToBeMinned}:`+app.colors.nc),g.forEach(e=>console.info(e))):console.info(`
16
- ${app.colors.by}${app.msgs.info_noFilesWillBeMinned}.`+app.colors.nc);else{let s=[],e=[];!app.config.relativeOutput&&c.statSync(o).isDirectory()?(r=p.minify(o,{verbose:!1,mangle:!app.config.noMangle,comment:app.config.comment?.replace(/\\n/g,"\n"),relativeOutput:!1,recursive:!app.config.noRecursion,dotFolders:!!app.config.includeDotFolders,dotFiles:!!app.config.includeDotFiles,rewriteImports:!!app.config.rewriteImports,ignores:app.config.ignores?app.config.ignores.split(",").map(e=>e.trim()):[]}))&&(r.error?s.push(o):e=[].concat(r)):e=g.map(e=>{var o=p.minify(e,{verbose:!app.config.quietMode,mangle:!app.config.noMangle,comment:app.config.comment?.replace(/\\n/g,"\n")});return o.error&&s.push(e),o}).filter(e=>!e.error),e?.length?(l.ifNotQuiet(`
17
- ${app.colors.bg}${app.msgs.info_minComplete}!`+app.colors.nc),l.ifNotQuiet(""+app.colors.bw+e.length+" "+app.msgs.info_file+`${1<e.length?"s":""} ${app.msgs.info_minified}.`+app.colors.nc)):l.ifNotQuiet(`
18
- ${app.colors.by}${app.msgs.info_noFilesProcessed}.`+app.colors.nc),s.length&&(l.ifNotQuiet(`
19
- ${app.colors.br}${s.length} `+app.msgs.info_file+`${1<s.length?"s":""} ${app.msgs.info_failedToMinify}:`+app.colors.nc),s.forEach(e=>l.ifNotQuiet(e))),e?.length&&(app.config.copy&&1==e?.length?(console.log(`
20
- `+app.colors.bw+e[0].code+app.colors.nc),l.ifNotQuiet(`
21
- ${app.msgs.info_copying}...`),i.writeSync(e[0].code)):(l.ifNotQuiet(`
22
- ${app.msgs.info_writing}${1<e?.length?"s":""}...`),e?.forEach(({code:e,srcPath:s,relPath:i})=>{let p,r;if(!app.config.relativeOutput&&i){let e=t.resolve(process.cwd(),a||"min"),o=t.dirname(i);p="."!=o?t.join(e,o):e,r=t.basename(s,".js")+`${app.config.noFilenameChange?"":".min"}.js`}else p=t.join(t.dirname(s),a.endsWith(".js")?t.dirname(a):a||"min"),r=`${a.endsWith(".js")&&n.endsWith(".js")?t.basename(a).replace(/(\.min)?\.js$/,""):t.basename(s,".js")}${app.config.noFilenameChange?"":".min"}.js`;let o=t.join(p,r);c.existsSync(p)||c.mkdirSync(p,{recursive:!0}),c.writeFileSync(o,e,"utf8"),l.ifNotQuiet(` ${app.colors.bg}✓${app.colors.nc} `+t.relative(process.cwd(),o))})))}}})();
7
+ (async()=>{var e,i=process.argv.slice(2);globalThis.env={debugMode:i.some(e=>/^--?debug(?:-?mode)?$/.test(e)),devMode:/[\\/]src(?:[\\/]|$)/i.test(__dirname)};let s=require("node-clipboardy"),l=require("fs"),{generateRandomLang:n,getMsgs:o,getSysLang:c}=require(`./lib/language${env.devMode?"":".min"}.js`),r=require(`./lib/github${env.devMode?"":".min"}.js`),t=require(`./lib/log${env.devMode?"":".min"}.js`),g=require(`../minify${env.devMode?"":".min"}.js`),a=require("path"),d=require(`./lib/settings${env.devMode?"":".min"}.js`);Object.assign(globalThis.cli??={},require(`../${env.devMode?"../":"./data/"}package-data.json`)),env.sysLang=env.debugMode?n({excludes:["en"]}):c(),cli.msgs=await o(env.sysLang),cli.urls.docs+="/#-command-line-usage",env.sysLang.startsWith("en")||(cli.docLocale=env.sysLang.replace("_","-").toLowerCase(),cli.docLocales=await r.getDirContents({path:"node.js/docs",type:"dir"}),cli.docLocales.includes(cli.docLocale)&&(cli.urls.docs=cli.urls.docs.replace(/\/#.*$/g,`/${cli.docLocale}#readme`)));for(e of i){if(d.controls.init.regex.test(e))return d.initConfigFile();if(d.controls.help.regex.test(e))return t.help();if(d.controls.version.regex.test(e))return t.version()}let[m="",f=""]=i.filter(e=>!e.startsWith("-")).map(e=>e.replace(/^\/*/,"")),u=a.resolve(process.cwd(),m);m&&!l.existsSync(u)&&(i=u+".js",l.existsSync(i)?u=i:(t.error(`${cli.msgs.error_firstArgNotExist}.\n${u} ${cli.msgs.error_doesNotExist}.`),t.success(cli.msgs.info_exampleValidCmd+`:
8
+ » minify-js . output.min.js`),t.helpCmdAndDocURL(),process.exit(1))),d.load();var p,i=u.endsWith(".js")&&!l.statSync(u).isDirectory()?[u]:g.findJS(u,{recursive:!cli.config.noRecursion,verbose:!cli.config.quietMode,ignores:(cli.config.ignores?.split(",")??[]).map(e=>e.trim())});if(cli.config.dryRun)i.length?(t.info(cli.msgs.info_filesToBeMinned+":"),i.forEach(e=>console.info(e))):t.info(cli.msgs.info_noFilesWillBeMinned+".");else{let n=[],e=[];!cli.config.relativeOutput&&l.statSync(u).isDirectory()?(p=g.minify(u,{verbose:!1,mangle:!cli.config.noMangle,comment:cli.config.comment?.replace(/\\n/g,"\n"),relativeOutput:!1,recursive:!cli.config.noRecursion,dotFolders:cli.config.includeDotFolders,dotFiles:cli.config.includeDotFiles,rewriteImports:cli.config.rewriteImports,ignores:cli.config.ignores?cli.config.ignores.split(",").map(e=>e.trim()):[]}))&&(p.error?n.push(u):e=[].concat(p)):e=i.map(e=>{var i=g.minify(e,{verbose:!cli.config.quietMode,mangle:!cli.config.noMangle,comment:cli.config.comment?.replace(/\\n/g,"\n")});return i.error&&n.push(e),i}).filter(e=>!e.error),cli.config.quietMode||(e?.length?(t.success(cli.msgs.info_minComplete+"!"),t.data(e.length+" "+cli.msgs.info_file+`${1==e.length?"":"s"} ${cli.msgs.info_minified}.`)):console.info(cli.msgs.info_noFilesProcessed+"."),n.length&&(t.error(n.length+" "+cli.msgs.info_file+(1==n.length?"":"s"),cli.msgs.info_failedToMinify+":"),n.forEach(e=>console.info(e)))),e?.length&&(cli.config.copy&&1==e?.length?(t.data(e[0].code),t.ifNotQuiet(`
9
+ ${cli.msgs.info_copyingToClip}...`),s.writeSync(e[0].code)):(t.ifNotQuiet(`
10
+ ${cli.msgs.info_writing}${1<e?.length?"s":""}...`),e?.forEach(({code:e,srcPath:n,relPath:s})=>{let o,c;if(!cli.config.relativeOutput&&s){let e=a.resolve(process.cwd(),f||"min"),i=a.dirname(s);o="."!=i?a.join(e,i):e,c=`${a.basename(n,".js")}${cli.config.noFilenameChange?"":".min"}.js`}else o=a.join(a.dirname(n),f.endsWith(".js")?a.dirname(f):f||"min"),c=`${f.endsWith(".js")&&m.endsWith(".js")?a.basename(f).replace(/(\.min)?\.js$/,""):a.basename(n,".js")}${cli.config.noFilenameChange?"":".min"}.js`;let i=a.join(o,c);l.mkdirSync(o,{recursive:!0}),l.writeFileSync(i,e,"utf8"),t.ifNotQuiet(` ${t.colors.bg}✓${t.colors.nc} `+a.relative(process.cwd(),i))})))}})();
@@ -1,6 +1,6 @@
1
1
  /**
2
- * © 2023–2026 Adam Lui & contributors under the MIT license.
3
- * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
- * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
2
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
3
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
5
  */
6
- module.exports={fetch(n){return new Promise((t,e)=>{var r=n.match(/^([^:]+):\/\//)[1];/^https?$/.test(r)||e(new Error(app.msgs.error_invalidURL+".")),require(r).get(n,e=>{let r="";e.on("data",e=>r+=e),e.on("end",()=>t({json:()=>JSON.parse(r)}))}).on("error",e)})},flatten(e,{key:r="message"}={}){var t,n={};for(t in e)n[t]="object"==typeof e[t]&&r in e[t]?e[t][r]:e[t];return n}};
6
+ module.exports={atomicWrite(e,r,t="utf8"){var n=require("path"),a=require("fs"),n=n.join(n.dirname(e),`.${n.basename(e)}.tmp`);a.writeFileSync(n,r,t),a.renameSync(n,e)},fetch(n){return"undefined"==typeof fetch?new Promise((t,e)=>{var r=n.match(/^([^:]+):\/\//)[1];/^https?$/.test(r)||e(new Error(cli.msgs.error_invalidURL+".")),require(r).get(n,e=>{let r="";e.on("data",e=>r+=e),e.on("end",()=>t({json:()=>JSON.parse(r)}))}).on("error",e)}):fetch(n)},flatten(e,{key:r="message"}={}){var t,n={};for(t in e)n[t]="object"==typeof e[t]&&r in e[t]?e[t][r]:e[t];return n}};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
3
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
+ */
6
+ let log=require(`./log${env.devMode?"":".min"}.js`);module.exports={async getDirContents({owner:e="adamlui",repo:t="minify.js",path:r="/",type:a="all"}){log.prefix="github.getDirContents()";try{var o=await require(`./data${env.devMode?"":".min"}.js`).fetch(`https://api.github.com/repos/${e}/${t}/contents/`+r);if(o.ok)return(await o.json()).filter(e=>"all"==a||e.type==a).map(e=>e.name);throw new Error("Failed to fetch data")}catch(e){log.error(e.message)}}};
@@ -1,6 +1,7 @@
1
1
  /**
2
- * © 2023–2026 Adam Lui & contributors under the MIT license.
3
- * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
- * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
2
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
3
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
5
  */
6
- module.exports={async getMsgs(r="en"){var e=require(`./data${env.devMode?"":".min"}.js`);let t=e.flatten(require(`../../${env.devMode?"../../_locales/en/":"data/"}messages.json`),{key:"message"});if(!r.startsWith("en")){var n=`${app.urls.jsdelivr}@${app.commitHashes.locales}/_locales/`;let s=n+`${r?r.replace("-","_"):"en"}/`+"messages.json",a=0;for(;a<3;)try{t=e.flatten(await(await e.fetch(s)).json(),{key:"message"});break}catch(e){if(3==++a)break;s=r.includes("-")&&1==a?s.replace(/([^_]*)_[^/]*(\/.*)/,"$1$2"):n+"en/messages.json"}}return t},getSysLang(){var e;if("win32"!=process.platform)return((e=process.env).LANG||e.LANGUAGE||e.LC_ALL||e.LC_MESSAGES||e.LC_NAME||"en").split(".")[0];try{return require("child_process").execSync("(Get-Culture).TwoLetterISOLanguageName",{shell:"powershell",encoding:"utf-8"}).trim()}catch(e){return console.error("ERROR loading system language:",e.message),"en"}}};
6
+ let data=require(`./data${env.devMode?"":".min"}.js`),log=require(`./log${env.devMode?"":".min"}.js`);module.exports={generateRandomLang({includes:e=[],excludes:r=[]}={}){log.prefix="generateRandomLang()";let t=require("fs"),a=require("path"),s=e.length?e:(()=>{var e=a.join(__dirname,"..",".cache"),r=a.join(e,"locales.json");if(t.existsSync(r))try{return JSON.parse(t.readFileSync(r,"utf8"))}catch(e){}var s=a.resolve(process.cwd(),"_locales");return t.existsSync(s)?(s=t.readdirSync(s,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).filter(e=>/^[a-z]{2}(?:_[A-Z]{2})?$/.test(e)),t.mkdirSync(e,{recursive:!0}),data.atomicWrite(r,JSON.stringify(s,null,2)),s):["en"]})(),n=new Set(r),i="en";return(s=s.filter(e=>!n.has(e))).length&&(i=s[Math.floor(Math.random()*s.length)]),log.debug(`Random language: ${i}
7
+ `),i},async getMsgs(s="en"){log.prefix="getMsgs()";let e=data.flatten(require(`../../${env.devMode?"../../_locales/en/":"data/"}messages.json`));if(!s.startsWith("en")){var t=`${cli.urls.jsdelivr}@${cli.commitHashes.locales}/_locales/`;let r=t+s.replace("-","_")+"/messages.json";for(;(this.msgFetchesTried||=0)<3;)try{e=data.flatten(await(await data.fetch(r)).json()),this.msgFetchesTried=0;break}catch(e){if(this.msgFetchesTried++,3<=this.msgFetchesTried)break;log.debug(r=s.includes("-")&&1==this.msgFetchesTried?r.replace(/([^_]*)_[^/]*(\/.*)/,"$1$2"):t+"en/messages.json")}}return e},getSysLang(){var e;if(log.prefix="getSysLang()","win32"!=process.platform)return((e=process.env).LANG||e.LANGUAGE||e.LC_ALL||e.LC_MESSAGES||e.LC_NAME||"en").split(".")[0];try{return require("child_process").execSync("(Get-Culture).TwoLetterISOLanguageName",{shell:"powershell",encoding:"utf-8"}).trim()}catch(e){return log.error("ERROR loading system language:",e.message),"en"}}};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
3
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
+ */
6
+ module.exports={colors:{nc:"",br:"",by:"",bo:"",bg:"",bw:"",blk:"",tlBG:""},configURL(){this.info(`
7
+ ${cli.msgs.info_exampleValidConfigFile}: `+cli.urls.config)},configURLandExit(...s){this.error(...s),this.configURL(),process.exit(1)},data(s){console.log(`
8
+ `+this.colors.bw+s+this.colors.nc)},debug(s){env.debugMode&&console.log(this.prefix+" » "+s)},error(...s){console.error(`
9
+ ${this.colors.br}${this.prefix} » ${cli.msgs.prefix_error}:`,...s,this.colors.nc)},errorAndExit(...s){this.error(...s),this.helpCmdAndDocURL(),process.exit(1)},ifNotQuiet(s){cli.config.quietMode||console.info(s)},info(s){console.info(`
10
+ `+this.colors.by+s+this.colors.nc)},tip(s){console.info(""+this.colors.by+cli.msgs.prefix_tip+": "+s+this.colors.nc)},success(s){console.log(`
11
+ `+this.colors.bg+s+this.colors.nc)},warn(...s){console.warn(`
12
+ ${this.colors.bo}${this.prefix}${cli.msgs.prefix_warning}:`,...s,this.colors.nc)},help(s=["header","usage","pathArgs","flags","params","cmds"]){cli.prefix=""+this.colors.tlBG+this.colors.blk+` ${cli.name.replace(/^@[^/]+\//,"")} ${this.colors.nc} `;let o={header:[`
13
+ ├ ${cli.prefix}${cli.msgs.appCopyright}.`,""+cli.prefix+cli.msgs.prefix_source+": "+cli.urls.src],usage:[`
14
+ ${this.colors.bw}o ${cli.msgs.helpSection_usage}:`+this.colors.nc,` ${this.colors.bw}» `+this.colors.bg+cli.cmdFormat+this.colors.nc],pathArgs:[`
15
+ ${this.colors.bw}o ${cli.msgs.helpSection_pathArgs}:`+this.colors.nc,` [inputPath] ${cli.msgs.inputPathDesc_main}, ${cli.msgs.inputPathDesc_extra}.`,` [outputPath] ${cli.msgs.outputPathDesc_main}, ${cli.msgs.outputPathDesc_extra}.`],flags:[`
16
+ ${this.colors.bw}o ${cli.msgs.helpSection_flags}:`+this.colors.nc,` -n, --dry-run ${cli.msgs.optionDesc_dryRun}.`,` -d, --include-dotfolders ${cli.msgs.optionDesc_dotfolders}.`,` -D, --include-dotfiles ${cli.msgs.optionDesc_dotfiles}.`,` -R, --no-recursion ${cli.msgs.optionDesc_noRecursion}.`,` -M, --no-mangle ${cli.msgs.optionDesc_noMangle}.`," -X, --no-filename-change "+cli.msgs.optionDesc_noFilenameChange,` -i, --rewrite-imports ${cli.msgs.optionDesc_rewriteImports}.`,` -c, --copy ${cli.msgs.optionDesc_copy}.`,` -r, --relative-output ${cli.msgs.optionDesc_relativeOutput}.`,` -q, --quiet ${cli.msgs.optionDesc_quiet}.`],params:[`
17
+ ${this.colors.bw}o ${cli.msgs.helpSection_params}:`+this.colors.nc,`--ignores="dir/,file1.js,file2.js" ${cli.msgs.optionDesc_ignores}.`,`--comment="comment" ${cli.msgs.optionDesc_commentMain}.`+` ${cli.msgs.optionDesc_commentExtra}.`,` --config="path/to/file" ${cli.msgs.optionDesc_config}.`],cmds:[`
18
+ ${this.colors.bw}o ${cli.msgs.helpSection_cmds}:`+this.colors.nc,` --init ${cli.msgs.optionDesc_init}.`,` -h, --help ${cli.msgs.optionDesc_help}.`,` -v, --version ${cli.msgs.optionDesc_version}.`]};s.forEach(r=>o[r]?.forEach(o=>{{var l=/header|usage/.test(r)?1:37;let i=process.stdout.columns||80,s=o.match(/\S+|\s+/g),c=[],e="";s.forEach(s=>{var o=i-(c.length?l:0);e.length+"| ".length+s.length>o&&(c.push(c.length?e.trimStart():e),e=""),e+=s}),c.push(c.length?e.trimStart():e),c.forEach((s,o)=>console.info("| "+(0==o?s:" ".repeat(l)+s)))}})),console.info(`
19
+ ${cli.msgs.info_moreHelp}, ${cli.msgs.info_visit}: `+this.colors.bw+cli.urls.docs+this.colors.nc)},helpCmdAndDocURL(){console.info(`
20
+ ${cli.msgs.info_moreHelp}, ${cli.msgs.info_type} ${cli.name.split("/")[1]} --help' ${cli.msgs.info_or} ${cli.msgs.info_visit}
21
+ `+this.colors.bw+cli.urls.docs+this.colors.nc)},version(){var s=require("child_process").execSync(`npm view ${JSON.stringify(cli.name)} version`).toString().trim()||"none";let o="none";try{var i=require("path").resolve(process.cwd(),"node_modules",cli.name,"package.json");require("fs").existsSync(i)&&(o=require(i).version||"none")}catch(s){this.error(cli.msgs.error_readingLocalPkgVer+":",s.message)}console.info(`
22
+ ${cli.msgs.prefix_globalVer}: ${s}
23
+ ${cli.msgs.prefix_localVer}: `+o)}};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
3
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
+ */
6
+ let fs=require("fs"),log=require(`./log${env.devMode?"":".min"}.js`),path=require("path");(globalThis.cli??={}).config={},module.exports={configFilename:"minify.config.mjs",controls:{dryRun:{type:"flag",regex:/^--?(?:n|dry-?run)$/},includeDotFolders:{type:"flag",regex:/^--?(?:dd?|(?:include-?)?dot-?(?:folder|dir(?:ector(?:y|ie))?)s?=?(?:true|1)?)$/},includeDotFiles:{type:"flag",regex:/^--?(?:df|D|(?:include-?)?dot-?files?=?(?:true|1)?)$/},noRecursion:{type:"flag",regex:/^--?(?:R|(?:disable|no)-?recursi(?:on|ve)|recursi(?:on|ve)=(?:false|0))$/},noMangle:{type:"flag",regex:/^--?(?:M|(?:disable|no)-?mangle|mangle=(?:false|0))$/},noFilenameChange:{type:"flag",regex:/^--?(?:X|(?:disable|no)-?(?:file)?name-?change|(?:file)?name-?change=(?:false|0))$/},rewriteImports:{type:"flag",regex:/^--?(?:i|rewrite-?imports?=?(?:true|1)?)$/},copy:{type:"flag",regex:/^--?c(?:opy)?$/},relativeOutput:{type:"flag",regex:/^--?(?:r|relative-?output?=?(?:true|1)?)$/},quietMode:{type:"flag",regex:/^--?q(?:uiet)?(?:-?mode)?$/},ignores:{type:"param",regex:/^--?(?:ignores?|(?:ignore|skip|exclude)(?:d?-?files?)?)(?:=.*|$)/},comment:{type:"param",regex:/^--?comments?(?:=.*|$)/},config:{type:"param",regex:/^--?config(?:=.*|$)/},init:{type:"cmd",regex:/^-{0,2}init$/},help:{type:"cmd",regex:/^--?h(?:elp)?$/},version:{type:"cmd",regex:/^--?ve?r?s?i?o?n?$/}},async initConfigFile(i=this.configFilename){log.prefix="initConfigFile()";var e=path.resolve(process.cwd(),i);if(fs.existsSync(e))return log.warn(cli.msgs.warn_configFileExists+":",e);var r=path.resolve(__dirname,"../../"+(env.devMode?"../":"./data/")+i);if(fs.existsSync(r))fs.copyFileSync(r,e);else{r=require(`./data${env.devMode?"":".min"}.js`),i=cli.urls.jsdelivr+"/node.js/"+i;log.data(cli.msgs.info_fetchingRemoteConfigFrom+` ${i}...`);try{var o=await r.fetch(i);if(!o.ok)return log.warn(`${cli.msgs.warn_remoteConfigNotFound}: ${i} (${o.status})`);r.atomicWrite(e,await o.text())}catch(e){return log.warn(cli.msgs.warn_remoteConfigFailed+`: ${i} `+e.message)}}log.success(cli.msgs.info_configFileCreated+`: ${e}
7
+ `),log.tip(cli.msgs.tip_editToSetDefaults+"."),log.tip(cli.msgs.tip_cliArgsPrioritized+".")},load({args:e=process.argv.slice(2),ctrlKeys:t=Object.keys(this.controls)}={}){log.prefix="settings.load()",t.forEach(e=>{var i=this.controls[e];i.mode||"cmd"==i.type||(cli.config[e]??=i.defaultVal??("flag"!=i.type&&""))});let i;var r=e.find(e=>this.controls.config.regex.test(e));if(r){/=/.test(r)||log.errorAndExit(`[${r}] `+cli.msgs.error_mustIncludePath);r=r.split("=")[1];i=path.isAbsolute(r)?r:path.resolve(process.cwd(),r),fs.existsSync(i)||log.configURLandExit(cli.msgs.error_configFileNotFound+":",i)}else for(var o of["mjs","cjs","js"]){o=path.resolve(process.cwd(),this.configFilename.replace(/\.[^.]+$/,"."+o));if(fs.existsSync(o)){i=o;break}}if(i)try{var s=require(i),l=s?.default??s;l&&"object"==typeof l||log.configURLandExit(cli.msgs.error_invalidConfigFile+"."),Object.assign(cli.config,l)}catch(e){log.configURLandExit(cli.msgs.error_failedToLoadConfigFile+":",i,`
8
+ `+e.message)}return e.forEach(i=>{if(!/^[^-]|--?(?:config|debug)/.test(i)){var r=t.find(e=>this.controls[e]?.regex?.test(i)),o=(r||log.errorAndExit(`[${i}] ${cli.msgs.error_notRecognized}.`),this.controls[r]);if("cmd"!=o.type){let e="param"!=o.type||i.split("=")[1]?.trim();o.mode?cli.config.mode=r.replace(/mode$/i,"").toLowerCase():((o=o.parser)&&(e=o(e),isNaN(e)||e<1)&&log.errorAndExit(`[${r}] ${cli.msgs.error_nonPositiveNum}.`),cli.config[r]=e)}}}),cli.config}};
@@ -2,31 +2,48 @@
2
2
  "appName": { "message": "minify.js" },
3
3
  "appCopyright": { "message": "© 2024–2026 Adam Lui & contributors under the MIT license" },
4
4
  "prefix_error": { "message": "ERROR" },
5
+ "prefix_tip": { "message": "TIP" },
6
+ "prefix_warning": { "message": "WARNING" },
5
7
  "prefix_globalVer": { "message": "Global version" },
6
8
  "prefix_localVer": { "message": "Local version" },
7
9
  "prefix_source": { "message": "Source" },
10
+ "error_readingLocalPkgVer": { "message": "Error reading local package version" },
8
11
  "error_notRecognized": { "message": "not recognized" },
12
+ "error_nonPositiveNum": { "message": "argument can only be > 0" },
9
13
  "error_invalidURL": { "message": "Invalid URL" },
14
+ "error_invalidConfigFile": { "message": "Config file must export an object" },
15
+ "error_configFileNotFound": { "message": "Config file not found" },
16
+ "error_failedToLoadConfigFile": { "message": "Failed to load config file" },
17
+ "error_mustIncludePath": { "message": "must include =path" },
18
+ "warn_configFileExists": { "message": "Config file already exists" },
19
+ "info_exampleValidConfigFile": { "message": "Example valid config file" },
10
20
  "error_firstArgNotExist": { "message": "First argument can only be an existing file or directory" },
11
21
  "error_doesNotExist": { "message": "does not exist" },
12
- "info_validArgs": { "message": "Valid arguments are below" },
13
22
  "info_exampleValidCmd": { "message": "Example valid command" },
14
23
  "info_filesToBeMinned": { "message": "JS files to be minified" },
15
24
  "info_noFilesWillBeMinned": { "message": "No JS files will be minified" },
16
- "info_copying": { "message": "Copying to clipboard" },
25
+ "info_copyingToClip": { "message": "Copying to clipboard" },
17
26
  "info_writing": { "message": "Writing to file" },
18
27
  "info_minComplete": { "message": "Minification complete" },
19
28
  "info_file": { "message": "file" },
20
- "info_mininified": { "message": "minified" },
29
+ "info_minified": { "message": "minified" },
21
30
  "info_noFilesProcessed": { "message": "No unminified JavaScript files processed" },
22
31
  "info_failedToMinify": { "message": "failed to minify" },
23
32
  "info_moreHelp": { "message": "For more help" },
33
+ "info_type": { "message": "type" },
34
+ "info_or": { "message": "or" },
24
35
  "info_visit": { "message": "visit" },
36
+ "info_configFileCreated": { "message": "Config file created" },
37
+ "info_fetchingRemoteConfigFrom": { "message": "Fetching remote config file from" },
38
+ "warn_remoteConfigNotFound": { "message": "Remote config file not found" },
39
+ "warn_remoteConfigFailed": { "message": "Failed to fetch remote config file" },
40
+ "tip_editToSetDefaults": { "message": "Edit this file to customize defaults" },
41
+ "tip_cliArgsPrioritized": { "message": "CLI arguments always override these values" },
25
42
  "helpSection_usage": { "message": "Usage" },
26
43
  "helpSection_pathArgs": { "message": "Path arguments" },
27
44
  "helpSection_flags": { "message": "Boolean options" },
28
- "helpSection_paramOptions": { "message": "Parameter options" },
29
- "helpSection_infoCmds": { "message": "Info commands" },
45
+ "helpSection_params": { "message": "Parameter options" },
46
+ "helpSection_cmds": { "message": "Commands" },
30
47
  "inputPathDesc_main": { "message": "Path to JS file or directory containing JavaScript files to be minified" },
31
48
  "inputPathDesc_extra": { "message": "relative to the current working directory" },
32
49
  "outputPathDesc_main": { "message": "Path to file or directory where minified files will be stored" },
@@ -44,6 +61,8 @@
44
61
  "optionDesc_ignores": { "message": "Files/directories to exclude from minification" },
45
62
  "optionDesc_commentMain": { "message": "Prepend header comment to minified code" },
46
63
  "optionDesc_commentExtra": { "message": "Separate by line using '\\n'" },
64
+ "optionDesc_config": { "message": "Load custom config file" },
65
+ "optionDesc_init": { "message": "Create config file (in project root)" },
47
66
  "optionDesc_help": { "message": "Display help screen" },
48
67
  "optionDesc_version": { "message": "Show version number" }
49
68
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * minify.config.mjs
3
+ *
4
+ * Optional config file for the minify-js CLI.
5
+ * Copy this file to your project root to set default options.
6
+ * CLI arguments always override these values.
7
+ *
8
+ * Docs: https://github.com/adamlui/minify.js/tree/main/node.js/#-command-line-usage
9
+ */
10
+
11
+ export default {
12
+
13
+ // Info options
14
+ dryRun: false, // don't actually minify the file(s), just show if they will be processed
15
+ quietMode: false, // suppress all logging except errors
16
+
17
+ // Input options
18
+ includeDotFolders: false, // include dotfolders in file search
19
+ includeDotFiles: false, // include dotfiles in file search
20
+ noRecursion: false, // disable recursive file searching
21
+ ignores: '', // files/dirs to exclude from minification
22
+
23
+ // Output options
24
+ noMangle: false, // disable mangling names
25
+ noFilenameChange: false, // disable changing file extension to .min.js
26
+ rewriteImports: false, // update import paths from .js to .min.js
27
+ copy: false, // copy minified code to clipboard instead of write to file if single file processed
28
+ relativeOutput: false, // output files relative to each src file instead of to input root
29
+ comment: '' // header comment to prepend to minified code
30
+ }
@@ -5,6 +5,7 @@
5
5
  "copyrightYear": "2024–2026",
6
6
  "cmdFormat": "minify-js [inputPath] [outputPath] [options]",
7
7
  "urls": {
8
+ "config": "https://github.com/adamlui/minify.js/blob/main/node.js/minify.config.mjs",
8
9
  "docs": "https://github.com/adamlui/minify.js/tree/main/node.js/docs",
9
10
  "github": "https://github.com/adamlui/minify.js",
10
11
  "jsdelivr": "https://cdn.jsdelivr.net/gh/adamlui/minify.js",
@@ -12,6 +13,6 @@
12
13
  "src": "https://github.com/adamlui/minify.js/tree/main/node.js/src"
13
14
  },
14
15
  "commitHashes": {
15
- "locales": "589eb64"
16
+ "locales": "ceb5039"
16
17
  }
17
18
  }
@@ -1,9 +1,9 @@
1
1
  /**
2
- * © 2023–2026 Adam Lui & contributors under the MIT license.
3
- * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
- * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
2
+ * © 2024–2026 Adam Lui & contributors under the MIT license.
3
+ * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
+ * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
5
  */
6
- let fs=require("fs"),path=require("path"),uglifyJS=require("uglify-js");function findJS(i,s={}){var e="https://github.com/adamlui/minify.js/tree/main/node.js/docs/#findjssearchdir-options",o={recursive:!0,verbose:!0,dotFolders:!1,dotFiles:!1,ignores:[]};if(log.prefix="findJS()","string"!=typeof i)return log.error("1st arg <searchDir> must be a string."),log.helpURL(e);var r=path.resolve(process.cwd(),i);if(!fs.existsSync(r))return log.error("1st arg <searchDir> must be an existing directory."),log.error(r+" does not exist."),log.helpURL(e);if(validateOptions({options:s,defaultOptions:o,helpURL:e,exampleCall:"findJS('assets/js', { verbose: false, dotFoldes: true })"})){(s={...o,...s}).ignoreFiles&&(s.ignores=[...s.ignores,...s.ignoreFiles]);let e=fs.readdirSync(i),r=[];return s.verbose&&!s.isRecursing&&log.info("Searching for unminified JS files..."),e.forEach(e=>{let o=path.resolve(i,e);s.ignores.some(r=>r.endsWith("/")?o.split(path.sep).some(e=>e==r.replace(/\/$/,"")):e==r)?s.verbose&&log.info(`** ${e} ignored`):fs.statSync(o).isDirectory()&&"node_modules"!=e&&s.recursive&&(s.dotFolders||!e.startsWith("."))?r.push(...findJS(o,{...s,isRecursing:!0})):!/\.js(?<!\.min\.js)$/.test(e)||!s.dotFiles&&e.startsWith(".")||r.push(o)}),s.verbose&&!s.isRecursing&&(log.info("Search complete!",`${r.length||"No"} file${1==r.length?"":"s"} found.`),"minify"!=findJS.caller?.name)&&"undefined"!=typeof window&&log.info("Check returned array."),s.isRecursing||r.length?r:[]}}function minify(s,n={}){var r="https://github.com/adamlui/minify.js/tree/main/node.js/docs/#minifyinput-options",e={recursive:!0,verbose:!0,dotFolders:!1,dotFiles:!1,mangle:!0,rewriteImports:!1,relativeOutput:!1,ignores:[],comment:""};if(log.prefix="minify()","string"!=typeof s)return log.error("1st arg <input> must be a string."),log.helpURL(r);if(validateOptions({options:n,defaultOptions:e,helpURL:r,exampleCall:"minify('assets/js', { recursive: false, mangle: false })"})){(n={...e,...n}).ignoreFiles&&(n.ignores=[...n.ignores,...n.ignoreFiles]);let i={mangle:!!n.mangle&&{toplevel:!1}};try{var o,t=fs.openSync(s,fs.constants.O_RDONLY),l=fs.fstatSync(t);if(l.isFile()){if(!/\.[cm]?jsx?$/i.test(s))return o=new Error(s+" is not a JavaScript file (.js, .mjs, .cjs, .jsx)"),log.error(o.message),fs.closeSync(t),{code:"",srcPath:path.resolve(process.cwd(),s),error:o};n.verbose&&log.info(`** Minifying ${s}...`);var a=Buffer.alloc(l.size),c=(fs.readSync(t,a,0,l.size,0),fs.closeSync(t),uglifyJS.minify(a.toString("utf8"),i));return n.comment&&(c.code=prependComment(c.code,n.comment)),c.error?log.error(c.error.message):n.verbose&&"undefined"!=typeof window&&log.info("Minification complete! Check returned object."),{code:c.code,srcPath:path.resolve(process.cwd(),s),error:c.error}}fs.closeSync(t);var f=findJS(s,n)?.map(e=>{n.verbose&&log.info(`** Minifying ${e}...`);var r=fs.readFileSync(e,"utf8"),r=uglifyJS.minify(r,i),o=n.relativeOutput?void 0:path.relative(path.resolve(process.cwd(),s),e);return n.comment&&(r.code=prependComment(r.code,n.comment)),r.error&&log.error(r.error.message),{code:r.code,srcPath:e,relPath:o,error:r.error}}).filter(e=>!e.error);if(n.verbose&&(f.length&&"undefined"!=typeof window?log.info("Minification complete! Check returned object."):log.info("No unminified JavaScript files processed.")),n.rewriteImports&&f&&1<f.length){n.verbose&&log.info("** Rewriting import paths...");let e=f.map(e=>path.basename(e.srcPath,".js"));f.forEach(i=>e.forEach(e=>{var r=new RegExp(`(\\./?)?\\b${e}\\.js(['"])`,"g"),o=i.code;i.code=i.code.replace(r,`$1${e}.min.js$2`),o!=i.code&&n.verbose&&log.info(`Updated ${e}.js in `+path.basename(i.srcPath))})),n.verbose&&log.info("Import paths rewritten.")}return f}catch(e){if("ENOENT"==e.code)return n.verbose&&!process.argv.some(e=>e.includes("gulp"))&&log.info("** Minifying passed source code..."),r=uglifyJS.minify(s,i),n.comment&&(r.code=prependComment(r.code,n.comment)),r.error?log.error(r.error.message):n.verbose&&!process.argv.some(e=>e.includes("gulp"))&&log.info("Minification complete! Check returned object."),{code:r.code,srcPath:void 0,error:r.error};throw e}}}function prependComment(e,r){var o=e.match(/^#!.*\n/);let i="";return o&&(i=o[0],e=e.slice(i.length)),`${i}/**
6
+ let fs=require("fs"),path=require("path"),uglifyJS=require("uglify-js");function findJS(i,s={}){var e="https://github.com/adamlui/minify.js/tree/main/node.js/docs/#findjssearchdir-options",o={recursive:!0,verbose:!0,dotFolders:!1,dotFiles:!1,ignores:[]};if(log.prefix="findJS()","string"!=typeof i)return log.error("1st arg <searchDir> must be a string."),log.helpURL(e);var r=path.resolve(process.cwd(),i);if(!fs.existsSync(r))return log.error("1st arg <searchDir> must be an existing directory."),log.error(r+" does not exist."),log.helpURL(e);if(validateOptions({options:s,defaultOptions:o,helpURL:e,exampleCall:"findJS('assets/js', { verbose: false, dotFoldes: true })"})){(s={...o,...s}).ignoreFiles&&(s.ignores=[...s.ignores,...s.ignoreFiles]);let e=fs.readdirSync(i),r=[];return s.verbose&&!s.isRecursing&&log.info("Searching for unminified JS files..."),e.forEach(e=>{let o=path.resolve(i,e);s.ignores.some(r=>r.endsWith("/")?o.split(path.sep).some(e=>e==r.replace(/\/$/,"")):e==r)?s.verbose&&log.info(`** ${e} ignored`):fs.statSync(o).isDirectory()&&"node_modules"!=e&&s.recursive&&(s.dotFolders||!e.startsWith("."))?r.push(...findJS(o,{...s,isRecursing:!0})):!/\.js(?<!\.min\.js)$/.test(e)||!s.dotFiles&&e.startsWith(".")||r.push(o)}),s.verbose&&!s.isRecursing&&(log.info("Search complete!",`${r.length||"No"} file${1==r.length?"":"s"} found.`),"minify"!=findJS.caller?.name)&&"undefined"!=typeof window&&log.info("Check returned array."),s.isRecursing||r.length?r:[]}}function minify(s,n={}){var r="https://github.com/adamlui/minify.js/tree/main/node.js/docs/#minifyinput-options",o={recursive:!0,verbose:!0,dotFolders:!1,dotFiles:!1,mangle:!0,rewriteImports:!1,relativeOutput:!1,ignores:[],comment:""};if(log.prefix="minify()","string"!=typeof s)return log.error("1st arg <input> must be a string."),log.helpURL(r);if(validateOptions({options:n,defaultOptions:o,helpURL:r,exampleCall:"minify('assets/js', { recursive: false, mangle: false })"})){(n={...o,...n}).ignoreFiles&&(n.ignores=[...n.ignores,...n.ignoreFiles]);let i={mangle:!!n.mangle&&{toplevel:!1}};try{var e,t=fs.openSync(s,fs.constants.O_RDONLY),l=fs.fstatSync(t);if(l.isFile()){if(!/\.[cm]?jsx?$/i.test(s))return e=new Error(s+" is not a JavaScript file (.js, .mjs, .cjs, .jsx)"),log.error(e.message),fs.closeSync(t),{code:"",srcPath:path.resolve(process.cwd(),s),error:e};n.verbose&&log.info(`** Minifying ${s}...`);var a=Buffer.alloc(l.size),c=(fs.readSync(t,a,0,l.size,0),fs.closeSync(t),uglifyJS.minify(a.toString("utf8"),i));return n.comment&&(c.code=prependComment(c.code,n.comment)),c.error?log.error(c.error.message):n.verbose&&"undefined"!=typeof window&&log.info("Minification complete! Check returned object."),{code:c.code,srcPath:path.resolve(process.cwd(),s),error:c.error}}fs.closeSync(t);var f=findJS(s,n)?.map(e=>{n.verbose&&log.info(`** Minifying ${e}...`);var r=fs.readFileSync(e,"utf8"),r=uglifyJS.minify(r,i),o=n.relativeOutput?void 0:path.relative(path.resolve(process.cwd(),s),e);return n.comment&&(r.code=prependComment(r.code,n.comment)),r.error&&log.error(r.error.message),{code:r.code,srcPath:e,relPath:o,error:r.error}}).filter(e=>!e.error);if(n.verbose&&(f.length&&"undefined"!=typeof window?log.info("Minification complete! Check returned object."):log.info("No unminified JavaScript files processed.")),n.rewriteImports&&f&&1<f.length){n.verbose&&log.info("** Rewriting import paths...");let e=f.map(e=>path.basename(e.srcPath,".js"));f.forEach(i=>e.forEach(e=>{var r=new RegExp(`(\\./?)?\\b${e}\\.js(['"])`,"g"),o=i.code;i.code=i.code.replace(r,`$1${e}.min.js$2`),o!=i.code&&n.verbose&&log.info(`Updated ${e}.js in `+path.basename(i.srcPath))})),n.verbose&&log.info("Import paths rewritten.")}return f}catch(e){if("ENOENT"==e.code)return r=process.argv.some(e=>e.includes("gulp")),n.verbose&&!r&&log.info("** Minifying passed source code..."),o=uglifyJS.minify(s,i),n.comment&&(o.code=prependComment(o.code,n.comment)),o.error?log.error(o.error.message):n.verbose&&!r&&log.info("Minification complete! Check returned object."),{code:o.code,srcPath:void 0,error:o.error};throw e}}}function prependComment(e,r){let o="";var i=e.match(/^#!.*\n/);return i&&(o=i[0],e=e.slice(o.length)),`${o}/**
7
7
  ${r.split("\n").map(e=>" * "+e).join("\n")}
8
8
  */
9
- `+e}function validateOptions({options:e,defaultOptions:r,helpURL:o,exampleCall:i}){var s,n,t=Object.keys(r).filter(e=>"boolean"==typeof r[e]),l=Object.keys(r).filter(e=>Number.isInteger(r[e]));if("object"!=typeof e)return s=i.split(",").findIndex(e=>e.trim().startsWith("{"))+1,s+=["st","nd","rd"][s-1]||"th",log.error(`${"0th"==s?"[O":s+" arg [o"}ptions] can only be an object of key/vals.`),log.info("Example valid call:",i),log.validOptions(r),log.helpURL(o),!1;for(n in e)if("isRecursing"!=n&&Object.prototype.hasOwnProperty.call(r,n)){if(t.includes(n)&&"boolean"!=typeof e[n])return log.error(`[${n}] option can only be \`true\` or \`false\`.`),log.helpURL(o),!1;if(l.includes(n)&&(e[n]=parseInt(e[n],10),isNaN(e[n])||e[n]<1))return log.error(`[${n}] option can only be an integer > 0.`),log.helpURL(o),!1}return!0}Object.assign(globalThis.app??={},require(`${__dirname.match(/[\\/]src/)?"../":"./data/"}app.json`)),app.aliases={minify:["build","Build","compile","Compile","compress","Compress","Minify"],findJS:["find","Find","findjs","findJs","Findjs","FindJs","FindJS","search","Search"]};let log={prefix:app.name,error(...e){console.error(this.prefix+" » ERROR:",...e)},helpURL(e=app.urls?.docs){this.info("For more help, please visit",e)},info(...e){console.info(this.prefix+" »",...e)},validOptions(e){var r=Object.keys(e).join(", "),e=JSON.stringify(e,void 0,2).replace(/"([^"]+)":/g,"$1:").replace(/"/g,"'").replace(/\n\s*/g," ");this.info(`Valid options: [${r}]`),this.info("If omitted, default settings are: "+e)}};module.exports={minify:minify,findJS:findJS};for(let r in app.aliases)app.aliases[r].forEach(e=>module.exports[e]=module.exports[r]);
9
+ `+e}function validateOptions({options:e,defaultOptions:r,helpURL:o,exampleCall:i}){var s,n,t=Object.keys(r).filter(e=>"boolean"==typeof r[e]),l=Object.keys(r).filter(e=>Number.isInteger(r[e]));if("object"!=typeof e)return s=i.split(",").findIndex(e=>e.trim().startsWith("{"))+1,s+=["st","nd","rd"][s-1]||"th",log.error(`${"0th"==s?"[O":s+" arg [o"}ptions] can only be an object of key/vals.`),log.info("Example valid call:",i),log.validOptions(r),log.helpURL(o),!1;for(n in e)if("isRecursing"!=n&&Object.prototype.hasOwnProperty.call(r,n)){if(t.includes(n)&&"boolean"!=typeof e[n])return log.error(`[${n}] option can only be \`true\` or \`false\`.`),log.helpURL(o),!1;if(l.includes(n)&&(e[n]=parseInt(e[n],10),isNaN(e[n])||e[n]<1))return log.error(`[${n}] option can only be an integer > 0.`),log.helpURL(o),!1}return!0}Object.assign(globalThis.api??={},require(`${/[\\/]src(?:[\\/]|$)/i.test(__dirname)?"../":"./data/"}package-data.json`)),api.aliases={minify:["build","Build","compile","Compile","compress","Compress","Minify"],findJS:["find","Find","findjs","findJs","Findjs","FindJs","FindJS","search","Search"]};let log={prefix:api.name,error(...e){console.error(this.prefix+" » ERROR:",...e)},helpURL(e=api.urls?.docs){this.info("For more help, please visit",e)},info(...e){console.info(this.prefix+" »",...e)},validOptions(e){var r=Object.keys(e).join(", "),e=JSON.stringify(e,null,2).replace(/"([^"]+)":/g,"$1:").replace(/"/g,"'").replace(/\n\s*/g," ");this.info(`Valid options: [${r}]`),this.info("If omitted, default settings are: "+e)}};module.exports={minify:minify,findJS:findJS};for(let r in api.aliases)api.aliases[r].forEach(e=>module.exports[e]??=module.exports[r]);
package/docs/README.md CHANGED
@@ -21,14 +21,14 @@
21
21
 
22
22
  # </> minify.js
23
23
 
24
- ### Recursively minify all JavaScript files.
24
+ ### Recursively minify all JavaScript files
25
25
 
26
26
  <a href="https://www.npmjs.com/package/@adamlui/minify.js">
27
27
  <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>
28
28
  <a href="#%EF%B8%8F-mit-license">
29
29
  <img height=31 src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
30
- <a href="https://github.com/adamlui/minify.js/releases/tag/node-v2.1.4">
31
- <img height=31 src="https://img.shields.io/badge/Latest_Build-2.1.4-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
30
+ <a href="https://github.com/adamlui/minify.js/releases/tag/node-v2.2.1">
31
+ <img height=31 src="https://img.shields.io/badge/Latest_Build-2.2.1-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
32
32
  <a href="https://www.npmjs.com/package/@adamlui/minify.js?activeTab=code">
33
33
  <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>
34
34
  <a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_minify.js:node.js/src/minify.js">
@@ -155,12 +155,41 @@ Parameter options:
155
155
  --ignores="dir/,file1.js,file2.js" Files/directories to exclude from minification.
156
156
  --comment="comment" Prepend header comment to minified code.
157
157
  Separate by line using '\n'.
158
+ --config="path/to/file" Load custom config file.
158
159
 
159
- Info commands:
160
+ Commands:
161
+ --init Create config file (in project root).
160
162
  -h, --help Display help screen.
161
163
  -v, --version Show version number.
162
164
  ```
163
165
 
166
+ #
167
+
168
+ ### Configuration file
169
+
170
+ **minify.js** can be customized using a `minify.config.mjs` or `minify.config.js` placed in your project root.
171
+
172
+ Example defaults:
173
+
174
+ ```js
175
+ export default {
176
+ dryRun: false, // don't actually minify the file(s), just show if they will be processed
177
+ includeDotFolders: false, // include dotfolders in file search
178
+ includeDotFiles: false, // include dotfiles in file search
179
+ noRecursion: false, // disable recursive file searching
180
+ noMangle: false, // disable mangling names
181
+ noFilenameChange: false, // disable changing file extension to .min.js
182
+ rewriteImports: false, // update import paths from .js to .min.js
183
+ copy: false, // copy minified code to clipboard instead of write to file if single file processed
184
+ relativeOutput: false, // output files relative to each src file instead of to input root
185
+ quietMode: false, // suppress all logging except errors
186
+ ignores: '', // files/dirs to exclude from minification
187
+ comment: '' // header comment to prepend to minified code
188
+ }
189
+ ```
190
+
191
+ 💡 Run `minify-js init` to generate a template `minify.config.mjs` in your project root.
192
+
164
193
  <br>
165
194
 
166
195
  <img height=6px width="100%" src="https://assets.minify-js.org/images/separators/aqua-gradient.png?v=ad67551">
@@ -192,7 +221,7 @@ const minifyJS = require('@adamlui/minify.js')
192
221
  If **source code** is passed, it is directly minified, then an object containing `srcPath` + `code` + `error` is returned:
193
222
 
194
223
  ```js
195
- const srcCode = 'function add(first, second) { return first + second; }',
224
+ const srcCode = 'function add(first, second) { return first + second }',
196
225
  minifyResult = minifyJS.minify(srcCode)
197
226
 
198
227
  console.log(minifyResult.error) // outputs runtime error, or `undefined` if no error
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adamlui/minify.js",
3
- "version": "2.1.4",
3
+ "version": "2.2.1",
4
4
  "description": "Recursively minify all JavaScript files.",
5
5
  "author": {
6
6
  "name": "Adam Lui",
@@ -44,7 +44,11 @@
44
44
  },
45
45
  "scripts": {
46
46
  "test": "bash utils/test/minify-cli.test.sh",
47
- "build": "bash utils/build.sh",
47
+ "build": "node utils/build",
48
+ "build:js": "node utils/build --js",
49
+ "build:data": "node utils/build --data",
50
+ "build:json": "node utils/build --json",
51
+ "debug": "node src/cli --debug",
48
52
  "bump:patch": "bash utils/bump.sh patch",
49
53
  "bump:minor": "bash utils/bump.sh minor",
50
54
  "bump:major": "bash utils/bump.sh major",
@@ -1,17 +0,0 @@
1
- /**
2
- * © 2023–2026 Adam Lui & contributors under the MIT license.
3
- * Source: https://github.com/adamlui/minify.js/tree/main/node.js/src
4
- * Documentation: https://github.com/adamlui/minify.js/tree/main/node.js/docs
5
- */
6
- module.exports={helpCmdAndDocURL(){console.info(`
7
- ${app.msgs.info_moreHelp}, ${app.msgs.info_type} ${app.name.split("/")[1]} --help' ${app.msgs.info_or} ${app.msgs.info_visit}
8
- `+app.colors.bw+app.urls.docs+app.colors.nc)},help(p=["header","usage","pathArgs","flags","paramOptions","infoCmds"]){app.prefix=""+app.colors.tlBG+app.colors.blk+` ${app.name.replace(/^@[^/]+\//,"")} ${app.colors.nc} `;let s={header:[`
9
- ├ ${app.prefix}${app.msgs.appCopyright||`© ${app.copyrightYear} ${app.author} under the ${app.license} license`}.`,""+app.prefix+app.msgs.prefix_source+": "+app.urls.src],usage:[`
10
- ${app.colors.bw}o ${app.msgs.helpSection_usage}:`+app.colors.nc,` ${app.colors.bw}» `+app.colors.bg+app.cmdFormat+app.colors.nc],pathArgs:[`
11
- ${app.colors.bw}o ${app.msgs.helpSection_pathArgs}:`+app.colors.nc," [inputPath] "+app.msgs.inputPathDesc_main+", "+app.msgs.inputPathDesc_extra+"."," [outputPath] "+app.msgs.outputPathDesc_main+", "+app.msgs.outputPathDesc_extra+"."],flags:[`
12
- ${app.colors.bw}o ${app.msgs.helpSection_flags}:`+app.colors.nc,` -n, --dry-run ${app.msgs.optionDesc_dryRun}.`,` -d, --include-dotfolders ${app.msgs.optionDesc_dotfolders}.`,` -D, --include-dotfiles ${app.msgs.optionDesc_dotfiles}.`,` -R, --no-recursion ${app.msgs.optionDesc_noRecursion}.`,` -M, --no-mangle ${app.msgs.optionDesc_noMangle}.`," -X, --no-filename-change "+app.msgs.optionDesc_noFilenameChange,` -i, --rewrite-imports ${app.msgs.optionDesc_rewriteImports}.`,` -c, --copy ${app.msgs.optionDesc_copy}.`,` -r, --relative-output ${app.msgs.optionDesc_relativeOutput}.`,` -q, --quiet ${app.msgs.optionDesc_quiet}.`],paramOptions:[`
13
- ${app.colors.bw}o ${app.msgs.helpSection_paramOptions}:`+app.colors.nc,`--ignores="dir/,file1.js,file2.js" ${app.msgs.optionDesc_ignores}.`,`--comment="comment" ${app.msgs.optionDesc_commentMain}.`+` ${app.msgs.optionDesc_commentExtra}.`],infoCmds:[`
14
- ${app.colors.bw}o ${app.msgs.helpSection_infoCmds}:`+app.colors.nc," -h, --help "+app.msgs.optionDesc_help,` -v, --version ${app.msgs.optionDesc_version}.`]};p.forEach(r=>s[r]?.forEach(s=>{{var n=/header|usage/.test(r)?1:37;let o=process.stdout.columns||80,e=[],p=s.match(/\S+|\s+/g),a="";p.forEach(p=>{var s=o-(e.length?n:0);a.length+"| ".length+p.length>s&&(e.push(e.length?a.trimStart():a),a=""),a+=p}),e.push(e.length?a.trimStart():a),e.forEach((p,s)=>console.info("| "+(0==s?p:" ".repeat(n)+p)))}})),console.info(`
15
- ${app.msgs.info_moreHelp}, ${app.msgs.info_visit}: `+app.colors.bw+app.urls.docs+app.colors.nc)},ifNotQuiet(p){app.config.quietMode||console.info(p)},version(){var p=require("path"),s=require("child_process").execSync(`npm view ${JSON.stringify(app.name)} version`).toString().trim()||"none";let o,e=process.cwd();for(;"/"!=e;){var a=p.join(e,"package.json");if(require("fs").existsSync(a)){a=require(a);o=(a.dependencies?.[app.name]||a.devDependencies?.[app.name])?.match(/^[~^>=]?\d+\.\d+\.\d+$/)?.[1]||"none";break}e=p.dirname(e)}console.info(`
16
- ${app.msgs.prefix_globalVer}: ${s}
17
- ${app.msgs.prefix_localVer}: `+o)}};