js-beautify 1.8.5 → 1.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +38 -13
  2. package/README.md +17 -14
  3. package/js/lib/beautifier.js +115 -30
  4. package/js/lib/beautifier.min.js +1 -1
  5. package/js/lib/beautify-css.js +14 -5
  6. package/js/lib/beautify-html.js +47 -18
  7. package/js/lib/beautify.js +68 -15
  8. package/js/lib/cli.js +515 -482
  9. package/js/lib/unpackers/javascriptobfuscator_unpacker.js +1 -1
  10. package/js/lib/unpackers/myobfuscate_unpacker.js +1 -1
  11. package/js/lib/unpackers/p_a_c_k_e_r_unpacker.js +1 -1
  12. package/js/lib/unpackers/urlencode_unpacker.js +1 -1
  13. package/js/src/cli.js +515 -482
  14. package/js/src/core/directives.js +1 -1
  15. package/js/src/core/inputscanner.js +1 -1
  16. package/js/src/core/options.js +4 -5
  17. package/js/src/core/output.js +1 -1
  18. package/js/src/core/token.js +1 -1
  19. package/js/src/core/tokenizer.js +1 -1
  20. package/js/src/core/tokenstream.js +1 -1
  21. package/js/src/css/beautifier.js +1 -1
  22. package/js/src/css/index.js +6 -2
  23. package/js/src/css/options.js +1 -1
  24. package/js/src/css/tokenizer.js +1 -1
  25. package/js/src/html/beautifier.js +28 -13
  26. package/js/src/html/index.js +6 -2
  27. package/js/src/html/options.js +2 -2
  28. package/js/src/html/tokenizer.js +1 -1
  29. package/js/src/index.js +2 -1
  30. package/js/src/javascript/acorn.js +1 -1
  31. package/js/src/javascript/beautifier.js +33 -4
  32. package/js/src/javascript/index.js +6 -2
  33. package/js/src/javascript/options.js +3 -1
  34. package/js/src/javascript/tokenizer.js +15 -8
  35. package/js/src/unpackers/javascriptobfuscator_unpacker.js +1 -1
  36. package/js/src/unpackers/myobfuscate_unpacker.js +1 -1
  37. package/js/src/unpackers/p_a_c_k_e_r_unpacker.js +1 -1
  38. package/js/src/unpackers/urlencode_unpacker.js +1 -1
  39. package/package.json +8 -7
package/js/lib/cli.js CHANGED
@@ -34,607 +34,640 @@
34
34
  /*jshint strict:false */
35
35
 
36
36
  var debug = process.env.DEBUG_JSBEAUTIFY || process.env.JSBEAUTIFY_DEBUG ? function() {
37
- console.error.apply(console, arguments);
37
+ console.error.apply(console, arguments);
38
38
  } : function() {};
39
39
 
40
40
  var fs = require('fs'),
41
- cc = require('config-chain'),
42
- beautify = require('../index'),
43
- mkdirp = require('mkdirp'),
44
- nopt = require('nopt');
41
+ cc = require('config-chain'),
42
+ beautify = require('../index'),
43
+ mkdirp = require('mkdirp'),
44
+ nopt = require('nopt'),
45
+ glob = require('glob');
45
46
 
46
47
  nopt.invalidHandler = function(key, val) {
47
- throw new Error(key + " was invalid with value \"" + val + "\"");
48
+ throw new Error(key + " was invalid with value \"" + val + "\"");
48
49
  };
49
50
 
50
51
  nopt.typeDefs.brace_style = {
51
- type: "brace_style",
52
- validate: function(data, key, val) {
53
- data[key] = val;
54
- // TODO: expand-strict is obsolete, now identical to expand. Remove in future version
55
- // TODO: collapse-preserve-inline is obselete, now identical to collapse,preserve-inline = true. Remove in future version
56
- var validVals = ["collapse", "collapse-preserve-inline", "expand", "end-expand", "expand-strict", "none", "preserve-inline"];
57
- var valSplit = val.split(/[^a-zA-Z0-9_\-]+/); //Split will always return at least one parameter
58
- for (var i = 0; i < valSplit.length; i++) {
59
- if (validVals.indexOf(valSplit[i]) === -1) {
60
- return false;
61
- }
52
+ type: "brace_style",
53
+ validate: function(data, key, val) {
54
+ data[key] = val;
55
+ // TODO: expand-strict is obsolete, now identical to expand. Remove in future version
56
+ // TODO: collapse-preserve-inline is obselete, now identical to collapse,preserve-inline = true. Remove in future version
57
+ var validVals = ["collapse", "collapse-preserve-inline", "expand", "end-expand", "expand-strict", "none", "preserve-inline"];
58
+ var valSplit = val.split(/[^a-zA-Z0-9_\-]+/); //Split will always return at least one parameter
59
+ for (var i = 0; i < valSplit.length; i++) {
60
+ if (validVals.indexOf(valSplit[i]) === -1) {
61
+ return false;
62
+ }
63
+ }
64
+ return true;
62
65
  }
63
- return true;
64
- }
65
66
  };
66
67
  var path = require('path'),
67
- editorconfig = require('editorconfig'),
68
- knownOpts = {
69
- // Beautifier
70
- "indent_size": Number,
71
- "indent_char": String,
72
- "eol": String,
73
- "indent_level": Number,
74
- "indent_with_tabs": Boolean,
75
- "preserve_newlines": Boolean,
76
- "max_preserve_newlines": Number,
77
- "space_in_paren": Boolean,
78
- "space_in_empty_paren": Boolean,
79
- "jslint_happy": Boolean,
80
- "space_after_anon_function": Boolean,
81
- "brace_style": "brace_style", //See above for validation
82
- "unindent_chained_methods": Boolean,
83
- "break_chained_methods": Boolean,
84
- "keep_array_indentation": Boolean,
85
- "unescape_strings": Boolean,
86
- "wrap_line_length": Number,
87
- "wrap_attributes": ["auto", "force", "force-aligned", "force-expand-multiline", "aligned-multiple"],
88
- "wrap_attributes_indent_size": Number,
89
- "e4x": Boolean,
90
- "end_with_newline": Boolean,
91
- "comma_first": Boolean,
92
- "operator_position": ["before-newline", "after-newline", "preserve-newline"],
93
- // CSS-only
94
- "selector_separator_newline": Boolean,
95
- "newline_between_rules": Boolean,
96
- "space_around_combinator": Boolean,
97
- //deprecated - replaced with space_around_combinator, remove in future version
98
- "space_around_selector_separator": Boolean,
99
- // HTML-only
100
- "max_char": Number, // obsolete since 1.3.5
101
- "inline": [String, Array],
102
- "unformatted": [String, Array],
103
- "content_unformatted": [String, Array],
104
- "indent_inner_html": [Boolean],
105
- "indent_handlebars": [Boolean],
106
- "indent_scripts": ["keep", "separate", "normal"],
107
- "extra_liners": [String, Array],
108
- // CLI
109
- "version": Boolean,
110
- "help": Boolean,
111
- "files": [path, Array],
112
- "outfile": path,
113
- "replace": Boolean,
114
- "quiet": Boolean,
115
- "type": ["js", "css", "html"],
116
- "config": path,
117
- "editorconfig": Boolean
118
- },
119
- // dasherizeShorthands provides { "indent-size": ["--indent_size"] }
120
- // translation, allowing more convenient dashes in CLI arguments
121
- shortHands = dasherizeShorthands({
122
- // Beautifier
123
- "s": ["--indent_size"],
124
- "c": ["--indent_char"],
125
- "e": ["--eol"],
126
- "l": ["--indent_level"],
127
- "t": ["--indent_with_tabs"],
128
- "p": ["--preserve_newlines"],
129
- "m": ["--max_preserve_newlines"],
130
- "P": ["--space_in_paren"],
131
- "Q": ["--space_in_empty_paren"],
132
- "j": ["--jslint_happy"],
133
- "a": ["--space_after_anon_function"],
134
- "b": ["--brace_style"],
135
- "u": ["--unindent_chained_methods"],
136
- "B": ["--break_chained_methods"],
137
- "k": ["--keep_array_indentation"],
138
- "x": ["--unescape_strings"],
139
- "w": ["--wrap_line_length"],
140
- "X": ["--e4x"],
141
- "n": ["--end_with_newline"],
142
- "C": ["--comma_first"],
143
- "O": ["--operator_position"],
144
- // CSS-only
145
- "L": ["--selector_separator_newline"],
146
- "N": ["--newline_between_rules"],
147
- // HTML-only
148
- "A": ["--wrap_attributes"],
149
- "i": ["--wrap_attributes_indent_size"],
150
- "W": ["--max_char"], // obsolete since 1.3.5
151
- "d": ["--inline"],
152
- "U": ["--unformatted"],
153
- "T": ["--content_unformatted"],
154
- "I": ["--indent_inner_html"],
155
- "H": ["--indent_handlebars"],
156
- "S": ["--indent_scripts"],
157
- "E": ["--extra_liners"],
158
- // non-dasherized hybrid shortcuts
159
- "good-stuff": [
160
- "--keep_array_indentation",
161
- "--keep_function_indentation",
162
- "--jslint_happy"
163
- ],
164
- "js": ["--type", "js"],
165
- "css": ["--type", "css"],
166
- "html": ["--type", "html"],
167
- // CLI
168
- "v": ["--version"],
169
- "h": ["--help"],
170
- "f": ["--files"],
171
- "o": ["--outfile"],
172
- "r": ["--replace"],
173
- "q": ["--quiet"]
174
- // no shorthand for "config"
175
- // no shorthand for "editorconfig"
176
- });
68
+ editorconfig = require('editorconfig'),
69
+ knownOpts = {
70
+ // Beautifier
71
+ "indent_size": Number,
72
+ "indent_char": String,
73
+ "eol": String,
74
+ "indent_level": Number,
75
+ "indent_with_tabs": Boolean,
76
+ "preserve_newlines": Boolean,
77
+ "max_preserve_newlines": Number,
78
+ "space_in_paren": Boolean,
79
+ "space_in_empty_paren": Boolean,
80
+ "jslint_happy": Boolean,
81
+ "space_after_anon_function": Boolean,
82
+ "space_after_named_function": Boolean,
83
+ "brace_style": "brace_style", //See above for validation
84
+ "unindent_chained_methods": Boolean,
85
+ "break_chained_methods": Boolean,
86
+ "keep_array_indentation": Boolean,
87
+ "unescape_strings": Boolean,
88
+ "wrap_line_length": Number,
89
+ "wrap_attributes": ["auto", "force", "force-aligned", "force-expand-multiline", "aligned-multiple", "preserve", "preserve-aligned"],
90
+ "wrap_attributes_indent_size": Number,
91
+ "e4x": Boolean,
92
+ "end_with_newline": Boolean,
93
+ "comma_first": Boolean,
94
+ "operator_position": ["before-newline", "after-newline", "preserve-newline"],
95
+ // CSS-only
96
+ "selector_separator_newline": Boolean,
97
+ "newline_between_rules": Boolean,
98
+ "space_around_combinator": Boolean,
99
+ //deprecated - replaced with space_around_combinator, remove in future version
100
+ "space_around_selector_separator": Boolean,
101
+ // HTML-only
102
+ "max_char": Number, // obsolete since 1.3.5
103
+ "inline": [String, Array],
104
+ "unformatted": [String, Array],
105
+ "content_unformatted": [String, Array],
106
+ "indent_inner_html": [Boolean],
107
+ "indent_handlebars": [Boolean],
108
+ "indent_scripts": ["keep", "separate", "normal"],
109
+ "extra_liners": [String, Array],
110
+ // CLI
111
+ "version": Boolean,
112
+ "help": Boolean,
113
+ "files": [path, Array],
114
+ "outfile": path,
115
+ "replace": Boolean,
116
+ "quiet": Boolean,
117
+ "type": ["js", "css", "html"],
118
+ "config": path,
119
+ "editorconfig": Boolean
120
+ },
121
+ // dasherizeShorthands provides { "indent-size": ["--indent_size"] }
122
+ // translation, allowing more convenient dashes in CLI arguments
123
+ shortHands = dasherizeShorthands({
124
+ // Beautifier
125
+ "s": ["--indent_size"],
126
+ "c": ["--indent_char"],
127
+ "e": ["--eol"],
128
+ "l": ["--indent_level"],
129
+ "t": ["--indent_with_tabs"],
130
+ "p": ["--preserve_newlines"],
131
+ "m": ["--max_preserve_newlines"],
132
+ "P": ["--space_in_paren"],
133
+ "Q": ["--space_in_empty_paren"],
134
+ "j": ["--jslint_happy"],
135
+ "a": ["--space_after_anon_function"],
136
+ "b": ["--brace_style"],
137
+ "u": ["--unindent_chained_methods"],
138
+ "B": ["--break_chained_methods"],
139
+ "k": ["--keep_array_indentation"],
140
+ "x": ["--unescape_strings"],
141
+ "w": ["--wrap_line_length"],
142
+ "X": ["--e4x"],
143
+ "n": ["--end_with_newline"],
144
+ "C": ["--comma_first"],
145
+ "O": ["--operator_position"],
146
+ // CSS-only
147
+ "L": ["--selector_separator_newline"],
148
+ "N": ["--newline_between_rules"],
149
+ // HTML-only
150
+ "A": ["--wrap_attributes"],
151
+ "i": ["--wrap_attributes_indent_size"],
152
+ "W": ["--max_char"], // obsolete since 1.3.5
153
+ "d": ["--inline"],
154
+ "U": ["--unformatted"],
155
+ "T": ["--content_unformatted"],
156
+ "I": ["--indent_inner_html"],
157
+ "H": ["--indent_handlebars"],
158
+ "S": ["--indent_scripts"],
159
+ "E": ["--extra_liners"],
160
+ // non-dasherized hybrid shortcuts
161
+ "good-stuff": [
162
+ "--keep_array_indentation",
163
+ "--keep_function_indentation",
164
+ "--jslint_happy"
165
+ ],
166
+ "js": ["--type", "js"],
167
+ "css": ["--type", "css"],
168
+ "html": ["--type", "html"],
169
+ // CLI
170
+ "v": ["--version"],
171
+ "h": ["--help"],
172
+ "f": ["--files"],
173
+ "file": ["--files"],
174
+ "o": ["--outfile"],
175
+ "r": ["--replace"],
176
+ "q": ["--quiet"]
177
+ // no shorthand for "config"
178
+ // no shorthand for "editorconfig"
179
+ });
177
180
 
178
181
  function verifyExists(fullPath) {
179
- return fs.existsSync(fullPath) ? fullPath : null;
182
+ return fs.existsSync(fullPath) ? fullPath : null;
180
183
  }
181
184
 
182
185
  function findRecursive(dir, fileName) {
183
- var fullPath = path.join(dir, fileName);
184
- var nextDir = path.dirname(dir);
185
- var result = verifyExists(fullPath);
186
+ var fullPath = path.join(dir, fileName);
187
+ var nextDir = path.dirname(dir);
188
+ var result = verifyExists(fullPath);
186
189
 
187
- if (!result && (nextDir !== dir)) {
188
- result = findRecursive(nextDir, fileName);
189
- }
190
+ if (!result && (nextDir !== dir)) {
191
+ result = findRecursive(nextDir, fileName);
192
+ }
190
193
 
191
- return result;
194
+ return result;
192
195
  }
193
196
 
194
197
  function getUserHome() {
195
- var user_home = '';
196
- try {
197
- user_home = process.env.USERPROFILE || process.env.HOME || '';
198
- } catch (ex) {}
199
- return user_home;
198
+ var user_home = '';
199
+ try {
200
+ user_home = process.env.USERPROFILE || process.env.HOME || '';
201
+ } catch (ex) {}
202
+ return user_home;
200
203
  }
201
204
 
202
205
  function set_file_editorconfig_opts(file, config) {
203
- try {
204
- var eConfigs = editorconfig.parseSync(file);
205
-
206
- if (eConfigs.indent_style === "tab") {
207
- config.indent_with_tabs = true;
208
- } else if (eConfigs.indent_style === "space") {
209
- config.indent_with_tabs = false;
206
+ try {
207
+ var eConfigs = editorconfig.parseSync(file);
208
+
209
+ if (eConfigs.indent_style === "tab") {
210
+ config.indent_with_tabs = true;
211
+ } else if (eConfigs.indent_style === "space") {
212
+ config.indent_with_tabs = false;
213
+ }
214
+
215
+ if (eConfigs.indent_size) {
216
+ config.indent_size = eConfigs.indent_size;
217
+ }
218
+
219
+ if (eConfigs.max_line_length) {
220
+ if (eConfigs.max_line_length === "off") {
221
+ config.wrap_line_length = 0;
222
+ } else {
223
+ config.wrap_line_length = parseInt(eConfigs.max_line_length, 10);
224
+ }
225
+ }
226
+
227
+ if (eConfigs.insert_final_newline === true) {
228
+ config.end_with_newline = true;
229
+ } else if (eConfigs.insert_final_newline === false) {
230
+ config.end_with_newline = false;
231
+ }
232
+
233
+ if (eConfigs.end_of_line) {
234
+ if (eConfigs.end_of_line === 'cr') {
235
+ config.eol = '\r';
236
+ } else if (eConfigs.end_of_line === 'lf') {
237
+ config.eol = '\n';
238
+ } else if (eConfigs.end_of_line === 'crlf') {
239
+ config.eol = '\r\n';
240
+ }
241
+ }
242
+ } catch (e) {
243
+ debug(e);
210
244
  }
245
+ }
211
246
 
212
- if (eConfigs.indent_size) {
213
- config.indent_size = eConfigs.indent_size;
247
+ // var cli = require('js-beautify/cli'); cli.interpret();
248
+ var interpret = exports.interpret = function(argv, slice) {
249
+ var parsed;
250
+ try {
251
+ parsed = nopt(knownOpts, shortHands, argv, slice);
252
+ } catch (ex) {
253
+ usage(ex);
254
+ // console.error(ex);
255
+ // console.error('Run `' + getScriptName() + ' -h` for help.');
256
+ process.exit(1);
214
257
  }
215
258
 
216
- if (eConfigs.max_line_length) {
217
- if (eConfigs.max_line_length === "off") {
218
- config.wrap_line_length = 0;
219
- } else {
220
- config.wrap_line_length = parseInt(eConfigs.max_line_length, 10);
221
- }
222
- }
223
259
 
224
- if (eConfigs.insert_final_newline === true) {
225
- config.end_with_newline = true;
226
- } else if (eConfigs.insert_final_newline === false) {
227
- config.end_with_newline = false;
260
+ if (parsed.version) {
261
+ console.log(require('../../package.json').version);
262
+ process.exit(0);
263
+ } else if (parsed.help) {
264
+ usage();
265
+ process.exit(0);
228
266
  }
229
267
 
230
- if (eConfigs.end_of_line) {
231
- if (eConfigs.end_of_line === 'cr') {
232
- config.eol = '\r';
233
- } else if (eConfigs.end_of_line === 'lf') {
234
- config.eol = '\n';
235
- } else if (eConfigs.end_of_line === 'crlf') {
236
- config.eol = '\r\n';
237
- }
268
+ var cfg;
269
+ var configRecursive = findRecursive(process.cwd(), '.jsbeautifyrc');
270
+ var configHome = verifyExists(path.join(getUserHome() || "", ".jsbeautifyrc"));
271
+ var configDefault = __dirname + '/../config/defaults.json';
272
+
273
+ try {
274
+ cfg = cc(
275
+ parsed,
276
+ cleanOptions(cc.env('jsbeautify_'), knownOpts),
277
+ parsed.config,
278
+ configRecursive,
279
+ configHome,
280
+ configDefault
281
+ ).snapshot;
282
+ } catch (ex) {
283
+ debug(cfg);
284
+ // usage(ex);
285
+ console.error(ex);
286
+ console.error('Error while loading beautifier configuration.');
287
+ console.error('Configuration file chain included:');
288
+ if (parsed.config) {
289
+ console.error(parsed.config);
290
+ }
291
+ if (configRecursive) {
292
+ console.error(configRecursive);
293
+ }
294
+ if (configHome) {
295
+ console.error(configHome);
296
+ }
297
+ console.error(configDefault);
298
+ console.error('Run `' + getScriptName() + ' -h` for help.');
299
+ process.exit(1);
238
300
  }
239
- } catch (e) {
240
- debug(e);
241
- }
242
- }
243
301
 
244
- // var cli = require('js-beautify/cli'); cli.interpret();
245
- var interpret = exports.interpret = function(argv, slice) {
246
- var parsed;
247
- try {
248
- parsed = nopt(knownOpts, shortHands, argv, slice);
249
- } catch (ex) {
250
- usage(ex);
251
- // console.error(ex);
252
- // console.error('Run `' + getScriptName() + ' -h` for help.');
253
- process.exit(1);
254
- }
255
-
256
-
257
- if (parsed.version) {
258
- console.log(require('../../package.json').version);
259
- process.exit(0);
260
- } else if (parsed.help) {
261
- usage();
262
- process.exit(0);
263
- }
264
-
265
- var cfg;
266
- var configRecursive = findRecursive(process.cwd(), '.jsbeautifyrc');
267
- var configHome = verifyExists(path.join(getUserHome() || "", ".jsbeautifyrc"));
268
- var configDefault = __dirname + '/../config/defaults.json';
269
-
270
- try {
271
- cfg = cc(
272
- parsed,
273
- cleanOptions(cc.env('jsbeautify_'), knownOpts),
274
- parsed.config,
275
- configRecursive,
276
- configHome,
277
- configDefault
278
- ).snapshot;
279
- } catch (ex) {
280
- debug(cfg);
281
- // usage(ex);
282
- console.error(ex);
283
- console.error('Error while loading beautifier configuration.');
284
- console.error('Configuration file chain included:');
285
- if (parsed.config) {
286
- console.error(parsed.config);
302
+ try {
303
+ // Verify arguments
304
+ checkType(cfg);
305
+ checkFiles(cfg);
306
+ debug(cfg);
307
+
308
+ // Process files synchronously to avoid EMFILE error
309
+ cfg.files.forEach(processInputSync, {
310
+ cfg: cfg
311
+ });
312
+ } catch (ex) {
313
+ debug(cfg);
314
+ // usage(ex);
315
+ console.error(ex);
316
+ console.error('Run `' + getScriptName() + ' -h` for help.');
317
+ process.exit(1);
287
318
  }
288
- if (configRecursive) {
289
- console.error(configRecursive);
290
- }
291
- if (configHome) {
292
- console.error(configHome);
293
- }
294
- console.error(configDefault);
295
- console.error('Run `' + getScriptName() + ' -h` for help.');
296
- process.exit(1);
297
- }
298
-
299
- try {
300
- // Verify arguments
301
- checkType(cfg);
302
- checkFiles(cfg);
303
- debug(cfg);
304
-
305
- // Process files synchronously to avoid EMFILE error
306
- cfg.files.forEach(processInputSync, {
307
- cfg: cfg
308
- });
309
- } catch (ex) {
310
- debug(cfg);
311
- // usage(ex);
312
- console.error(ex);
313
- console.error('Run `' + getScriptName() + ' -h` for help.');
314
- process.exit(1);
315
- }
316
319
  };
317
320
 
318
321
  // interpret args immediately when called as executable
319
322
  if (require.main === module) {
320
- interpret();
323
+ interpret();
321
324
  }
322
325
 
323
326
  function usage(err) {
324
- var scriptName = getScriptName();
325
- var msg = [
326
- scriptName + '@' + require('../../package.json').version,
327
- '',
328
- 'CLI Options:',
329
- ' -f, --file Input file(s) (Pass \'-\' for stdin)',
330
- ' -r, --replace Write output in-place, replacing input',
331
- ' -o, --outfile Write output to file (default stdout)',
332
- ' --config Path to config file',
333
- ' --type [js|css|html] ["js"]',
334
- ' -q, --quiet Suppress logging to stdout',
335
- ' -h, --help Show this help',
336
- ' -v, --version Show the version',
337
- '',
338
- 'Beautifier Options:',
339
- ' -s, --indent-size Indentation size [4]',
340
- ' -c, --indent-char Indentation character [" "]',
341
- ' -t, --indent-with-tabs Indent with tabs, overrides -s and -c',
342
- ' -e, --eol Character(s) to use as line terminators.',
343
- ' [first newline in file, otherwise "\\n]',
344
- ' -n, --end-with-newline End output with newline',
345
- ' --editorconfig Use EditorConfig to set up the options'
346
- ];
347
-
348
- switch (scriptName.split('-').shift()) {
349
- case "js":
350
- msg.push(' -l, --indent-level Initial indentation level [0]');
351
- msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
352
- msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
353
- msg.push(' -P, --space-in-paren Add padding spaces within paren, ie. f( a, b )');
354
- msg.push(' -E, --space-in-empty-paren Add a single space inside empty paren, ie. f( )');
355
- msg.push(' -j, --jslint-happy Enable jslint-stricter mode');
356
- msg.push(' -a, --space-after-anon-function Add a space before an anonymous function\'s parens, ie. function ()');
357
- msg.push(' -b, --brace-style [collapse|expand|end-expand|none][,preserve-inline] [collapse,preserve-inline]');
358
- msg.push(' -u, --unindent-chained-methods Don\'t indent chained method calls');
359
- msg.push(' -B, --break-chained-methods Break chained method calls across subsequent lines');
360
- msg.push(' -k, --keep-array-indentation Preserve array indentation');
361
- msg.push(' -x, --unescape-strings Decode printable characters encoded in xNN notation');
362
- msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
363
- msg.push(' -X, --e4x Pass E4X xml literals through untouched');
364
- msg.push(' --good-stuff Warm the cockles of Crockford\'s heart');
365
- msg.push(' -C, --comma-first Put commas at the beginning of new line instead of end');
366
- msg.push(' -O, --operator-position Set operator position (before-newline|after-newline|preserve-newline) [before-newline]');
367
- break;
368
- case "html":
369
- msg.push(' -b, --brace-style [collapse|expand|end-expand] ["collapse"]');
370
- msg.push(' -I, --indent-inner-html Indent body and head sections. Default is false.');
371
- msg.push(' -H, --indent-handlebars Indent handlebars. Default is false.');
372
- msg.push(' -S, --indent-scripts [keep|separate|normal] ["normal"]');
373
- msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
374
- msg.push(' -A, --wrap-attributes Wrap html tag attributes to new lines [auto|force] ["auto"]');
375
- msg.push(' -i, --wrap-attributes-indent-size Indent wrapped tags to after N characters [indent-level]');
376
- msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
377
- msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
378
- msg.push(' -U, --unformatted List of tags (defaults to inline) that should not be reformatted');
379
- msg.push(' -T, --content_unformatted List of tags (defaults to pre) whose content should not be reformatted');
380
- msg.push(' -E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline');
381
- break;
382
- case "css":
383
- msg.push(' -L, --selector-separator-newline Add a newline between multiple selectors.');
384
- msg.push(' -N, --newline-between-rules Add a newline between CSS rules.');
385
- }
386
-
387
- if (err) {
388
- msg.push(err);
389
- msg.push('');
390
- console.error(msg.join('\n'));
391
- } else {
392
- console.log(msg.join('\n'));
393
- }
327
+ var scriptName = getScriptName();
328
+ var msg = [
329
+ scriptName + '@' + require('../../package.json').version,
330
+ '',
331
+ 'CLI Options:',
332
+ ' -f, --file Input file(s) (Pass \'-\' for stdin)',
333
+ ' -r, --replace Write output in-place, replacing input',
334
+ ' -o, --outfile Write output to file (default stdout)',
335
+ ' --config Path to config file',
336
+ ' --type [js|css|html] ["js"]',
337
+ ' -q, --quiet Suppress logging to stdout',
338
+ ' -h, --help Show this help',
339
+ ' -v, --version Show the version',
340
+ '',
341
+ 'Beautifier Options:',
342
+ ' -s, --indent-size Indentation size [4]',
343
+ ' -c, --indent-char Indentation character [" "]',
344
+ ' -t, --indent-with-tabs Indent with tabs, overrides -s and -c',
345
+ ' -e, --eol Character(s) to use as line terminators.',
346
+ ' [first newline in file, otherwise "\\n]',
347
+ ' -n, --end-with-newline End output with newline',
348
+ ' --editorconfig Use EditorConfig to set up the options'
349
+ ];
350
+
351
+ switch (scriptName.split('-').shift()) {
352
+ case "js":
353
+ msg.push(' -l, --indent-level Initial indentation level [0]');
354
+ msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
355
+ msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
356
+ msg.push(' -P, --space-in-paren Add padding spaces within paren, ie. f( a, b )');
357
+ msg.push(' -E, --space-in-empty-paren Add a single space inside empty paren, ie. f( )');
358
+ msg.push(' -j, --jslint-happy Enable jslint-stricter mode');
359
+ msg.push(' -a, --space-after-anon-function Add a space before an anonymous function\'s parens, ie. function ()');
360
+ msg.push(' --space_after_named_function Add a space before a named function\'s parens, ie. function example ()');
361
+ msg.push(' -b, --brace-style [collapse|expand|end-expand|none][,preserve-inline] [collapse,preserve-inline]');
362
+ msg.push(' -u, --unindent-chained-methods Don\'t indent chained method calls');
363
+ msg.push(' -B, --break-chained-methods Break chained method calls across subsequent lines');
364
+ msg.push(' -k, --keep-array-indentation Preserve array indentation');
365
+ msg.push(' -x, --unescape-strings Decode printable characters encoded in xNN notation');
366
+ msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
367
+ msg.push(' -X, --e4x Pass E4X xml literals through untouched');
368
+ msg.push(' --good-stuff Warm the cockles of Crockford\'s heart');
369
+ msg.push(' -C, --comma-first Put commas at the beginning of new line instead of end');
370
+ msg.push(' -O, --operator-position Set operator position (before-newline|after-newline|preserve-newline) [before-newline]');
371
+ break;
372
+ case "html":
373
+ msg.push(' -b, --brace-style [collapse|expand|end-expand] ["collapse"]');
374
+ msg.push(' -I, --indent-inner-html Indent body and head sections. Default is false.');
375
+ msg.push(' -H, --indent-handlebars Indent handlebars. Default is false.');
376
+ msg.push(' -S, --indent-scripts [keep|separate|normal] ["normal"]');
377
+ msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
378
+ msg.push(' -A, --wrap-attributes Wrap html tag attributes to new lines [auto|force|force-aligned|force-expand-multiline|aligned-multiple|preserve|preserve-aligned] ["auto"]');
379
+ msg.push(' -i, --wrap-attributes-indent-size Indent wrapped tags to after N characters [indent-level]');
380
+ msg.push(' -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables)');
381
+ msg.push(' -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10]');
382
+ msg.push(' -U, --unformatted List of tags (defaults to inline) that should not be reformatted');
383
+ msg.push(' -T, --content_unformatted List of tags (defaults to pre) whose content should not be reformatted');
384
+ msg.push(' -E, --extra_liners List of tags (defaults to [head,body,/html] that should have an extra newline');
385
+ break;
386
+ case "css":
387
+ msg.push(' -L, --selector-separator-newline Add a newline between multiple selectors.');
388
+ msg.push(' -N, --newline-between-rules Add a newline between CSS rules.');
389
+ }
390
+
391
+ if (err) {
392
+ msg.push(err);
393
+ msg.push('');
394
+ console.error(msg.join('\n'));
395
+ } else {
396
+ console.log(msg.join('\n'));
397
+ }
394
398
  }
395
399
 
396
400
  // main iterator, {cfg} passed as thisArg of forEach call
397
401
 
398
402
  function processInputSync(filepath) {
399
- var data = '',
400
- config = this.cfg,
401
- outfile = config.outfile,
402
- input;
403
-
404
- // -o passed with no value overwrites
405
- if (outfile === true || config.replace) {
406
- outfile = filepath;
407
- }
408
-
409
- var fileType = getOutputType(outfile, filepath, config.type);
410
-
411
- if (config.editorconfig) {
412
- var editorconfig_filepath = filepath;
413
-
414
- if (editorconfig_filepath === '-') {
415
- if (outfile) {
416
- editorconfig_filepath = outfile;
417
- } else {
418
- editorconfig_filepath = 'stdin.' + fileType;
419
- }
403
+ var data = null,
404
+ config = this.cfg,
405
+ outfile = config.outfile,
406
+ input;
407
+
408
+ // -o passed with no value overwrites
409
+ if (outfile === true || config.replace) {
410
+ outfile = filepath;
420
411
  }
421
412
 
422
- debug("EditorConfig is enabled for ", editorconfig_filepath);
423
- config = cc(config).snapshot;
424
- set_file_editorconfig_opts(editorconfig_filepath, config);
425
- debug(config);
426
- }
413
+ var fileType = getOutputType(outfile, filepath, config.type);
427
414
 
428
- if (filepath === '-') {
429
- input = process.stdin;
430
- input.resume();
415
+ if (config.editorconfig) {
416
+ var editorconfig_filepath = filepath;
431
417
 
432
- input.setEncoding('utf8');
418
+ if (editorconfig_filepath === '-') {
419
+ if (outfile) {
420
+ editorconfig_filepath = outfile;
421
+ } else {
422
+ editorconfig_filepath = 'stdin.' + fileType;
423
+ }
424
+ }
433
425
 
434
- input.on('data', function(chunk) {
435
- data += chunk;
436
- });
426
+ debug("EditorConfig is enabled for ", editorconfig_filepath);
427
+ config = cc(config).snapshot;
428
+ set_file_editorconfig_opts(editorconfig_filepath, config);
429
+ debug(config);
430
+ }
437
431
 
438
- input.on('end', function() {
439
- makePretty(fileType, data, config, outfile, writePretty); // Where things get beautified
440
- });
441
- } else {
442
- data = fs.readFileSync(filepath, 'utf8');
443
- makePretty(fileType, data, config, outfile, writePretty);
444
- }
432
+ if (filepath === '-') {
433
+ input = process.stdin;
434
+
435
+ input.setEncoding('utf8');
436
+
437
+ input.on('error', function() {
438
+ throw 'Must pipe input or define at least one file.';
439
+ });
440
+
441
+ input.on('data', function(chunk) {
442
+ data = data || '';
443
+ data += chunk;
444
+ });
445
+
446
+ input.on('end', function() {
447
+ if (data === null) {
448
+ throw 'Must pipe input or define at least one file.';
449
+ }
450
+ makePretty(fileType, data, config, outfile, writePretty); // Where things get beautified
451
+ });
452
+
453
+ input.resume();
454
+
455
+ } else {
456
+ data = fs.readFileSync(filepath, 'utf8');
457
+ makePretty(fileType, data, config, outfile, writePretty);
458
+ }
445
459
  }
446
460
 
447
461
  function makePretty(fileType, code, config, outfile, callback) {
448
- try {
449
- var pretty = beautify[fileType](code, config);
462
+ try {
463
+ var pretty = beautify[fileType](code, config);
450
464
 
451
- callback(null, pretty, outfile, config);
452
- } catch (ex) {
453
- callback(ex);
454
- }
465
+ callback(null, pretty, outfile, config);
466
+ } catch (ex) {
467
+ callback(ex);
468
+ }
455
469
  }
456
470
 
457
471
  function writePretty(err, pretty, outfile, config) {
458
- debug('writing ' + outfile);
459
- if (err) {
460
- console.error(err);
461
- process.exit(1);
462
- }
463
-
464
- if (outfile) {
465
- mkdirp.sync(path.dirname(outfile));
466
-
467
- if (isFileDifferent(outfile, pretty)) {
468
- try {
469
- fs.writeFileSync(outfile, pretty, 'utf8');
470
- logToStdout('beautified ' + path.relative(process.cwd(), outfile), config);
471
- } catch (ex) {
472
- onOutputError(ex);
473
- }
472
+ debug('writing ' + outfile);
473
+ if (err) {
474
+ console.error(err);
475
+ process.exit(1);
476
+ }
477
+
478
+ if (outfile) {
479
+ mkdirp.sync(path.dirname(outfile));
480
+
481
+ if (isFileDifferent(outfile, pretty)) {
482
+ try {
483
+ fs.writeFileSync(outfile, pretty, 'utf8');
484
+ logToStdout('beautified ' + path.relative(process.cwd(), outfile), config);
485
+ } catch (ex) {
486
+ onOutputError(ex);
487
+ }
488
+ } else {
489
+ logToStdout('beautified ' + path.relative(process.cwd(), outfile) + ' - unchanged', config);
490
+ }
474
491
  } else {
475
- logToStdout('beautified ' + path.relative(process.cwd(), outfile) + ' - unchanged', config);
492
+ process.stdout.write(pretty);
476
493
  }
477
- } else {
478
- process.stdout.write(pretty);
479
- }
480
494
  }
481
495
 
482
496
  function isFileDifferent(filePath, expected) {
483
- try {
484
- return fs.readFileSync(filePath, 'utf8') !== expected;
485
- } catch (ex) {
486
- // failing to read is the same as different
487
- return true;
488
- }
497
+ try {
498
+ return fs.readFileSync(filePath, 'utf8') !== expected;
499
+ } catch (ex) {
500
+ // failing to read is the same as different
501
+ return true;
502
+ }
489
503
  }
490
504
 
491
505
  // workaround the fact that nopt.clean doesn't return the object passed in :P
492
506
 
493
507
  function cleanOptions(data, types) {
494
- nopt.clean(data, types);
495
- return data;
508
+ nopt.clean(data, types);
509
+ return data;
496
510
  }
497
511
 
498
512
  // error handler for output stream that swallows errors silently,
499
513
  // allowing the loop to continue over unwritable files.
500
514
 
501
515
  function onOutputError(err) {
502
- if (err.code === 'EACCES') {
503
- console.error(err.path + " is not writable. Skipping!");
504
- } else {
505
- console.error(err);
506
- process.exit(0);
507
- }
516
+ if (err.code === 'EACCES') {
517
+ console.error(err.path + " is not writable. Skipping!");
518
+ } else {
519
+ console.error(err);
520
+ process.exit(0);
521
+ }
508
522
  }
509
523
 
510
524
  // turn "--foo_bar" into "foo-bar"
511
525
 
512
526
  function dasherizeFlag(str) {
513
- return str.replace(/^\-+/, '').replace(/_/g, '-');
527
+ return str.replace(/^\-+/, '').replace(/_/g, '-');
514
528
  }
515
529
 
516
530
  // translate weird python underscored keys into dashed argv,
517
531
  // avoiding single character aliases.
518
532
 
519
533
  function dasherizeShorthands(hash) {
520
- // operate in-place
521
- Object.keys(hash).forEach(function(key) {
522
- // each key value is an array
523
- var val = hash[key][0];
524
- // only dasherize one-character shorthands
525
- if (key.length === 1 && val.indexOf('_') > -1) {
526
- hash[dasherizeFlag(val)] = val;
527
- }
528
- });
534
+ // operate in-place
535
+ Object.keys(hash).forEach(function(key) {
536
+ // each key value is an array
537
+ var val = hash[key][0];
538
+ // only dasherize one-character shorthands
539
+ if (key.length === 1 && val.indexOf('_') > -1) {
540
+ hash[dasherizeFlag(val)] = val;
541
+ }
542
+ });
529
543
 
530
- return hash;
544
+ return hash;
531
545
  }
532
546
 
533
547
  function getOutputType(outfile, filepath, configType) {
534
- if (outfile && /\.(js|css|html)$/.test(outfile)) {
535
- return outfile.split('.').pop();
536
- } else if (filepath !== '-' && /\.(js|css|html)$/.test(filepath)) {
537
- return filepath.split('.').pop();
538
- } else if (configType) {
539
- return configType;
540
- } else {
541
- throw 'Could not determine appropriate beautifier from file paths: ' + filepath;
542
- }
548
+ if (outfile && /\.(js|css|html)$/.test(outfile)) {
549
+ return outfile.split('.').pop();
550
+ } else if (filepath !== '-' && /\.(js|css|html)$/.test(filepath)) {
551
+ return filepath.split('.').pop();
552
+ } else if (configType) {
553
+ return configType;
554
+ } else {
555
+ throw 'Could not determine appropriate beautifier from file paths: ' + filepath;
556
+ }
543
557
  }
544
558
 
545
559
  function getScriptName() {
546
- return path.basename(process.argv[1]);
560
+ return path.basename(process.argv[1]);
547
561
  }
548
562
 
549
563
  function checkType(parsed) {
550
- var scriptType = getScriptName().split('-').shift();
551
- if (!/^(js|css|html)$/.test(scriptType)) {
552
- scriptType = null;
553
- }
564
+ var scriptType = getScriptName().split('-').shift();
565
+ if (!/^(js|css|html)$/.test(scriptType)) {
566
+ scriptType = null;
567
+ }
554
568
 
555
- debug("executable type:", scriptType);
569
+ debug("executable type:", scriptType);
556
570
 
557
- var parsedType = parsed.type;
558
- debug("parsed type:", parsedType);
571
+ var parsedType = parsed.type;
572
+ debug("parsed type:", parsedType);
559
573
 
560
- if (!parsedType) {
561
- debug("type defaulted:", scriptType);
562
- parsed.type = scriptType;
563
- }
574
+ if (!parsedType) {
575
+ debug("type defaulted:", scriptType);
576
+ parsed.type = scriptType;
577
+ }
564
578
  }
565
579
 
566
580
  function checkFiles(parsed) {
567
- var argv = parsed.argv;
568
- var isTTY = true;
581
+ var argv = parsed.argv;
582
+ var isTTY = true;
583
+ var file_params = parsed.files || [];
584
+ var hadGlob = false;
585
+
586
+ try {
587
+ isTTY = process.stdin.isTTY;
588
+ } catch (ex) {
589
+ debug("error querying for isTTY:", ex);
590
+ }
569
591
 
570
- try {
571
- isTTY = process.stdin.isTTY;
572
- } catch (ex) {
573
- debug("error querying for isTTY:", ex);
574
- }
592
+ debug('isTTY: ' + isTTY);
575
593
 
576
- debug('isTTY: ' + isTTY);
594
+ // assume any remaining args are files
595
+ file_params = file_params.concat(argv.remain);
577
596
 
578
- if (!parsed.files) {
579
597
  parsed.files = [];
580
- } else {
581
- if (argv.cooked.indexOf('-') > -1) {
582
- // strip stdin path eagerly added by nopt in '-f -' case
583
- parsed.files.some(removeDashedPath);
584
- }
585
- }
586
-
587
- if (argv.remain.length) {
588
598
  // assume any remaining args are files
589
- argv.remain.forEach(function(f) {
590
- if (f !== '-') {
591
- parsed.files.push(path.resolve(f));
592
- }
599
+ file_params.forEach(function(f) {
600
+ // strip stdin path eagerly added by nopt in '-f -' case
601
+ if (f === '-') {
602
+ return;
603
+ }
604
+
605
+ var foundFiles = [];
606
+ var isGlob = glob.hasMagic(f);
607
+
608
+ // Input was a glob
609
+ if (isGlob) {
610
+ hadGlob = true;
611
+ foundFiles = glob(f, {
612
+ sync: true,
613
+ absolute: true,
614
+ ignore: ['**/node_modules/**', '**/.git/**']
615
+ });
616
+ } else {
617
+ // Input was not a glob, add it to an array so we are able to handle it in the same loop below
618
+ testFilePath(f);
619
+ foundFiles = [f];
620
+ }
621
+
622
+ if (foundFiles && foundFiles.length) {
623
+ // Add files to the parsed.files if it didn't exist in the array yet
624
+ foundFiles.forEach(function(file) {
625
+ var filePath = path.resolve(file);
626
+ if (parsed.files.indexOf(filePath) === -1) {
627
+ parsed.files.push(filePath);
628
+ }
629
+ });
630
+ }
593
631
  });
594
- }
595
632
 
596
- if ('string' === typeof parsed.outfile && isTTY && !parsed.files.length) {
597
- // use outfile as input when no other files passed in args
598
- parsed.files.push(parsed.outfile);
599
- // operation is now an implicit overwrite
600
- parsed.replace = true;
601
- }
633
+ if ('string' === typeof parsed.outfile && isTTY && !parsed.files.length) {
634
+ testFilePath(parsed.outfile);
635
+ // use outfile as input when no other files passed in args
636
+ parsed.files.push(parsed.outfile);
637
+ // operation is now an implicit overwrite
638
+ parsed.replace = true;
639
+ }
602
640
 
603
- if (!parsed.files.length) {
604
- // read stdin by default
605
- parsed.files.push('-');
606
- }
607
- debug('files.length ' + parsed.files.length);
641
+ if (hadGlob || parsed.files.length > 1) {
642
+ parsed.replace = true;
643
+ }
608
644
 
609
- if (parsed.files.indexOf('-') > -1 && isTTY) {
610
- throw 'Must pipe input or define at least one file.';
611
- }
645
+ if (!parsed.files.length && !hadGlob) {
646
+ // read stdin by default
647
+ parsed.files.push('-');
648
+ }
612
649
 
613
- parsed.files.forEach(testFilePath);
650
+ debug('files.length ' + parsed.files.length);
614
651
 
615
- return parsed;
616
- }
652
+ if (parsed.files.indexOf('-') > -1 && isTTY && !hadGlob) {
653
+ throw 'Must pipe input or define at least one file.';
654
+ }
617
655
 
618
- function removeDashedPath(filepath, i, arr) {
619
- var found = filepath.lastIndexOf('-') === (filepath.length - 1);
620
- if (found) {
621
- arr.splice(i, 1);
622
- }
623
- return found;
656
+ return parsed;
624
657
  }
625
658
 
626
659
  function testFilePath(filepath) {
627
- try {
628
- if (filepath !== "-") {
629
- fs.statSync(filepath);
660
+ try {
661
+ if (filepath !== "-") {
662
+ fs.statSync(filepath);
663
+ }
664
+ } catch (err) {
665
+ throw 'Unable to open path "' + filepath + '"';
630
666
  }
631
- } catch (err) {
632
- throw 'Unable to open path "' + filepath + '"';
633
- }
634
667
  }
635
668
 
636
669
  function logToStdout(str, config) {
637
- if (typeof config.quiet === "undefined" || !config.quiet) {
638
- console.log(str);
639
- }
670
+ if (typeof config.quiet === "undefined" || !config.quiet) {
671
+ console.log(str);
672
+ }
640
673
  }