from __future__ import print_function import sys import os import platform import io import getopt import re import string import errno import copy import glob from jsbeautifier.__version__ import __version__ from jsbeautifier.cli import * from jsbeautifier.javascript.options import BeautifierOptions from jsbeautifier.javascript.beautifier import Beautifier # # 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. # # Originally written by Einar Lielmanis et al., # Conversion to python by Einar Lielmanis, einar@beautifier.io, # Parsing improvement for brace-less and semicolon-less statements # by Liam Newman # Python is not my native language, feel free to push things around. # # Use either from command line (script displays its usage when run # without any parameters), # # # or, alternatively, use it as a module: # # import jsbeautifier # res = jsbeautifier.beautify('your javascript string') # res = jsbeautifier.beautify_file('some_file.js') # # you may specify some options: # # opts = jsbeautifier.default_options() # opts.indent_size = 2 # res = jsbeautifier.beautify('some javascript', opts) # # # Here are the available options: (read source) __all__ = [ "default_options", "beautify", "beautify_file", "usage", "main", ] def default_options(): return BeautifierOptions() def beautify(string, opts=default_options()): b = Beautifier() return b.beautify(string, opts) def beautify_file(file_name, opts=default_options()): return process_file(file_name, opts, beautify) def usage(stream=sys.stdout): print( "jsbeautifier.py@" + __version__ + """ Javascript beautifier (https://beautifier.io/) Usage: jsbeautifier.py [options] can be "-", which means stdin. Input options: -i, --stdin Read input from stdin Output options: -s, --indent-size=NUMBER Indentation size. (default 4). -c, --indent-char=CHAR Character to indent with. (default space). -e, --eol=STRING Character(s) to use as line terminators. (default first newline in file, otherwise "\\n") -t, --indent-with-tabs Indent with tabs, overrides -s and -c -d, --disable-preserve-newlines Do not preserve existing line breaks. -P, --space-in-paren Add padding spaces within paren, ie. f( a, b ) -E, --space-in-empty-paren Add a single space inside empty paren, ie. f( ) -j, --jslint-happy More jslint-compatible output -a, --space-after-anon-function Add a space before an anonymous function's parens, ie. function () --space-after-named-function Add a space before a named function's parens, i.e. function example () -b, --brace-style=collapse Brace style (collapse, expand, end-expand, none)(,preserve-inline) -k, --keep-array-indentation Keep array indentation. --quiet Suppress info about a file if nothing was changed. -r, --replace Write output in-place, replacing input -o, --outfile=FILE Specify a file to output to (default stdout) -f, --keep-function-indentation Do not re-indent function bodies defined in var lines. -x, --unescape-strings Decode printable chars encoded in \\xNN notation. -X, --e4x Pass E4X xml literals through untouched -C, --comma-first Put commas at the beginning of new line instead of end. -m, --max-preserve-newlines=NUMBER Number of line-breaks to be preserved in one chunk (default 10) -O, --operator-position=STRING Set operator position (before-newline, after-newline, preserve-newline) -w, --wrap-line-length Attempt to wrap line when it exceeds this length. NOTE: Line continues until next wrap point is found. -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,smarty,angular) ["auto"] auto = none in JavaScript, all in html --editorconfig Enable setting configuration from EditorConfig Rarely needed options: --eval-code evaluate code if a JS interpreter is installed. May be useful with some obfuscated script but poses a potential security issue. -l, --indent-level=NUMBER Initial indentation level. (default 0). -h, --help, --usage Prints this help statement. -v, --version Show the version """, file=stream, ) if stream == sys.stderr: return 1 else: return 0 def main(): argv = sys.argv[1:] try: opts, args = getopt.getopt( argv, "f:s:c:e:o:rdEPjab:kil:xhtvXnCO:w:m:", [ "brace-style=", "comma-first", "disable-preserve-newlines", "e4x", "editorconfig", "end-with-newline", "eol=", "eval-code", "file=", "help", "indent-char=", "indent-empty-lines", "indent-level=", "indent-size=", "indent-with-tabs", "jslint-happy", "keep-array-indentation", "keep-function-indentation", "max-preserve-newlines=", "operator-position=", "outfile=", "quiet", "replace", "space-after-anon-function", "space-after-named-function", "space-in-empty-paren", "space-in-paren", "stdin", "templating", "unescape-strings", "usage", "version", "wrap-line-length", ], ) except getopt.GetoptError as ex: print(ex, file=sys.stderr) return usage(sys.stderr) js_options = default_options() filepath_params = [] filepath_params.extend(args) outfile_param = "stdout" replace = False for opt, arg in opts: if opt in ("--file", "-f"): filepath_params.append(arg) elif opt in ("--keep-array-indentation", "-k"): js_options.keep_array_indentation = True elif opt in ("--keep-function-indentation",): js_options.keep_function_indentation = True elif opt in ("--outfile", "-o"): outfile_param = arg elif opt in ("--replace", "-r"): replace = True elif opt in ("--indent-size", "-s"): js_options.indent_size = int(arg) elif opt in ("--indent-char", "-c"): js_options.indent_char = arg elif opt in ("--eol", "-e"): js_options.eol = arg elif opt in ("--indent-with-tabs", "-t"): js_options.indent_with_tabs = True elif opt in ("--disable-preserve-newlines", "-d"): js_options.preserve_newlines = False elif opt in ("--max-preserve-newlines", "-m"): js_options.max_preserve_newlines = int(arg) elif opt in ("--space-in-paren", "-P"): js_options.space_in_paren = True elif opt in ("--space-in-empty-paren", "-E"): js_options.space_in_empty_paren = True elif opt in ("--jslint-happy", "-j"): js_options.jslint_happy = True elif opt in ("--space-after-anon-function", "-a"): js_options.space_after_anon_function = True elif opt in ("--space-after-named-function",): js_options.space_after_named_function = True elif opt in ("--eval-code",): js_options.eval_code = True elif opt in ("--quiet",): js_options.keep_quiet = True elif opt in ("--brace-style", "-b"): js_options.brace_style = arg elif opt in ("--unescape-strings", "-x"): js_options.unescape_strings = True elif opt in ("--e4x", "-X"): js_options.e4x = True elif opt in ("--end-with-newline", "-n"): js_options.end_with_newline = True elif opt in ("--comma-first", "-C"): js_options.comma_first = True elif opt in ("--operator-position", "-O"): js_options.operator_position = arg elif opt in ("--wrap-line-length ", "-w"): js_options.wrap_line_length = int(arg) elif opt in ("--indent-empty-lines",): js_options.indent_empty_lines = True elif opt in ("--templating",): js_options.templating = arg.split(",") elif opt in ("--stdin", "-i"): # stdin is the default if no files are passed filepath_params = [] elif opt in ("--editorconfig",): js_options.editorconfig = True elif opt in ("--version", "-v"): return print(__version__) elif opt in ("--help", "--usage", "-h"): return usage() try: filepaths, replace = get_filepaths_from_params(filepath_params, replace) for filepath in filepaths: if not replace: outfile = outfile_param else: outfile = filepath js_options = integrate_editorconfig_options( filepath, js_options, outfile, "js" ) pretty = beautify_file(filepath, js_options) write_beautified_output(pretty, js_options, outfile) except MissingInputStreamError: print("Must pipe input or define at least one file.\n", file=sys.stderr) usage(sys.stderr) return 1 except UnicodeError as ex: print("Error while decoding input or encoding output:", file=sys.stderr) print(ex, file=sys.stderr) return 1 except Exception as ex: print(ex, file=sys.stderr) return 1 # Success return 0 if __name__ == "__main__": main()