You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							692 lines
						
					
					
						
							24 KiB
						
					
					
				
			
		
		
	
	
							692 lines
						
					
					
						
							24 KiB
						
					
					
				#!/usr/bin/env node | 
						|
 | 
						|
/* | 
						|
  The MIT License (MIT) | 
						|
 | 
						|
  Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. | 
						|
 | 
						|
  Permission is hereby granted, free of charge, to any person | 
						|
  obtaining a copy of this software and associated documentation files | 
						|
  (the "Software"), to deal in the Software without restriction, | 
						|
  including without limitation the rights to use, copy, modify, merge, | 
						|
  publish, distribute, sublicense, and/or sell copies of the Software, | 
						|
  and to permit persons to whom the Software is furnished to do so, | 
						|
  subject to the following conditions: | 
						|
 | 
						|
  The above copyright notice and this permission notice shall be | 
						|
  included in all copies or substantial portions of the Software. | 
						|
 | 
						|
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
						|
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
						|
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
						|
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 
						|
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 
						|
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
						|
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
						|
  SOFTWARE. | 
						|
 | 
						|
  Js-Beautify Command-line for node.js | 
						|
  ------------------------------------- | 
						|
 | 
						|
  Written by Daniel Stockman (daniel.stockman@gmail.com) | 
						|
 | 
						|
*/ | 
						|
/*jshint strict:false */ | 
						|
 | 
						|
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('../index'), | 
						|
    mkdirp = require('mkdirp'), | 
						|
    nopt = require('nopt'), | 
						|
    glob = require('glob'); | 
						|
 | 
						|
nopt.invalidHandler = function(key, val) { | 
						|
    throw new Error(key + " was invalid with value \"" + val + "\""); | 
						|
}; | 
						|
 | 
						|
nopt.typeDefs.brace_style = { | 
						|
    type: "brace_style", | 
						|
    validate: function(data, key, val) { | 
						|
        data[key] = val; | 
						|
        // TODO: expand-strict is obsolete, now identical to expand.  Remove in future version | 
						|
        // TODO: collapse-preserve-inline is obselete, now identical to collapse,preserve-inline = true. Remove in future version | 
						|
        var validVals = ["collapse", "collapse-preserve-inline", "expand", "end-expand", "expand-strict", "none", "preserve-inline"]; | 
						|
        var valSplit = val.split(/[^a-zA-Z0-9_\-]+/); //Split will always return at least one parameter | 
						|
        for (var i = 0; i < valSplit.length; i++) { | 
						|
            if (validVals.indexOf(valSplit[i]) === -1) { | 
						|
                return false; | 
						|
            } | 
						|
        } | 
						|
        return true; | 
						|
    } | 
						|
}; | 
						|
var path = require('path'), | 
						|
    editorconfig = require('editorconfig'), | 
						|
    knownOpts = { | 
						|
        // Beautifier | 
						|
        "indent_size": Number, | 
						|
        "indent_char": String, | 
						|
        "eol": String, | 
						|
        "indent_level": Number, | 
						|
        "indent_with_tabs": Boolean, | 
						|
        "preserve_newlines": Boolean, | 
						|
        "max_preserve_newlines": Number, | 
						|
        "space_in_paren": Boolean, | 
						|
        "space_in_empty_paren": Boolean, | 
						|
        "jslint_happy": Boolean, | 
						|
        "space_after_anon_function": Boolean, | 
						|
        "space_after_named_function": Boolean, | 
						|
        "brace_style": "brace_style", //See above for validation | 
						|
        "unindent_chained_methods": Boolean, | 
						|
        "break_chained_methods": Boolean, | 
						|
        "keep_array_indentation": Boolean, | 
						|
        "unescape_strings": Boolean, | 
						|
        "wrap_line_length": Number, | 
						|
        "wrap_attributes": ["auto", "force", "force-aligned", "force-expand-multiline", "aligned-multiple", "preserve", "preserve-aligned"], | 
						|
        "wrap_attributes_indent_size": Number, | 
						|
        "e4x": Boolean, | 
						|
        "end_with_newline": Boolean, | 
						|
        "comma_first": Boolean, | 
						|
        "operator_position": ["before-newline", "after-newline", "preserve-newline"], | 
						|
        "indent_empty_lines": Boolean, | 
						|
        "templating": [String, Array], | 
						|
        // CSS-only | 
						|
        "selector_separator_newline": Boolean, | 
						|
        "newline_between_rules": Boolean, | 
						|
        "space_around_combinator": Boolean, | 
						|
        //deprecated - replaced with space_around_combinator, remove in future version | 
						|
        "space_around_selector_separator": Boolean, | 
						|
        // HTML-only | 
						|
        "max_char": Number, // obsolete since 1.3.5 | 
						|
        "inline": [String, Array], | 
						|
        "unformatted": [String, Array], | 
						|
        "content_unformatted": [String, Array], | 
						|
        "indent_inner_html": [Boolean], | 
						|
        "indent_handlebars": [Boolean], | 
						|
        "indent_scripts": ["keep", "separate", "normal"], | 
						|
        "extra_liners": [String, Array], | 
						|
        "unformatted_content_delimiter": String, | 
						|
        // CLI | 
						|
        "version": Boolean, | 
						|
        "help": Boolean, | 
						|
        "files": [path, Array], | 
						|
        "outfile": path, | 
						|
        "replace": Boolean, | 
						|
        "quiet": Boolean, | 
						|
        "type": ["js", "css", "html"], | 
						|
        "config": path, | 
						|
        "editorconfig": Boolean | 
						|
    }, | 
						|
    // dasherizeShorthands provides { "indent-size": ["--indent_size"] } | 
						|
    // translation, allowing more convenient dashes in CLI arguments | 
						|
    shortHands = dasherizeShorthands({ | 
						|
        // Beautifier | 
						|
        "s": ["--indent_size"], | 
						|
        "c": ["--indent_char"], | 
						|
        "e": ["--eol"], | 
						|
        "l": ["--indent_level"], | 
						|
        "t": ["--indent_with_tabs"], | 
						|
        "p": ["--preserve_newlines"], | 
						|
        "m": ["--max_preserve_newlines"], | 
						|
        "P": ["--space_in_paren"], | 
						|
        "Q": ["--space_in_empty_paren"], | 
						|
        "j": ["--jslint_happy"], | 
						|
        "a": ["--space_after_anon_function"], | 
						|
        "b": ["--brace_style"], | 
						|
        "u": ["--unindent_chained_methods"], | 
						|
        "B": ["--break_chained_methods"], | 
						|
        "k": ["--keep_array_indentation"], | 
						|
        "x": ["--unescape_strings"], | 
						|
        "w": ["--wrap_line_length"], | 
						|
        "X": ["--e4x"], | 
						|
        "n": ["--end_with_newline"], | 
						|
        "C": ["--comma_first"], | 
						|
        "O": ["--operator_position"], | 
						|
        // CSS-only | 
						|
        "L": ["--selector_separator_newline"], | 
						|
        "N": ["--newline_between_rules"], | 
						|
        // HTML-only | 
						|
        "A": ["--wrap_attributes"], | 
						|
        "i": ["--wrap_attributes_indent_size"], | 
						|
        "W": ["--max_char"], // obsolete since 1.3.5 | 
						|
        "d": ["--inline"], | 
						|
        "U": ["--unformatted"], | 
						|
        "T": ["--content_unformatted"], | 
						|
        "I": ["--indent_inner_html"], | 
						|
        "H": ["--indent_handlebars"], | 
						|
        "S": ["--indent_scripts"], | 
						|
        "E": ["--extra_liners"], | 
						|
        // non-dasherized hybrid shortcuts | 
						|
        "good-stuff": [ | 
						|
            "--keep_array_indentation", | 
						|
            "--keep_function_indentation", | 
						|
            "--jslint_happy" | 
						|
        ], | 
						|
        "js": ["--type", "js"], | 
						|
        "css": ["--type", "css"], | 
						|
        "html": ["--type", "html"], | 
						|
        // CLI | 
						|
        "v": ["--version"], | 
						|
        "h": ["--help"], | 
						|
        "f": ["--files"], | 
						|
        "file": ["--files"], | 
						|
        "o": ["--outfile"], | 
						|
        "r": ["--replace"], | 
						|
        "q": ["--quiet"] | 
						|
        // no shorthand for "config" | 
						|
        // no shorthand for "editorconfig" | 
						|
        // no shorthand for "indent_empty_lines" | 
						|
        // not shorthad for "templating" | 
						|
    }); | 
						|
 | 
						|
function verifyExists(fullPath) { | 
						|
    return fs.existsSync(fullPath) ? fullPath : null; | 
						|
} | 
						|
 | 
						|
function findRecursive(dir, fileName) { | 
						|
    var fullPath = path.join(dir, fileName); | 
						|
    var nextDir = path.dirname(dir); | 
						|
    var result = verifyExists(fullPath); | 
						|
 | 
						|
    if (!result && (nextDir !== dir)) { | 
						|
        result = findRecursive(nextDir, fileName); | 
						|
    } | 
						|
 | 
						|
    return result; | 
						|
} | 
						|
 | 
						|
function getUserHome() { | 
						|
    var user_home = ''; | 
						|
    try { | 
						|
        user_home = process.env.USERPROFILE || process.env.HOME || ''; | 
						|
    } catch (ex) {} | 
						|
    return user_home; | 
						|
} | 
						|
 | 
						|
function set_file_editorconfig_opts(file, config) { | 
						|
    try { | 
						|
        var eConfigs = editorconfig.parseSync(file); | 
						|
 | 
						|
        if (eConfigs.indent_style === "tab") { | 
						|
            config.indent_with_tabs = true; | 
						|
        } else if (eConfigs.indent_style === "space") { | 
						|
            config.indent_with_tabs = false; | 
						|
        } | 
						|
 | 
						|
        if (eConfigs.indent_size) { | 
						|
            config.indent_size = eConfigs.indent_size; | 
						|
        } | 
						|
 | 
						|
        if (eConfigs.max_line_length) { | 
						|
            if (eConfigs.max_line_length === "off") { | 
						|
                config.wrap_line_length = 0; | 
						|
            } else { | 
						|
                config.wrap_line_length = parseInt(eConfigs.max_line_length, 10); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        if (eConfigs.insert_final_newline === true) { | 
						|
            config.end_with_newline = true; | 
						|
        } else if (eConfigs.insert_final_newline === false) { | 
						|
            config.end_with_newline = false; | 
						|
        } | 
						|
 | 
						|
        if (eConfigs.end_of_line) { | 
						|
            if (eConfigs.end_of_line === 'cr') { | 
						|
                config.eol = '\r'; | 
						|
            } else if (eConfigs.end_of_line === 'lf') { | 
						|
                config.eol = '\n'; | 
						|
            } else if (eConfigs.end_of_line === 'crlf') { | 
						|
                config.eol = '\r\n'; | 
						|
            } | 
						|
        } | 
						|
    } catch (e) { | 
						|
        debug(e); | 
						|
    } | 
						|
} | 
						|
 | 
						|
// var cli = require('js-beautify/cli'); cli.interpret(); | 
						|
var interpret = exports.interpret = function(argv, slice) { | 
						|
    var parsed; | 
						|
    try { | 
						|
        parsed = nopt(knownOpts, shortHands, argv, slice); | 
						|
    } catch (ex) { | 
						|
        usage(ex); | 
						|
        // console.error(ex); | 
						|
        // console.error('Run `' + getScriptName() + ' -h` for help.'); | 
						|
        process.exit(1); | 
						|
    } | 
						|
 | 
						|
 | 
						|
    if (parsed.version) { | 
						|
        console.log(require('../../package.json').version); | 
						|
        process.exit(0); | 
						|
    } else if (parsed.help) { | 
						|
        usage(); | 
						|
        process.exit(0); | 
						|
    } | 
						|
 | 
						|
    var cfg; | 
						|
    var configRecursive = findRecursive(process.cwd(), '.jsbeautifyrc'); | 
						|
    var configHome = verifyExists(path.join(getUserHome() || "", ".jsbeautifyrc")); | 
						|
    var configDefault = __dirname + '/../config/defaults.json'; | 
						|
 | 
						|
    try { | 
						|
        cfg = cc( | 
						|
            parsed, | 
						|
            cleanOptions(cc.env('jsbeautify_'), knownOpts), | 
						|
            parsed.config, | 
						|
            configRecursive, | 
						|
            configHome, | 
						|
            configDefault | 
						|
        ).snapshot; | 
						|
    } catch (ex) { | 
						|
        debug(cfg); | 
						|
        // usage(ex); | 
						|
        console.error(ex); | 
						|
        console.error('Error while loading beautifier configuration.'); | 
						|
        console.error('Configuration file chain included:'); | 
						|
        if (parsed.config) { | 
						|
            console.error(parsed.config); | 
						|
        } | 
						|
        if (configRecursive) { | 
						|
            console.error(configRecursive); | 
						|
        } | 
						|
        if (configHome) { | 
						|
            console.error(configHome); | 
						|
        } | 
						|
        console.error(configDefault); | 
						|
        console.error('Run `' + getScriptName() + ' -h` for help.'); | 
						|
        process.exit(1); | 
						|
    } | 
						|
 | 
						|
    try { | 
						|
        // Verify arguments | 
						|
        checkType(cfg); | 
						|
        checkFiles(cfg); | 
						|
        debug(cfg); | 
						|
 | 
						|
        // Process files synchronously to avoid EMFILE error | 
						|
        cfg.files.forEach(processInputSync, { | 
						|
            cfg: cfg | 
						|
        }); | 
						|
    } catch (ex) { | 
						|
        debug(cfg); | 
						|
        // usage(ex); | 
						|
        console.error(ex); | 
						|
        console.error('Run `' + getScriptName() + ' -h` for help.'); | 
						|
        process.exit(1); | 
						|
    } | 
						|
}; | 
						|
 | 
						|
// interpret args immediately when called as executable | 
						|
if (require.main === module) { | 
						|
    interpret(); | 
						|
} | 
						|
 | 
						|
function usage(err) { | 
						|
    var scriptName = getScriptName(); | 
						|
    var msg = [ | 
						|
        scriptName + '@' + 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', | 
						|
        '  --type           [js|css|html] ["js"]', | 
						|
        '  -q, --quiet      Suppress logging to stdout', | 
						|
        '  -h, --help       Show this help', | 
						|
        '  -v, --version    Show the version', | 
						|
        '', | 
						|
        'Beautifier Options:', | 
						|
        '  -s, --indent-size                 Indentation size [4]', | 
						|
        '  -c, --indent-char                 Indentation character [" "]', | 
						|
        '  -t, --indent-with-tabs            Indent with tabs, overrides -s and -c', | 
						|
        '  -e, --eol                         Character(s) to use as line terminators.', | 
						|
        '                                    [first newline in file, otherwise "\\n]', | 
						|
        '  -n, --end-with-newline            End output with newline', | 
						|
        '  --indent-empty-lines              Keep indentation on empty lines', | 
						|
        '  --templating                      List of templating languages (auto,none,django,erb,handlebars,php) ["auto"] auto = none in JavaScript, all in html', | 
						|
        '  --editorconfig                    Use EditorConfig to set up the options' | 
						|
    ]; | 
						|
 | 
						|
    switch (scriptName.split('-').shift()) { | 
						|
        case "js": | 
						|
            msg.push('  -l, --indent-level                Initial indentation level [0]'); | 
						|
            msg.push('  -p, --preserve-newlines           Preserve line-breaks (--no-preserve-newlines disables)'); | 
						|
            msg.push('  -m, --max-preserve-newlines       Number of line-breaks to be preserved in one chunk [10]'); | 
						|
            msg.push('  -P, --space-in-paren              Add padding spaces within paren, ie. f( a, b )'); | 
						|
            msg.push('  -E, --space-in-empty-paren        Add a single space inside empty paren, ie. f( )'); | 
						|
            msg.push('  -j, --jslint-happy                Enable jslint-stricter mode'); | 
						|
            msg.push('  -a, --space-after-anon-function   Add a space before an anonymous function\'s parens, ie. function ()'); | 
						|
            msg.push('  --space_after_named_function      Add a space before a named function\'s parens, ie. function example ()'); | 
						|
            msg.push('  -b, --brace-style                 [collapse|expand|end-expand|none][,preserve-inline] [collapse,preserve-inline]'); | 
						|
            msg.push('  -u, --unindent-chained-methods    Don\'t indent chained method calls'); | 
						|
            msg.push('  -B, --break-chained-methods       Break chained method calls across subsequent lines'); | 
						|
            msg.push('  -k, --keep-array-indentation      Preserve array indentation'); | 
						|
            msg.push('  -x, --unescape-strings            Decode printable characters encoded in xNN notation'); | 
						|
            msg.push('  -w, --wrap-line-length            Wrap lines that exceed N characters [0]'); | 
						|
            msg.push('  -X, --e4x                         Pass E4X xml literals through untouched'); | 
						|
            msg.push('  --good-stuff                      Warm the cockles of Crockford\'s heart'); | 
						|
            msg.push('  -C, --comma-first                 Put commas at the beginning of new line instead of end'); | 
						|
            msg.push('  -O, --operator-position           Set operator position (before-newline|after-newline|preserve-newline) [before-newline]'); | 
						|
            break; | 
						|
        case "html": | 
						|
            msg.push('  -b, --brace-style                 [collapse|expand|end-expand] ["collapse"]'); | 
						|
            msg.push('  -I, --indent-inner-html           Indent body and head sections. Default is false.'); | 
						|
            msg.push('  -H, --indent-handlebars           Indent handlebars. Default is false.'); | 
						|
            msg.push('  -S, --indent-scripts              [keep|separate|normal] ["normal"]'); | 
						|
            msg.push('  -w, --wrap-line-length            Wrap lines that exceed N characters [0]'); | 
						|
            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"]'); | 
						|
            msg.push('  -i, --wrap-attributes-indent-size Indent wrapped tags to after N characters [indent-level]'); | 
						|
            msg.push('  -p, --preserve-newlines           Preserve line-breaks (--no-preserve-newlines disables)'); | 
						|
            msg.push('  -m, --max-preserve-newlines       Number of line-breaks to be preserved in one chunk [10]'); | 
						|
            msg.push('  -U, --unformatted                 List of tags (defaults to inline) that should not be reformatted'); | 
						|
            msg.push('  -T, --content_unformatted         List of tags (defaults to pre) whose content should not be reformatted'); | 
						|
            msg.push('  -E, --extra_liners                List of tags (defaults to [head,body,/html] that should have an extra newline'); | 
						|
            msg.push('  --unformatted_content_delimiter    Keep text content together between this string [""]'); | 
						|
            break; | 
						|
        case "css": | 
						|
            msg.push('  -L, --selector-separator-newline        Add a newline between multiple selectors.'); | 
						|
            msg.push('  -N, --newline-between-rules             Add a newline between CSS rules.'); | 
						|
    } | 
						|
 | 
						|
    if (err) { | 
						|
        msg.push(err); | 
						|
        msg.push(''); | 
						|
        console.error(msg.join('\n')); | 
						|
    } else { | 
						|
        console.log(msg.join('\n')); | 
						|
    } | 
						|
} | 
						|
 | 
						|
// main iterator, {cfg} passed as thisArg of forEach call | 
						|
 | 
						|
function processInputSync(filepath) { | 
						|
    var data = null, | 
						|
        config = this.cfg, | 
						|
        outfile = config.outfile, | 
						|
        input; | 
						|
 | 
						|
    // -o passed with no value overwrites | 
						|
    if (outfile === true || config.replace) { | 
						|
        outfile = filepath; | 
						|
    } | 
						|
 | 
						|
    var fileType = getOutputType(outfile, filepath, config.type); | 
						|
 | 
						|
    if (config.editorconfig) { | 
						|
        var editorconfig_filepath = filepath; | 
						|
 | 
						|
        if (editorconfig_filepath === '-') { | 
						|
            if (outfile) { | 
						|
                editorconfig_filepath = outfile; | 
						|
            } else { | 
						|
                editorconfig_filepath = 'stdin.' + fileType; | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        debug("EditorConfig is enabled for ", editorconfig_filepath); | 
						|
        config = cc(config).snapshot; | 
						|
        set_file_editorconfig_opts(editorconfig_filepath, config); | 
						|
        debug(config); | 
						|
    } | 
						|
 | 
						|
    if (filepath === '-') { | 
						|
        input = process.stdin; | 
						|
 | 
						|
        input.setEncoding('utf8'); | 
						|
 | 
						|
        input.on('error', function() { | 
						|
            throw 'Must pipe input or define at least one file.'; | 
						|
        }); | 
						|
 | 
						|
        input.on('data', function(chunk) { | 
						|
            data = data || ''; | 
						|
            data += chunk; | 
						|
        }); | 
						|
 | 
						|
        input.on('end', function() { | 
						|
            if (data === null) { | 
						|
                throw 'Must pipe input or define at least one file.'; | 
						|
            } | 
						|
            makePretty(fileType, data, config, outfile, writePretty); // Where things get beautified | 
						|
        }); | 
						|
 | 
						|
        input.resume(); | 
						|
 | 
						|
    } else { | 
						|
        data = fs.readFileSync(filepath, 'utf8'); | 
						|
        makePretty(fileType, data, config, outfile, writePretty); | 
						|
    } | 
						|
} | 
						|
 | 
						|
function makePretty(fileType, code, config, outfile, callback) { | 
						|
    try { | 
						|
        var pretty = beautify[fileType](code, config); | 
						|
 | 
						|
        callback(null, pretty, outfile, config); | 
						|
    } catch (ex) { | 
						|
        callback(ex); | 
						|
    } | 
						|
} | 
						|
 | 
						|
function writePretty(err, pretty, outfile, config) { | 
						|
    debug('writing ' + outfile); | 
						|
    if (err) { | 
						|
        console.error(err); | 
						|
        process.exit(1); | 
						|
    } | 
						|
 | 
						|
    if (outfile) { | 
						|
        mkdirp.sync(path.dirname(outfile)); | 
						|
 | 
						|
        if (isFileDifferent(outfile, pretty)) { | 
						|
            try { | 
						|
                fs.writeFileSync(outfile, pretty, 'utf8'); | 
						|
                logToStdout('beautified ' + path.relative(process.cwd(), outfile), config); | 
						|
            } catch (ex) { | 
						|
                onOutputError(ex); | 
						|
            } | 
						|
        } else { | 
						|
            logToStdout('beautified ' + path.relative(process.cwd(), outfile) + ' - unchanged', config); | 
						|
        } | 
						|
    } else { | 
						|
        process.stdout.write(pretty); | 
						|
    } | 
						|
} | 
						|
 | 
						|
function isFileDifferent(filePath, expected) { | 
						|
    try { | 
						|
        return fs.readFileSync(filePath, 'utf8') !== expected; | 
						|
    } catch (ex) { | 
						|
        // failing to read is the same as different | 
						|
        return true; | 
						|
    } | 
						|
} | 
						|
 | 
						|
// 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!"); | 
						|
    } else { | 
						|
        console.error(err); | 
						|
        process.exit(0); | 
						|
    } | 
						|
} | 
						|
 | 
						|
// 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 getOutputType(outfile, filepath, configType) { | 
						|
    if (outfile && /\.(js|css|html)$/.test(outfile)) { | 
						|
        return outfile.split('.').pop(); | 
						|
    } else if (filepath !== '-' && /\.(js|css|html)$/.test(filepath)) { | 
						|
        return filepath.split('.').pop(); | 
						|
    } else if (configType) { | 
						|
        return configType; | 
						|
    } else { | 
						|
        throw 'Could not determine appropriate beautifier from file paths: ' + filepath; | 
						|
    } | 
						|
} | 
						|
 | 
						|
function getScriptName() { | 
						|
    return path.basename(process.argv[1]); | 
						|
} | 
						|
 | 
						|
function checkType(parsed) { | 
						|
    var scriptType = getScriptName().split('-').shift(); | 
						|
    if (!/^(js|css|html)$/.test(scriptType)) { | 
						|
        scriptType = null; | 
						|
    } | 
						|
 | 
						|
    debug("executable type:", scriptType); | 
						|
 | 
						|
    var parsedType = parsed.type; | 
						|
    debug("parsed type:", parsedType); | 
						|
 | 
						|
    if (!parsedType) { | 
						|
        debug("type defaulted:", scriptType); | 
						|
        parsed.type = scriptType; | 
						|
    } | 
						|
} | 
						|
 | 
						|
function checkFiles(parsed) { | 
						|
    var argv = parsed.argv; | 
						|
    var isTTY = true; | 
						|
    var file_params = parsed.files || []; | 
						|
    var hadGlob = false; | 
						|
 | 
						|
    try { | 
						|
        isTTY = process.stdin.isTTY; | 
						|
    } catch (ex) { | 
						|
        debug("error querying for isTTY:", ex); | 
						|
    } | 
						|
 | 
						|
    debug('isTTY: ' + isTTY); | 
						|
 | 
						|
    // assume any remaining args are files | 
						|
    file_params = file_params.concat(argv.remain); | 
						|
 | 
						|
    parsed.files = []; | 
						|
    // assume any remaining args are files | 
						|
    file_params.forEach(function(f) { | 
						|
        // strip stdin path eagerly added by nopt in '-f -' case | 
						|
        if (f === '-') { | 
						|
            return; | 
						|
        } | 
						|
 | 
						|
        var foundFiles = []; | 
						|
        var isGlob = glob.hasMagic(f); | 
						|
 | 
						|
        // Input was a glob | 
						|
        if (isGlob) { | 
						|
            hadGlob = true; | 
						|
            foundFiles = glob(f, { | 
						|
                sync: true, | 
						|
                absolute: true, | 
						|
                ignore: ['**/node_modules/**', '**/.git/**'] | 
						|
            }); | 
						|
        } else { | 
						|
            // Input was not a glob, add it to an array so we are able to handle it in the same loop below | 
						|
            try { | 
						|
                testFilePath(f); | 
						|
            } catch (err) { | 
						|
                // if file is not found, and the resolved path indicates stdin marker | 
						|
                if (path.parse(f).base === '-') { | 
						|
                    f = '-'; | 
						|
                } else { | 
						|
                    throw err; | 
						|
                } | 
						|
            } | 
						|
            foundFiles = [f]; | 
						|
        } | 
						|
 | 
						|
        if (foundFiles && foundFiles.length) { | 
						|
            // Add files to the parsed.files if it didn't exist in the array yet | 
						|
            foundFiles.forEach(function(file) { | 
						|
                var filePath = path.resolve(file); | 
						|
                if (file === '-') { // case of stdin | 
						|
                    parsed.files.push(file); | 
						|
                } else if (parsed.files.indexOf(filePath) === -1) { | 
						|
                    parsed.files.push(filePath); | 
						|
                } | 
						|
            }); | 
						|
        } | 
						|
    }); | 
						|
 | 
						|
    if ('string' === typeof parsed.outfile && isTTY && !parsed.files.length) { | 
						|
        testFilePath(parsed.outfile); | 
						|
        // 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 (hadGlob || parsed.files.length > 1) { | 
						|
        parsed.replace = true; | 
						|
    } | 
						|
 | 
						|
    if (!parsed.files.length && !hadGlob) { | 
						|
        // read stdin by default | 
						|
        parsed.files.push('-'); | 
						|
    } | 
						|
 | 
						|
    debug('files.length ' + parsed.files.length); | 
						|
 | 
						|
    if (parsed.files.indexOf('-') > -1 && isTTY && !hadGlob) { | 
						|
        throw 'Must pipe input or define at least one file.'; | 
						|
    } | 
						|
 | 
						|
    return parsed; | 
						|
} | 
						|
 | 
						|
function testFilePath(filepath) { | 
						|
    try { | 
						|
        if (filepath !== "-") { | 
						|
            fs.statSync(filepath); | 
						|
        } | 
						|
    } catch (err) { | 
						|
        throw 'Unable to open path "' + filepath + '"'; | 
						|
    } | 
						|
} | 
						|
 | 
						|
function logToStdout(str, config) { | 
						|
    if (typeof config.quiet === "undefined" || !config.quiet) { | 
						|
        console.log(str); | 
						|
    } | 
						|
} |