js-beautify
Advanced tools
Comparing version 0.2.4 to 0.3.0
294
cli.js
#!/usr/bin/env node | ||
var debug = process.env.DEBUG_JSBEAUTIFY || process.env.JSBEAUTIFY_DEBUG | ||
? function () { console.error.apply(console, arguments); } | ||
: function () {}; | ||
var fs = require('fs'), | ||
cc = require('config-chain'), | ||
beautify = require('./beautify').js_beautify, | ||
config, | ||
options; | ||
nopt = require('nopt'), | ||
path = require('path'), | ||
knownOpts = { | ||
// Beautifier | ||
"indent_size": Number, | ||
"indent_char": String, | ||
"indent_level": Number, | ||
"indent_with_tabs": Boolean, | ||
"preserve_newlines": Boolean, | ||
"max_preserve_newlines": Number, | ||
"jslint_happy": Boolean, | ||
"brace_style": ["collapse", "expand", "end-expand", "expand-strict"], | ||
"break_chained_methods": Boolean, | ||
"keep_array_indentation": Boolean, | ||
"unescape_strings": Boolean, | ||
// CLI | ||
"version": Boolean, | ||
"help": Boolean, | ||
"files": [path, Array], | ||
"outfile": path, | ||
"replace": Boolean, | ||
"config": path | ||
}, | ||
// dasherizeShorthands provides { "indent-size": ["--indent_size"] } | ||
// translation, allowing more convenient dashes in CLI arguments | ||
shortHands = dasherizeShorthands({ | ||
// Beautifier | ||
"s": ["--indent_size"], | ||
"c": ["--indent_char"], | ||
"l": ["--indent_level"], | ||
"t": ["--indent_with_tabs"], | ||
"p": ["--preserve_newlines"], | ||
"m": ["--max_preserve_newlines"], | ||
"j": ["--jslint_happy"], | ||
"b": ["--brace_style"], | ||
"B": ["--break_chained_methods"], | ||
"k": ["--keep_array_indentation"], | ||
"x": ["--unescape_strings"], | ||
// non-dasherized hybrid shortcuts | ||
"good-stuff": [ | ||
"--keep_array_indentation", | ||
"--keep_function_indentation", | ||
"--jslint_happy" | ||
], | ||
// CLI | ||
"v": ["--version"], | ||
"h": ["--help"], | ||
"f": ["--files"], | ||
"o": ["--outfile"], | ||
"r": ["--replace"] | ||
// no shorthand for "config" | ||
}), | ||
parsed = nopt(knownOpts, shortHands); | ||
// only node v0.5+ can require json | ||
if (parseFloat(process.version.substr(1)) < 0.5) { | ||
config = JSON.parse(fs.readFileSync(__dirname + '/config/defaults.json', 'utf8')); | ||
options = JSON.parse(fs.readFileSync(__dirname + '/config/options.json', 'utf8')); | ||
} else { | ||
config = require('./config/defaults.json'); | ||
options = require('./config/options.json'); | ||
if (parsed.version) { | ||
console.log(require('./package.json').version); | ||
process.exit(0); | ||
} | ||
else if (parsed.help) { | ||
usage(); | ||
process.exit(0); | ||
} | ||
var argv = require('optimist') | ||
.usage("Reformat JS files in idiomatic style.\n\nUsage:\n $0 [options] path/to/file [...]") | ||
.options(options) | ||
.check(function (argv) { | ||
if (argv.file) { | ||
if (Array.isArray(argv.file)) { | ||
// might pass multiple -f args | ||
argv._ = argv._.concat(argv.file); | ||
} | ||
else if ('string' === typeof argv.file) { | ||
// `cat foo.js | cli.js -f -`, avoid ['-', true] | ||
argv._.push(argv.file); | ||
} | ||
} | ||
var cfg = cc( | ||
parsed, | ||
cleanOptions(cc.env('jsbeautify_'), knownOpts), | ||
parsed.config, | ||
cc.find('.jsbeautifyrc'), | ||
__dirname + '/config/defaults.json' | ||
).snapshot; | ||
if ('string' === typeof argv.outfile && !argv._.length) { | ||
// use outfile as input when no other files passed in args | ||
argv._.push(argv.outfile); | ||
// operation is now an implicit overwrite | ||
argv.replace = true; | ||
} | ||
try { | ||
checkFiles(cfg); | ||
checkIndent(cfg); | ||
debug(cfg); | ||
} | ||
catch (ex) { | ||
debug(cfg); | ||
usage(ex); | ||
process.exit(1); | ||
} | ||
if (!argv._.length) { | ||
throw 'Must define at least one file.'; | ||
} | ||
argv._.forEach(function (filepath) { | ||
try { | ||
if (filepath !== "-") { | ||
fs.statSync(filepath); | ||
} | ||
} catch (err) { | ||
throw 'Unable to open path "' + filepath + '"'; | ||
} | ||
}); | ||
}) | ||
.argv; | ||
cfg.files.forEach(processInput, { cfg: cfg }); | ||
if (argv["indent-with-tabs"]) { | ||
argv["indent-size"] = 1; | ||
argv["indent-char"] = "\t"; | ||
} | ||
// translate dashed argv into weird python underscored keys, | ||
// avoiding single character aliases. | ||
Object.keys(argv).forEach(function (key) { | ||
if (key.length > 1) { | ||
config[key.replace(/-/g, '_')] = argv[key]; | ||
} | ||
}); | ||
function usage(err) { | ||
var msg = [ | ||
'js-beautify@' + require('./package.json').version, | ||
'', | ||
'CLI Options:', | ||
' -f, --file Input file(s) (Pass \'-\' for stdin)', | ||
' -r, --replace Write output in-place, replacing input', | ||
' -o, --outfile Write output to file (default stdout)', | ||
' --config Path to config file', | ||
' -h, --help Show this help', | ||
' -v, --version Show the version', | ||
'', | ||
'Beautifier Options:', | ||
' -s, --indent-size Indentation size [4]', | ||
' -c, --indent-char Indentation character [" "]', | ||
' -l, --indent-level Initial indentation level [0]', | ||
' -t, --indent-with-tabs Indent with tabs, overrides -s and -c', | ||
' -p, --preserve-newlines Preserve existing line-breaks (--no-preserve-newlines disables)', | ||
' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]', | ||
' -j, --jslint-happy Enable jslint-stricter mode', | ||
' -b, --brace-style [collapse|expand|end-expand|expand-strict] ["collapse"]', | ||
' -B, --break-chained-methods Break chained method calls across subsequent lines', | ||
' -k, --keep-array-indentation Preserve array indentation', | ||
' -x, --unescape-strings Decode printable characters encoded in xNN notation', | ||
' -g, --good-stuff Warm the cockles of Crockford\'s heart', | ||
'' | ||
]; | ||
function onOutputError(err) { | ||
if (err.code === 'EACCES') { | ||
console.error(err.path + " is not writable. Skipping!"); | ||
if (err) { | ||
msg.push(err); | ||
msg.push(''); | ||
console.error(msg.join('\n')); | ||
} else { | ||
console.log(msg.join('\n')); | ||
} | ||
} | ||
argv._.forEach(function (filepath) { | ||
// main iterator, {cfg} passed as thisArg of forEach call | ||
function processInput(filepath) { | ||
var data = '', | ||
config = this.cfg, | ||
input; | ||
@@ -92,14 +153,15 @@ | ||
var pretty = beautify(data, config), | ||
outfile = config.outfile, | ||
output; | ||
// -o passed with no value overwrites | ||
if (config.outfile === true || config.replace) { | ||
config.outfile = filepath; | ||
if (outfile === true || config.replace) { | ||
outfile = filepath; | ||
} | ||
if (config.outfile) { | ||
output = fs.createWriteStream(config.outfile, { | ||
if (outfile) { | ||
output = fs.createWriteStream(outfile, { | ||
flags: "w", | ||
encoding: "utf8", | ||
mode: 0644 | ||
mode: '644' | ||
}); | ||
@@ -119,3 +181,3 @@ | ||
if (config.outfile) { | ||
if (outfile) { | ||
output.end(); | ||
@@ -125,2 +187,104 @@ } | ||
}); | ||
}); | ||
} | ||
// workaround the fact that nopt.clean doesn't return the object passed in :P | ||
function cleanOptions(data, types) { | ||
nopt.clean(data, types); | ||
return data; | ||
} | ||
// error handler for output stream that swallows errors silently, | ||
// allowing the loop to continue over unwritable files. | ||
function onOutputError(err) { | ||
if (err.code === 'EACCES') { | ||
console.error(err.path + " is not writable. Skipping!"); | ||
} | ||
} | ||
// turn "--foo_bar" into "foo-bar" | ||
function dasherizeFlag(str) { | ||
return str.replace(/^\-+/, '').replace(/_/g, '-'); | ||
} | ||
// translate weird python underscored keys into dashed argv, | ||
// avoiding single character aliases. | ||
function dasherizeShorthands(hash) { | ||
// operate in-place | ||
Object.keys(hash).forEach(function (key) { | ||
// each key value is an array | ||
var val = hash[key][0]; | ||
// only dasherize one-character shorthands | ||
if (key.length === 1 && val.indexOf('_') > -1) { | ||
hash[dasherizeFlag(val)] = val; | ||
} | ||
}); | ||
return hash; | ||
} | ||
function checkIndent(parsed) { | ||
if (parsed["indent_with_tabs"]) { | ||
parsed["indent_size"] = 1; | ||
parsed["indent_char"] = "\t"; | ||
} | ||
return parsed; | ||
} | ||
function checkFiles(parsed) { | ||
var argv = parsed.argv; | ||
if (!parsed.files) { | ||
parsed.files = []; | ||
} else { | ||
if (argv.cooked.indexOf('-') > -1) { | ||
// strip stdin path eagerly added by nopt in '-f -' case | ||
parsed.files.some(removeDashedPath); | ||
} | ||
} | ||
if (argv.remain.length) { | ||
// assume any remaining args are files | ||
argv.remain.forEach(function (f) { | ||
parsed.files.push(path.resolve(f)); | ||
}); | ||
} | ||
if ('string' === typeof parsed.outfile && !parsed.files.length) { | ||
// use outfile as input when no other files passed in args | ||
parsed.files.push(parsed.outfile); | ||
// operation is now an implicit overwrite | ||
parsed.replace = true; | ||
} | ||
if (argv.original.indexOf('-') > -1) { | ||
// ensure '-' without '-f' still consumes stdin | ||
parsed.files.push('-'); | ||
} | ||
if (!parsed.files.length) { | ||
throw 'Must define at least one file.'; | ||
} | ||
parsed.files.forEach(testFilePath); | ||
return parsed; | ||
} | ||
function removeDashedPath(filepath, i, arr) { | ||
var found = filepath.lastIndexOf('-') === (filepath.length - 1); | ||
if (found) { | ||
arr.splice(i, 1); | ||
} | ||
return found; | ||
} | ||
function testFilePath(filepath) { | ||
try { | ||
if (filepath !== "-") { | ||
fs.statSync(filepath); | ||
} | ||
} catch (err) { | ||
throw 'Unable to open path "' + filepath + '"'; | ||
} | ||
} |
{ | ||
"name": "js-beautify", | ||
"version": "0.2.4", | ||
"version": "0.3.0", | ||
"description": "jsbeautifier.org for node", | ||
@@ -36,4 +36,5 @@ "main": "beautify.js", | ||
"dependencies": { | ||
"optimist": "~0.3.4" | ||
"config-chain": "~1.1.3", | ||
"nopt": "2.x" | ||
} | ||
} |
@@ -66,39 +66,55 @@ # JS Beautifier | ||
CLI Options: | ||
-f, --file Input file(s) (Pass '-' for stdin). These can also be passed directly. | ||
-r, --replace Write output in-place, replacing input | ||
-o, --outfile Write output to file (default stdout) | ||
Beautifier Options: | ||
-s, --indent-size Indentation size [default: 4] | ||
-c, --indent-char Indentation character [default: " "] | ||
-l, --indent-level Initial indentation level [default: 0] | ||
-t, --indent-with-tabs Indent with tabs, overrides -s and -c | ||
-p, --preserve-newlines Preserve existing line-breaks (--no-preserve-newlines disables) [default: true] | ||
-m, --max-preserve-newlines Maximum number of line-breaks to be preserved in one chunk [default: 10] | ||
-j, --jslint-happy Enable jslint-stricter mode | ||
-b, --brace-style Brace style [collapse|expand|end-expand|expand-strict] [default: "collapse"] | ||
-B, --break-chained-methods Break chained method calls across subsequent lines | ||
-k, --keep-array-indentation Preserve array indentation | ||
-x, --unescape-strings Decode printable characters encoded in xNN notation | ||
```txt | ||
CLI Options: | ||
-f, --file Input file(s) (Pass '-' for stdin). These can also be passed directly. | ||
-r, --replace Write output in-place, replacing input | ||
-o, --outfile Write output to file (default stdout) | ||
--config Path to config file | ||
-v, --version Show the version | ||
-h, --help Show this help | ||
These correspond to underscored option keys for both library interfaces: | ||
Beautifier Options: | ||
-s, --indent-size Indentation size [4] | ||
-c, --indent-char Indentation character [" "] | ||
-l, --indent-level Initial indentation level [0] | ||
-t, --indent-with-tabs Indent with tabs, overrides -s and -c | ||
-p, --preserve-newlines Preserve existing line-breaks (--no-preserve-newlines disables) | ||
-m, --max-preserve-newlines Maximum number of line-breaks to be preserved in one chunk [10] | ||
-j, --jslint-happy Enable jslint-stricter mode | ||
-b, --brace-style [collapse|expand|end-expand|expand-strict] ["collapse"] | ||
-B, --break-chained-methods Break chained method calls across subsequent lines | ||
-k, --keep-array-indentation Preserve array indentation | ||
-x, --unescape-strings Decode printable characters encoded in xNN notation | ||
-g, --good-stuff Warm the cockles of Crockford's heart | ||
``` | ||
defaults = { | ||
"indent_size": 4, | ||
"indent_char": " ", | ||
"indent_level": 0, | ||
"indent_with_tabs": false, | ||
"preserve_newlines": true, | ||
"max_preserve_newlines": 10, | ||
"jslint_happy": false, | ||
"brace_style": "collapse", | ||
"keep_array_indentation": false, | ||
"keep_function_indentation": false, | ||
"space_before_conditional": true, | ||
"break_chained_methods": false, | ||
"eval_code": false, | ||
"unescape_strings": false | ||
} | ||
These largely correspond to the underscored option keys for both library interfaces, which have these defaults: | ||
```json | ||
{ | ||
"indent_size": 4, | ||
"indent_char": " ", | ||
"indent_level": 0, | ||
"indent_with_tabs": false, | ||
"preserve_newlines": true, | ||
"max_preserve_newlines": 10, | ||
"jslint_happy": false, | ||
"brace_style": "collapse", | ||
"keep_array_indentation": false, | ||
"keep_function_indentation": false, | ||
"space_before_conditional": true, | ||
"break_chained_methods": false, | ||
"eval_code": false, | ||
"unescape_strings": false | ||
} | ||
``` | ||
In addition to CLI arguments, you may pass config to the JS executable via: | ||
* any `jsbeautify_`-prefixed environment variables | ||
* a `JSON`-formatted file indicated by the `--config` parameter | ||
* a `.jsbeautifyrc` file containing `JSON` data at any level of the filesystem above `$PWD` | ||
Configuration sources provided earlier in this stack will override later ones. | ||
You might notice that the CLI options and defaults hash aren't 100% correlated. Historically, the Python and JS APIs have not been 100% identical. For example, `space_before_conditional` is currently JS-only, and not addressable from the CLI script. There are a few other additional cases keeping us from 100% API-compatibility. Patches welcome! | ||
@@ -105,0 +121,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*global js_beautify */ | ||
/*global js_beautify: true */ | ||
/*jshint node:true */ | ||
@@ -7,2 +7,3 @@ | ||
var SanityTest = require('./sanitytest'), | ||
Urlencoded = require('../unpackers/urlencode_unpacker'), | ||
js_beautify = require('../beautify').js_beautify; | ||
@@ -9,0 +10,0 @@ } |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
90849
1931
134
2
12
3
+ Addedconfig-chain@~1.1.3
+ Addednopt@2.x
+ Addedabbrev@1.1.1(transitive)
+ Addedconfig-chain@1.1.13(transitive)
+ Addedini@1.3.8(transitive)
+ Addednopt@2.2.1(transitive)
+ Addedproto-list@1.2.4(transitive)
- Removedoptimist@~0.3.4
- Removedoptimist@0.3.7(transitive)
- Removedwordwrap@0.0.3(transitive)