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