././@PaxHeader 0000000 0000000 0000000 00000000033 00000000000 010211 x ustar 00 27 mtime=1699316581.318391
jsbeautifier-1.14.11/ 0000755 0001751 0000177 00000000000 14522301545 013741 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/MANIFEST.in 0000644 0001751 0000177 00000000055 14522301436 015476 0 ustar 00runner docker include js-beautify
include js-beautify-test
././@PaxHeader 0000000 0000000 0000000 00000000033 00000000000 010211 x ustar 00 27 mtime=1699316581.318391
jsbeautifier-1.14.11/PKG-INFO 0000644 0001751 0000177 00000000470 14522301545 015037 0 ustar 00runner docker Metadata-Version: 2.1
Name: jsbeautifier
Version: 1.14.11
Summary: JavaScript unobfuscator and beautifier.
Home-page: https://beautifier.io
Author: Liam Newman, Einar Lielmanis, et al.
Author-email: team@beautifier.io
License: MIT
Beautify, unpack or deobfuscate JavaScript. Handles popular online obfuscators.
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/js-beautify-test 0000755 0001751 0000177 00000000215 14522301436 017063 0 ustar 00runner docker #! /bin/sh
#
# Test suite launcher
#
if [ -z $PYTHON ]; then
env python js-beautify-test.py
else
env $PYTHON js-beautify-test.py
fi
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1699316581.3143911
jsbeautifier-1.14.11/jsbeautifier/ 0000755 0001751 0000177 00000000000 14522301545 016415 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/__init__.py 0000644 0001751 0000177 00000026112 14522301436 020527 0 ustar 00runner docker 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) ["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()
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316558.0
jsbeautifier-1.14.11/jsbeautifier/__version__.py 0000644 0001751 0000177 00000000030 14522301516 021237 0 ustar 00runner docker __version__ = "1.14.11"
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1699316581.3143911
jsbeautifier-1.14.11/jsbeautifier/cli/ 0000755 0001751 0000177 00000000000 14522301545 017164 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/cli/__init__.py 0000644 0001751 0000177 00000021022 14522301436 021271 0 ustar 00runner docker 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.javascript.options import BeautifierOptions
from jsbeautifier.javascript.beautifier import Beautifier
#
# The MIT License (MIT)
# Copyright (c) 2007-2020 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.
__all__ = [
"MissingInputStreamError",
"process_file",
"get_filepaths_from_params",
"integrate_editorconfig_options",
"write_beautified_output",
]
class MissingInputStreamError(Exception):
pass
def set_file_editorconfig_opts(filename, js_options):
from editorconfig import get_properties, EditorConfigError
try:
_ecoptions = get_properties(os.path.abspath(filename))
if _ecoptions.get("indent_style") == "tab":
js_options.indent_with_tabs = True
elif _ecoptions.get("indent_style") == "space":
js_options.indent_with_tabs = False
if _ecoptions.get("indent_size"):
js_options.indent_size = int(_ecoptions["indent_size"])
if _ecoptions.get("max_line_length"):
if _ecoptions.get("max_line_length") == "off":
js_options.wrap_line_length = 0
else:
js_options.wrap_line_length = int(_ecoptions["max_line_length"])
if _ecoptions.get("insert_final_newline") == "true":
js_options.end_with_newline = True
elif _ecoptions.get("insert_final_newline") == "false":
js_options.end_with_newline = False
if _ecoptions.get("end_of_line"):
if _ecoptions["end_of_line"] == "cr":
js_options.eol = "\r"
elif _ecoptions["end_of_line"] == "lf":
js_options.eol = "\n"
elif _ecoptions["end_of_line"] == "crlf":
js_options.eol = "\r\n"
except EditorConfigError:
# do not error on bad editor config
print("Error loading EditorConfig. Ignoring.", file=sys.stderr)
def process_file(file_name, opts, beautify_code):
input_string = ""
if file_name == "-": # stdin
if sys.stdin.isatty():
raise MissingInputStreamError()
stream = sys.stdin
if platform.platform().lower().startswith("windows"):
if sys.version_info.major >= 3:
# for python 3 on windows this prevents conversion
stream = io.TextIOWrapper(sys.stdin.buffer, newline="")
elif platform.architecture()[0] == "32bit":
# for python 2 x86 on windows this prevents conversion
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
else:
raise Exception(
"Pipe to stdin not supported on Windows with Python 2.x 64-bit."
)
input_string = stream.read()
# if you pipe an empty string, that is a failure
if input_string == "":
raise MissingInputStreamError()
else:
stream = io.open(file_name, "rt", newline="", encoding="UTF-8")
input_string = stream.read()
return beautify_code(input_string, opts)
def mkdir_p(path):
try:
if path:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise Exception()
def isFileDifferent(filepath, expected):
try:
return "".join(io.open(filepath, "rt", newline="").readlines()) != expected
except BaseException:
return True
def get_filepaths_from_params(filepath_params, replace):
filepaths = []
if not filepath_params or (len(filepath_params) == 1 and filepath_params[0] == "-"):
# default to stdin
filepath_params = []
filepaths.append("-")
for filepath_param in filepath_params:
# ignore stdin setting if files are specified
if "-" == filepath_param:
continue
# Check if each literal filepath exists
if os.path.isfile(filepath_param):
filepaths.append(filepath_param)
elif "*" in filepath_param or "?" in filepath_param:
# handle globs
# empty result is okay
if sys.version_info.major == 2 or (
sys.version_info.major == 3 and sys.version_info.minor <= 4
):
if "**" in filepath_param:
raise Exception("Recursive globs not supported on Python <= 3.4.")
filepaths.extend(glob.glob(filepath_param))
else:
filepaths.extend(glob.glob(filepath_param, recursive=True))
else:
# not a glob and not a file
raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), filepath_param)
if len(filepaths) > 1:
replace = True
elif filepaths and filepaths[0] == "-":
replace = False
# remove duplicates
filepaths = set(filepaths)
return filepaths, replace
def integrate_editorconfig_options(filepath, local_options, outfile, default_file_type):
# Editorconfig used only on files, not stdin
if getattr(local_options, "editorconfig"):
editorconfig_filepath = filepath
if editorconfig_filepath == "-":
if outfile != "stdout":
editorconfig_filepath = outfile
else:
fileType = default_file_type
editorconfig_filepath = "stdin." + fileType
# debug("EditorConfig is enabled for ", editorconfig_filepath);
local_options = copy.copy(local_options)
set_file_editorconfig_opts(editorconfig_filepath, local_options)
return local_options
def write_beautified_output(pretty, local_options, outfile):
if outfile == "stdout":
stream = sys.stdout
# python automatically converts newlines in text to "\r\n" when on windows
# switch to binary to prevent this
if platform.platform().lower().startswith("windows"):
if sys.version_info.major >= 3:
# for python 3 on windows this prevents conversion
stream = io.TextIOWrapper(sys.stdout.buffer, newline="")
elif platform.architecture()[0] == "32bit":
# for python 2 x86 on windows this prevents conversion
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
else:
raise Exception(
"Pipe to stdout not supported on Windows with Python 2.x 64-bit."
)
stream.write(pretty)
else:
if isFileDifferent(outfile, pretty):
mkdir_p(os.path.dirname(outfile))
# python automatically converts newlines in text to "\r\n" when on windows
# set newline to empty to prevent this
with io.open(outfile, "wt", newline="", encoding="UTF-8") as f:
if not local_options.keep_quiet:
print("beautified " + outfile, file=sys.stdout)
try:
f.write(pretty)
except TypeError:
# This is not pretty, but given how we did the version import
# it is the only way to do this without having setup.py
# fail on a missing six dependency.
six = __import__("six")
f.write(six.u(pretty))
elif not local_options.keep_quiet:
print("beautified " + outfile + " - unchanged", file=sys.stdout)
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1699316581.3143911
jsbeautifier-1.14.11/jsbeautifier/core/ 0000755 0001751 0000177 00000000000 14522301545 017345 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/__init__.py 0000644 0001751 0000177 00000000020 14522301436 021445 0 ustar 00runner docker # Empty file :)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/directives.py 0000644 0001751 0000177 00000004221 14522301436 022056 0 ustar 00runner docker # 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.
import re
class Directives:
def __init__(self, start_block_pattern, end_block_pattern):
self.__directives_block_pattern = re.compile(
start_block_pattern + r" beautify( \w+[:]\w+)+ " + end_block_pattern
)
self.__directive_pattern = re.compile(r" (\w+)[:](\w+)")
self.__directives_end_ignore_pattern = re.compile(
start_block_pattern + r"\sbeautify\signore:end\s" + end_block_pattern
)
def get_directives(self, text):
if not self.__directives_block_pattern.match(text):
return None
directives = {}
directive_match = self.__directive_pattern.search(text)
while directive_match:
directives[directive_match.group(1)] = directive_match.group(2)
directive_match = self.__directive_pattern.search(
text, directive_match.end()
)
return directives
def readIgnored(self, input):
return input.readUntilAfter(self.__directives_end_ignore_pattern)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/inputscanner.py 0000644 0001751 0000177 00000011043 14522301436 022426 0 ustar 00runner docker # 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.
import re
class InputScanner:
def __init__(self, input_string):
self.__six = __import__("six")
if input_string is None:
input_string = ""
self.__input = input_string
self.__input_length = len(self.__input)
self.__position = 0
def restart(self):
self.__position = 0
def back(self):
if self.__position > 0:
self.__position -= 1
def hasNext(self):
return self.__position < self.__input_length
def next(self):
val = None
if self.hasNext():
val = self.__input[self.__position]
self.__position += 1
return val
def peek(self, index=0):
val = None
index += self.__position
if index >= 0 and index < self.__input_length:
val = self.__input[index]
return val
def test(self, pattern, index=0):
index += self.__position
return (
index >= 0
and index < self.__input_length
and bool(pattern.match(self.__input, index))
)
def testChar(self, pattern, index=0):
# test one character regex match
val = self.peek(index)
return val is not None and bool(pattern.match(val))
def match(self, pattern):
pattern_match = None
if self.hasNext():
pattern_match = pattern.match(self.__input, self.__position)
if bool(pattern_match):
self.__position = pattern_match.end(0)
return pattern_match
def read(self, starting_pattern, until_pattern=None, until_after=False):
val = ""
pattern_match = None
if bool(starting_pattern):
pattern_match = self.match(starting_pattern)
if bool(pattern_match):
val = pattern_match.group(0)
if bool(until_pattern) and (bool(pattern_match) or not bool(starting_pattern)):
val += self.readUntil(until_pattern, until_after)
return val
def readUntil(self, pattern, include_match=False):
val = ""
pattern_match = None
match_index = self.__position
if self.hasNext():
pattern_match = pattern.search(self.__input, self.__position)
if bool(pattern_match):
if include_match:
match_index = pattern_match.end(0)
else:
match_index = pattern_match.start(0)
else:
match_index = self.__input_length
val = self.__input[self.__position : match_index]
self.__position = match_index
return val
def readUntilAfter(self, pattern):
return self.readUntil(pattern, True)
def get_regexp(self, pattern, match_from=False):
result = None
# strings are converted to regexp
if isinstance(pattern, self.__six.string_types) and pattern != "":
result = re.compile(pattern)
elif pattern is not None:
result = re.compile(pattern.pattern)
return result
# css beautifier legacy helpers
def peekUntilAfter(self, pattern):
start = self.__position
val = self.readUntilAfter(pattern)
self.__position = start
return val
def lookBack(self, testVal):
start = self.__position - 1
return (
start >= len(testVal)
and self.__input[start - len(testVal) : start].lower() == testVal
)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/options.py 0000644 0001751 0000177 00000017655 14522301436 021427 0 ustar 00runner docker # 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.
import copy
import re
from collections import namedtuple
class Options:
def __init__(self, options=None, merge_child_field=None):
self.css = None
self.js = None
self.html = None
self.raw_options = _mergeOpts(options, merge_child_field)
# Support passing the source text back with no change
self.disabled = self._get_boolean("disabled")
self.eol = self._get_characters("eol", "auto")
self.end_with_newline = self._get_boolean("end_with_newline")
self.indent_size = self._get_number("indent_size", 4)
self.indent_char = self._get_characters("indent_char", " ")
self.indent_level = self._get_number("indent_level")
self.preserve_newlines = self._get_boolean("preserve_newlines", True)
self.max_preserve_newlines = self._get_number("max_preserve_newlines", 32786)
if not self.preserve_newlines:
self.max_preserve_newlines = 0
self.indent_with_tabs = self._get_boolean(
"indent_with_tabs", self.indent_char == "\t"
)
if self.indent_with_tabs:
self.indent_char = "\t"
# indent_size behavior changed after 1.8.6
# It used to be that indent_size would be
# set to 1 for indent_with_tabs. That is no longer needed and
# actually doesn't make sense - why not use spaces? Further,
# that might produce unexpected behavior - tabs being used
# for single-column alignment. So, when indent_with_tabs is true
# and indent_size is 1, reset indent_size to 4.
if self.indent_size == 1:
self.indent_size = 4
# Backwards compat with 1.3.x
self.wrap_line_length = self._get_number(
"wrap_line_length", self._get_number("max_char")
)
# Support editor config setting
self.editorconfig = False
self.indent_empty_lines = self._get_boolean("indent_empty_lines")
# valid templating languages ['django', 'erb', 'handlebars', 'php', 'smarty']
# For now, 'auto' = all off for javascript, all on for html (and inline javascript).
# other values ignored
self.templating = self._get_selection_list(
"templating",
["auto", "none", "django", "erb", "handlebars", "php", "smarty"],
["auto"],
)
def _get_array(self, name, default_value=[]):
option_value = getattr(self.raw_options, name, default_value)
result = []
if isinstance(option_value, list):
result = copy.copy(option_value)
elif isinstance(option_value, str):
result = re.compile(r"[^a-zA-Z0-9_/\-]+").split(option_value)
return result
def _get_boolean(self, name, default_value=False):
option_value = getattr(self.raw_options, name, default_value)
result = False
try:
result = bool(option_value)
except ValueError:
pass
return result
def _get_characters(self, name, default_value=""):
option_value = getattr(self.raw_options, name, default_value)
result = ""
if isinstance(option_value, str):
result = (
option_value.replace("\\r", "\r")
.replace("\\n", "\n")
.replace("\\t", "\t")
)
return result
def _get_number(self, name, default_value=0):
option_value = getattr(self.raw_options, name, default_value)
result = 0
try:
result = int(option_value)
except ValueError:
pass
return result
def _get_selection(self, name, selection_list, default_value=None):
result = self._get_selection_list(name, selection_list, default_value)
if len(result) != 1:
raise ValueError(
"Invalid Option Value: The option '"
+ name
+ "' can only be one of the following values:\n"
+ str(selection_list)
+ "\nYou passed in: '"
+ str(getattr(self.raw_options, name, None))
+ "'"
)
return result[0]
def _get_selection_list(self, name, selection_list, default_value=None):
if not selection_list:
raise ValueError("Selection list cannot be empty.")
default_value = default_value or [selection_list[0]]
if not self._is_valid_selection(default_value, selection_list):
raise ValueError("Invalid Default Value!")
result = self._get_array(name, default_value)
if not self._is_valid_selection(result, selection_list):
raise ValueError(
"Invalid Option Value: The option '"
+ name
+ "' can contain only the following values:\n"
+ str(selection_list)
+ "\nYou passed in: '"
+ str(getattr(self.raw_options, name, None))
+ "'"
)
return result
def _is_valid_selection(self, result, selection_list):
if len(result) == 0 or len(selection_list) == 0:
return False
for item in result:
if item not in selection_list:
return False
return True
# merges child options up with the parent options object
# Example: obj = {a: 1, b: {a: 2}}
# mergeOpts(obj, 'b')
#
# Returns: {a: 2}
def _mergeOpts(options, childFieldName):
if options is None:
options = {}
if isinstance(options, tuple):
options = dict(options)
options = _normalizeOpts(options)
finalOpts = copy.copy(options)
if isinstance(options, dict):
local = finalOpts.get(childFieldName, None)
if local:
del finalOpts[childFieldName]
for key in local:
finalOpts[key] = local[key]
finalOpts = namedtuple("CustomOptions", finalOpts.keys())(*finalOpts.values())
if isinstance(options, Options):
local = getattr(finalOpts, childFieldName, None)
if local:
delattr(finalOpts, childFieldName)
for key in local:
setattr(finalOpts, key, local[key])
return finalOpts
def _normalizeOpts(options):
convertedOpts = copy.copy(options)
if isinstance(convertedOpts, dict):
option_keys = list(convertedOpts.keys())
for key in option_keys:
if "-" in key:
del convertedOpts[key]
convertedOpts[key.replace("-", "_")] = options[key]
else:
option_keys = list(getattr(convertedOpts, "__dict__", {}))
for key in option_keys:
if "-" in key:
delattr(convertedOpts, key)
setattr(
convertedOpts, key.replace("-", "_"), getattr(options, key, None)
)
return convertedOpts
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/output.py 0000644 0001751 0000177 00000027460 14522301436 021267 0 ustar 00runner docker # 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.
import re
import math
# Using object instead of string to allow for later expansion of info
# about each line
__all__ = ["Output"]
class OutputLine:
def __init__(self, parent):
self.__parent = parent
self.__character_count = 0
self.__indent_count = -1
self.__alignment_count = 0
self.__wrap_point_index = 0
self.__wrap_point_character_count = 0
self.__wrap_point_indent_count = -1
self.__wrap_point_alignment_count = 0
self.__items = []
def clone_empty(self):
line = OutputLine(self.__parent)
line.set_indent(self.__indent_count, self.__alignment_count)
return line
def item(self, index):
return self.__items[index]
def is_empty(self):
return len(self.__items) == 0
def set_indent(self, indent=0, alignment=0):
if self.is_empty():
self.__indent_count = indent
self.__alignment_count = alignment
self.__character_count = self.__parent.get_indent_size(
self.__indent_count, self.__alignment_count
)
def _set_wrap_point(self):
if self.__parent.wrap_line_length:
self.__wrap_point_index = len(self.__items)
self.__wrap_point_character_count = self.__character_count
self.__wrap_point_indent_count = self.__parent.next_line.__indent_count
self.__wrap_point_alignment_count = (
self.__parent.next_line.__alignment_count
)
def _should_wrap(self):
return (
self.__wrap_point_index
and self.__character_count > self.__parent.wrap_line_length
and self.__wrap_point_character_count
> self.__parent.next_line.__character_count
)
def _allow_wrap(self):
if self._should_wrap():
self.__parent.add_new_line()
next = self.__parent.current_line
next.set_indent(
self.__wrap_point_indent_count, self.__wrap_point_alignment_count
)
next.__items = self.__items[self.__wrap_point_index :]
self.__items = self.__items[: self.__wrap_point_index]
next.__character_count += (
self.__character_count - self.__wrap_point_character_count
)
self.__character_count = self.__wrap_point_character_count
if next.__items[0] == " ":
next.__items.pop(0)
next.__character_count -= 1
return True
return False
def last(self):
if not self.is_empty():
return self.__items[-1]
return None
def push(self, item):
self.__items.append(item)
last_newline_index = item.rfind("\n")
if last_newline_index != -1:
self.__character_count = len(item) - last_newline_index
else:
self.__character_count += len(item)
def pop(self):
item = None
if not self.is_empty():
item = self.__items.pop()
self.__character_count -= len(item)
return item
def _remove_indent(self):
if self.__indent_count > 0:
self.__indent_count -= 1
self.__character_count -= self.__parent.indent_size
def _remove_wrap_indent(self):
if self.__wrap_point_indent_count > 0:
self.__wrap_point_indent_count -= 1
def trim(self):
while self.last() == " ":
self.__items.pop()
self.__character_count -= 1
def toString(self):
result = ""
if self.is_empty():
if self.__parent.indent_empty_lines:
result = self.__parent.get_indent_string(self.__indent_count)
else:
result = self.__parent.get_indent_string(
self.__indent_count, self.__alignment_count
)
result += "".join(self.__items)
return result
class IndentStringCache:
def __init__(self, options, base_string):
self.__cache = [""]
self.__indent_size = options.indent_size
self.__indent_string = options.indent_char
if not options.indent_with_tabs:
self.__indent_string = options.indent_char * options.indent_size
# Set to null to continue support of auto detection of base indent
base_string = base_string or ""
if options.indent_level > 0:
base_string = options.indent_level * self.__indent_string
self.__base_string = base_string
self.__base_string_length = len(base_string)
def get_indent_size(self, indent, column=0):
result = self.__base_string_length
if indent < 0:
result = 0
result += indent * self.__indent_size
result += column
return result
def get_indent_string(self, indent_level, column=0):
result = self.__base_string
if indent_level < 0:
indent_level = 0
result = ""
column += indent_level * self.__indent_size
self.__ensure_cache(column)
result += self.__cache[column]
return result
def __ensure_cache(self, column):
while column >= len(self.__cache):
self.__add_column()
def __add_column(self):
column = len(self.__cache)
indent = 0
result = ""
if self.__indent_size and column >= self.__indent_size:
indent = int(math.floor(column / self.__indent_size))
column -= indent * self.__indent_size
result = indent * self.__indent_string
if column:
result += column * " "
self.__cache.append(result)
class Output:
def __init__(self, options, baseIndentString=""):
self.__indent_cache = IndentStringCache(options, baseIndentString)
self.raw = False
self._end_with_newline = options.end_with_newline
self.indent_size = options.indent_size
self.wrap_line_length = options.wrap_line_length
self.indent_empty_lines = options.indent_empty_lines
self.__lines = []
self.previous_line = None
self.current_line = None
self.next_line = OutputLine(self)
self.space_before_token = False
self.non_breaking_space = False
self.previous_token_wrapped = False
# initialize
self.__add_outputline()
def __add_outputline(self):
self.previous_line = self.current_line
self.current_line = self.next_line.clone_empty()
self.__lines.append(self.current_line)
def get_line_number(self):
return len(self.__lines)
def get_indent_string(self, indent, column=0):
return self.__indent_cache.get_indent_string(indent, column)
def get_indent_size(self, indent, column=0):
return self.__indent_cache.get_indent_size(indent, column)
def is_empty(self):
return self.previous_line is None and self.current_line.is_empty()
def add_new_line(self, force_newline=False):
# never newline at the start of file
# otherwise, newline only if we didn't just add one or we're forced
if self.is_empty() or (not force_newline and self.just_added_newline()):
return False
# if raw output is enabled, don't print additional newlines,
# but still return True as though you had
if not self.raw:
self.__add_outputline()
return True
def get_code(self, eol):
self.trim(True)
# handle some edge cases where the last tokens
# has text that ends with newline(s)
last_item = self.current_line.pop()
if last_item:
if last_item[-1] == "\n":
last_item = re.sub(r"[\n]+$", "", last_item)
self.current_line.push(last_item)
if self._end_with_newline:
self.__add_outputline()
sweet_code = "\n".join(line.toString() for line in self.__lines)
if not eol == "\n":
sweet_code = sweet_code.replace("\n", eol)
return sweet_code
def set_wrap_point(self):
self.current_line._set_wrap_point()
def set_indent(self, indent=0, alignment=0):
# Next line stores alignment values
self.next_line.set_indent(indent, alignment)
# Never indent your first output indent at the start of the file
if len(self.__lines) > 1:
self.current_line.set_indent(indent, alignment)
return True
self.current_line.set_indent()
return False
def add_raw_token(self, token):
for _ in range(token.newlines):
self.__add_outputline()
self.current_line.set_indent(-1)
self.current_line.push(token.whitespace_before)
self.current_line.push(token.text)
self.space_before_token = False
self.non_breaking_space = False
self.previous_token_wrapped = False
def add_token(self, printable_token):
self.__add_space_before_token()
self.current_line.push(printable_token)
self.space_before_token = False
self.non_breaking_space = False
self.previous_token_wrapped = self.current_line._allow_wrap()
def __add_space_before_token(self):
if self.space_before_token and not self.just_added_newline():
if not self.non_breaking_space:
self.set_wrap_point()
self.current_line.push(" ")
self.space_before_token = False
def remove_indent(self, index):
while index < len(self.__lines):
self.__lines[index]._remove_indent()
index += 1
self.current_line._remove_wrap_indent()
def trim(self, eat_newlines=False):
self.current_line.trim()
while eat_newlines and len(self.__lines) > 1 and self.current_line.is_empty():
self.__lines.pop()
self.current_line = self.__lines[-1]
self.current_line.trim()
if len(self.__lines) > 1:
self.previous_line = self.__lines[-2]
else:
self.previous_line = None
def just_added_newline(self):
return self.current_line.is_empty()
def just_added_blankline(self):
return self.is_empty() or (
self.current_line.is_empty() and self.previous_line.is_empty()
)
def ensure_empty_line_above(self, starts_with, ends_with):
index = len(self.__lines) - 2
while index >= 0:
potentialEmptyLine = self.__lines[index]
if potentialEmptyLine.is_empty():
break
elif (
not potentialEmptyLine.item(0).startswith(starts_with)
and potentialEmptyLine.item(-1) != ends_with
):
self.__lines.insert(index + 1, OutputLine(self))
self.previous_line = self.__lines[-2]
break
index -= 1
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/pattern.py 0000644 0001751 0000177 00000005712 14522301436 021400 0 ustar 00runner docker # 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.
__all__ = ["Pattern"]
class Pattern:
def __init__(self, input_scanner, parent=None):
self._input = input_scanner
self._starting_pattern = None
self._match_pattern = None
self._until_pattern = None
self._until_after = False
if parent is not None:
self._starting_pattern = self._input.get_regexp(parent._starting_pattern)
self._match_pattern = self._input.get_regexp(parent._match_pattern)
self._until_pattern = self._input.get_regexp(parent._until_pattern)
self._until_after = parent._until_after
def read(self):
result = self._input.read(self._starting_pattern)
if (self._starting_pattern is None) or result:
result += self._input.read(
self._match_pattern, self._until_pattern, self._until_after
)
return result
def read_match(self):
return self._input.match(self._match_pattern)
def until_after(self, pattern):
result = self._create()
result._until_after = True
result._until_pattern = self._input.get_regexp(pattern)
result._update()
return result
def until(self, pattern):
result = self._create()
result._until_after = False
result._until_pattern = self._input.get_regexp(pattern)
result._update()
return result
def starting_with(self, pattern):
result = self._create()
result._starting_pattern = self._input.get_regexp(pattern)
result._update()
return result
def matching(self, pattern):
result = self._create()
result._match_pattern = self._input.get_regexp(pattern)
result._update()
return result
def _create(self):
return Pattern(self._input, self)
def _update(self):
pass
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/templatablepattern.py 0000644 0001751 0000177 00000017127 14522301436 023616 0 ustar 00runner docker # 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.
import copy
from ..core.pattern import Pattern
__all__ = ["TemplatablePattern"]
class TemplateNames:
def __init__(self):
self.django = False
self.erb = False
self.handlebars = False
self.php = False
self.smarty = False
class TemplatePatterns:
def __init__(self, input_scanner):
pattern = Pattern(input_scanner)
self.handlebars_comment = pattern.starting_with(r"{{!--").until_after(r"--}}")
self.handlebars_unescaped = pattern.starting_with(r"{{{").until_after(r"}}}")
self.handlebars = pattern.starting_with(r"{{").until_after(r"}}")
self.php = pattern.starting_with(r"<\?(?:[= ]|php)").until_after(r"\?>")
self.erb = pattern.starting_with(r"<%[^%]").until_after(r"[^%]%>")
# django coflicts with handlebars a bit.
self.django = pattern.starting_with(r"{%").until_after(r"%}")
self.django_value = pattern.starting_with(r"{{").until_after(r"}}")
self.django_comment = pattern.starting_with(r"{#").until_after(r"#}")
self.smarty_value = pattern.starting_with(r"{(?=[^}{\s\n])").until_after(r"}")
self.smarty_comment = pattern.starting_with(r"{\*").until_after(r"\*}")
self.smarty_literal = pattern.starting_with(r"{literal}").until_after(
r"{/literal}"
)
class TemplatablePattern(Pattern):
def __init__(self, input_scanner, parent=None):
Pattern.__init__(self, input_scanner, parent)
self.__template_pattern = None
self._disabled = TemplateNames()
self._excluded = TemplateNames()
if parent is not None:
self.__template_pattern = self._input.get_regexp(parent.__template_pattern)
self._disabled = copy.copy(parent._disabled)
self._excluded = copy.copy(parent._excluded)
self.__patterns = TemplatePatterns(input_scanner)
def _create(self):
return TemplatablePattern(self._input, self)
def _update(self):
self.__set_templated_pattern()
def read_options(self, options):
result = self._create()
for language in ["django", "erb", "handlebars", "php", "smarty"]:
setattr(result._disabled, language, not (language in options.templating))
result._update()
return result
def disable(self, language):
result = self._create()
setattr(result._disabled, language, True)
result._update()
return result
def exclude(self, language):
result = self._create()
setattr(result._excluded, language, True)
result._update()
return result
def read(self):
result = ""
if bool(self._match_pattern):
result = self._input.read(self._starting_pattern)
else:
result = self._input.read(self._starting_pattern, self.__template_pattern)
next = self._read_template()
while bool(next):
if self._match_pattern is not None:
next += self._input.read(self._match_pattern)
else:
next += self._input.readUntil(self.__template_pattern)
result += next
next = self._read_template()
if self._until_after:
result += self._input.readUntilAfter(self._until_after)
return result
def __set_templated_pattern(self):
items = list()
if not self._disabled.php:
items.append(self.__patterns.php._starting_pattern.pattern)
if not self._disabled.handlebars:
items.append(self.__patterns.handlebars._starting_pattern.pattern)
if not self._disabled.erb:
items.append(self.__patterns.erb._starting_pattern.pattern)
if not self._disabled.django:
items.append(self.__patterns.django._starting_pattern.pattern)
# The starting pattern for django is more complex because it has different
# patterns for value, comment, and other sections
items.append(self.__patterns.django_value._starting_pattern.pattern)
items.append(self.__patterns.django_comment._starting_pattern.pattern)
if not self._disabled.smarty:
items.append(self.__patterns.smarty._starting_pattern.pattern)
if self._until_pattern:
items.append(self._until_pattern.pattern)
self.__template_pattern = self._input.get_regexp(r"(?:" + "|".join(items) + ")")
def _read_template(self):
resulting_string = ""
c = self._input.peek()
if c == "<":
peek1 = self._input.peek(1)
if not self._disabled.php and not self._excluded.php and peek1 == "?":
resulting_string = resulting_string or self.__patterns.php.read()
if not self._disabled.erb and not self._excluded.erb and peek1 == "%":
resulting_string = resulting_string or self.__patterns.erb.read()
elif c == "{":
if not self._disabled.handlebars and not self._excluded.handlebars:
resulting_string = (
resulting_string or self.__patterns.handlebars_comment.read()
)
resulting_string = (
resulting_string or self.__patterns.handlebars_unescaped.read()
)
resulting_string = resulting_string or self.__patterns.handlebars.read()
if not self._disabled.django:
# django coflicts with handlebars a bit.
if not self._excluded.django and not self._excluded.handlebars:
resulting_string = (
resulting_string or self.__patterns.django_value.read()
)
if not self._excluded.django:
resulting_string = (
resulting_string or self.__patterns.django_comment.read()
)
resulting_string = resulting_string or self.__patterns.django.read()
if not self._disabled.smarty:
# smarty cannot be enabled with django or handlebars enabled
if self._disabled.django and self._disabled.handlebars:
resulting_string = (
resulting_string or self.__patterns.smarty_comment.read()
)
resulting_string = (
resulting_string or self.__patterns.smarty_literal.read()
)
resulting_string = resulting_string or self.__patterns.smarty.read()
return resulting_string
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/token.py 0000644 0001751 0000177 00000003056 14522301436 021042 0 ustar 00runner docker # 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.
class Token:
def __init__(self, type, text, newlines=0, whitespace_before=""):
self.type = type
self.text = text
self.comments_before = None
self.newlines = newlines
self.whitespace_before = whitespace_before
self.parent = None
self.next = None
self.previous = None
self.opened = None
self.closed = None
self.directives = None
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/tokenizer.py 0000644 0001751 0000177 00000010445 14522301436 021734 0 ustar 00runner docker # 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.
import re
from ..core.inputscanner import InputScanner
from ..core.token import Token
from ..core.tokenstream import TokenStream
from ..core.pattern import Pattern
from ..core.whitespacepattern import WhitespacePattern
__all__ = ["TOKEN", "Tokenizer", "TokenizerPatterns", "TokenTypes"]
class TokenTypes:
START = "TK_START"
RAW = "TK_RAW"
EOF = "TK_EOF"
def __init__(self):
pass
TOKEN = TokenTypes()
class TokenizerPatterns:
def __init__(self, input_scanner):
self.whitespace = WhitespacePattern(input_scanner)
class Tokenizer:
def __init__(self, input_string, options):
self._input = InputScanner(input_string)
self._options = options
self.__tokens = None
self._patterns = TokenizerPatterns(self._input)
def tokenize(self):
self._input.restart()
self.__tokens = TokenStream()
current = None
previous = Token(TOKEN.START, "")
open_token = None
open_stack = []
comments = TokenStream()
while previous.type != TOKEN.EOF:
current = self.__get_next_token_with_comments(previous, open_token)
if self._is_opening(current):
open_stack.append(open_token)
open_token = current
elif open_token is not None and self._is_closing(current, open_token):
current.opened = open_token
open_token.closed = current
open_token = open_stack.pop()
current.parent = open_token
self.__tokens.add(current)
previous = current
return self.__tokens
def __get_next_token_with_comments(self, previous, open_token):
current = self._get_next_token(previous, open_token)
if self._is_comment(current):
comments = TokenStream()
while self._is_comment(current):
comments.add(current)
current = self._get_next_token(previous, open_token)
if not comments.isEmpty():
current.comments_before = comments
comments = TokenStream()
current.parent = open_token
current.previous = previous
previous.next = current
return current
def _is_first_token(self):
return self.__tokens.isEmpty()
def _reset(self):
pass
def _get_next_token(self, previous_token, open_token):
self._readWhitespace()
resulting_string = self._input.read(re.compile(r".+"))
if resulting_string:
return self._create_token(TOKEN.RAW, resulting_string)
else:
return self._create_token(TOKEN.EOF, "")
def _is_comment(self, current_token):
return False
def _is_opening(self, current_token):
return False
def _is_closing(self, current_token, open_token):
return False
def _create_token(self, token_type, text):
token = Token(
token_type,
text,
self._patterns.whitespace.newline_count,
self._patterns.whitespace.whitespace_before_token,
)
return token
def _readWhitespace(self):
return self._patterns.whitespace.read()
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/tokenstream.py 0000644 0001751 0000177 00000004454 14522301436 022261 0 ustar 00runner docker # 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.
import re
from ..core.inputscanner import InputScanner
from ..core.token import Token
class TokenStream:
def __init__(self, parent_token=None):
self.__tokens = []
self.__tokens_length = len(self.__tokens)
self.__position = 0
self.__parent_token = parent_token
def restart(self):
self.__position = 0
def isEmpty(self):
return self.__tokens_length == 0
def hasNext(self):
return self.__position < self.__tokens_length
def next(self):
if self.hasNext():
val = self.__tokens[self.__position]
self.__position += 1
return val
else:
raise StopIteration
def peek(self, index=0):
val = None
index += self.__position
if index >= 0 and index < self.__tokens_length:
val = self.__tokens[index]
return val
def add(self, token):
if self.__parent_token:
token.parent = self.__parent_token
self.__tokens.append(token)
self.__tokens_length += 1
def __iter__(self):
self.restart()
return self
def __next__(self):
return self.next()
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/core/whitespacepattern.py 0000644 0001751 0000177 00000005304 14522301436 023452 0 ustar 00runner docker # 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.
import re
from ..core.pattern import Pattern
__all__ = ["WhitespacePattern"]
class WhitespacePattern(Pattern):
def __init__(self, input_scanner, parent=None):
Pattern.__init__(self, input_scanner, parent)
if parent is not None:
self._newline_regexp = self._input.get_regexp(parent._newline_regexp)
else:
self.__set_whitespace_patterns("", "")
self.newline_count = 0
self.whitespace_before_token = ""
def __set_whitespace_patterns(self, whitespace_chars, newline_chars):
whitespace_chars += "\\t "
newline_chars += "\\n\\r"
self._match_pattern = self._input.get_regexp(
"[" + whitespace_chars + newline_chars + "]+"
)
self._newline_regexp = self._input.get_regexp("\\r\\n|[" + newline_chars + "]")
def read(self):
self.newline_count = 0
self.whitespace_before_token = ""
resulting_string = self._input.read(self._match_pattern)
if resulting_string == " ":
self.whitespace_before_token = " "
elif bool(resulting_string):
lines = self._newline_regexp.split(resulting_string)
self.newline_count = len(lines) - 1
self.whitespace_before_token = lines[-1]
return resulting_string
def matching(self, whitespace_chars, newline_chars):
result = self._create()
result.__set_whitespace_patterns(whitespace_chars, newline_chars)
result._update()
return result
def _create(self):
return WhitespacePattern(self._input, self)
././@PaxHeader 0000000 0000000 0000000 00000000033 00000000000 010211 x ustar 00 27 mtime=1699316581.318391
jsbeautifier-1.14.11/jsbeautifier/javascript/ 0000755 0001751 0000177 00000000000 14522301545 020563 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/javascript/__init__.py 0000644 0001751 0000177 00000000020 14522301436 022663 0 ustar 00runner docker # Empty file :)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/javascript/acorn.py 0000644 0001751 0000177 00000022410 14522301436 022235 0 ustar 00runner docker import re
# This section of code was translated to python from acorn (javascript).
#
# Acorn was written by Marijn Haverbeke and released under an MIT
# license. The Unicode regexps (for identifiers and whitespace) were
# taken from [Esprima](http://esprima.org) by Ariya Hidayat.
#
# Git repositories for Acorn are available at
#
# http://marijnhaverbeke.nl/git/acorn
# https://github.com/marijnh/acorn.git
# This is not pretty, but given how we did the version import
# it is the only way to do this without having setup.py fail on a missing
# six dependency.
six = __import__("six")
# ## Character categories
# acorn used char codes to squeeze the last bit of performance out
# Beautifier is okay without that, so we're using regex
# permit #(23), $ (36), and @ (64). @ is used in ES7 decorators.
# 65 through 91 are uppercase letters.
# permit _ (95).
# 97 through 123 are lowercase letters.
_baseASCIIidentifierStartChars = six.u(r"\x23\x24\x40\x41-\x5a\x5f\x61-\x7a")
# inside an identifier @ is not allowed but 0-9 are.
_baseASCIIidentifierChars = six.u(r"\x24\x30-\x39\x41-\x5a\x5f\x61-\x7a")
# Big ugly regular expressions that match characters in the
# whitespace, identifier, and identifier-start categories. These
# are only applied when a character is found to actually have a
# code point above 128.
# IMPORTANT: These strings must be run through six to handle \u chars
_nonASCIIidentifierStartChars = six.u(
r"\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"
)
_nonASCIIidentifierChars = six.u(
r"\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"
)
# _nonASCIIidentifierStart = re.compile("[" + _nonASCIIidentifierStartChars + "]")
# _nonASCIIidentifier = re.compile("[" + _nonASCIIidentifierStartChars + _nonASCIIidentifierChars + "]")
_unicodeEscapeOrCodePoint = six.u(r"\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}")
_identifierStart = (
six.u("(?:")
+ _unicodeEscapeOrCodePoint
+ six.u("|[")
+ _baseASCIIidentifierStartChars
+ _nonASCIIidentifierStartChars
+ six.u("])")
)
_identifierChars = (
six.u("(?:")
+ _unicodeEscapeOrCodePoint
+ six.u("|[")
+ _baseASCIIidentifierChars
+ _nonASCIIidentifierStartChars
+ _nonASCIIidentifierChars
+ six.u("])*")
)
identifier = re.compile(_identifierStart + _identifierChars)
identifierStart = re.compile(_identifierStart)
identifierMatch = re.compile(
six.u("(?:")
+ _unicodeEscapeOrCodePoint
+ six.u("|[")
+ _baseASCIIidentifierChars
+ _nonASCIIidentifierStartChars
+ _nonASCIIidentifierChars
+ six.u("])+")
)
_nonASCIIwhitespace = re.compile(
six.u(r"[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]")
)
# Whether a single character denotes a newline.
# IMPORTANT: This string must be run through six to handle \u chars
newline = re.compile(six.u(r"[\n\r\u2028\u2029]"))
# Matches a whole line break (where CRLF is considered a single
# line break). Used to count lines.
# in javascript, these two differ
# in python they are the same, different methods are called on them
# IMPORTANT: This string must be run through six to handle \u chars
lineBreak = re.compile(six.u(r"\r\n|[\n\r\u2028\u2029]"))
allLineBreaks = lineBreak
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/javascript/beautifier.py 0000644 0001751 0000177 00000177023 14522301436 023265 0 ustar 00runner docker # 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.
import re
import string
import copy
from ..core.token import Token
from .tokenizer import Tokenizer
from .tokenizer import TOKEN
from .options import BeautifierOptions
from ..core.output import Output
def default_options():
return BeautifierOptions()
class BeautifierFlags:
def __init__(self, mode):
self.mode = mode
self.parent = None
self.last_token = Token(TOKEN.START_BLOCK, "")
self.last_word = ""
self.declaration_statement = False
self.declaration_assignment = False
self.multiline_frame = False
self.inline_frame = False
self.if_block = False
self.else_block = False
self.class_start_block = False
self.do_block = False
self.do_while = False
self.import_block = False
self.in_case = False
self.in_case_statement = False
self.case_body = False
self.case_block = False
self.indentation_level = 0
self.alignment = 0
self.line_indent_level = 0
self.start_line_index = 0
self.ternary_depth = 0
def apply_base(self, flags_base, added_newline):
next_indent_level = flags_base.indentation_level
if not added_newline and flags_base.line_indent_level > next_indent_level:
next_indent_level = flags_base.line_indent_level
self.parent = flags_base
self.last_token = flags_base.last_token
self.last_word = flags_base.last_word
self.indentation_level = next_indent_level
OPERATOR_POSITION = {
"before_newline": "before-newline",
"after_newline": "after-newline",
"preserve_newline": "preserve-newline",
}
OPERATOR_POSITION_BEFORE_OR_PRESERVE = [
OPERATOR_POSITION["before_newline"],
OPERATOR_POSITION["preserve_newline"],
]
class MODE:
(
BlockStatement,
Statement,
ObjectLiteral,
ArrayLiteral,
ForInitializer,
Conditional,
Expression,
) = range(7)
def remove_redundant_indentation(output, frame):
# This implementation is effective but has some issues:
# - can cause line wrap to happen too soon due to indent removal
# after wrap points are calculated
# These issues are minor compared to ugly indentation.
if (
frame.multiline_frame
or frame.mode == MODE.ForInitializer
or frame.mode == MODE.Conditional
):
return
# remove one indent from each line inside this section
output.remove_indent(frame.start_line_index)
def reserved_word(token, word):
return token and token.type == TOKEN.RESERVED and token.text == word
def reserved_array(token, words):
return token and token.type == TOKEN.RESERVED and token.text in words
_special_word_set = frozenset(
[
"case",
"return",
"do",
"if",
"throw",
"else",
"await",
"break",
"continue",
"async",
]
)
class Beautifier:
def __init__(self, opts=None):
import jsbeautifier.javascript.acorn as acorn
self.acorn = acorn
self._options = BeautifierOptions(opts)
self._blank_state()
def _blank_state(self, js_source_text=None):
if js_source_text is None:
js_source_text = ""
# internal flags
self._flags = None
self._previous_flags = None
self._flag_store = []
self._tokens = None
if self._options.eol == "auto":
self._options.eol = "\n"
if self.acorn.lineBreak.search(js_source_text or ""):
self._options.eol = self.acorn.lineBreak.search(js_source_text).group()
baseIndentString = re.search("^[\t ]*", js_source_text).group(0)
self._last_last_text = "" # pre-last token text
self._output = Output(self._options, baseIndentString)
# If testing the ignore directive, start with output disable set to
# true
self._output.raw = self._options.test_output_raw
self.set_mode(MODE.BlockStatement)
return js_source_text
def beautify(self, source_text="", opts=None):
if opts is not None:
self._options = BeautifierOptions(opts)
source_text = source_text or ""
if self._options.disabled:
return source_text
source_text = self._blank_state(source_text)
source_text = self.unpack(source_text, self._options.eval_code)
self._tokens = Tokenizer(source_text, self._options).tokenize()
for current_token in self._tokens:
self.handle_token(current_token)
self._last_last_text = self._flags.last_token.text
self._flags.last_token = current_token
sweet_code = self._output.get_code(self._options.eol)
return sweet_code
def handle_token(self, current_token, preserve_statement_flags=False):
if current_token.type == TOKEN.START_EXPR:
self.handle_start_expr(current_token)
elif current_token.type == TOKEN.END_EXPR:
self.handle_end_expr(current_token)
elif current_token.type == TOKEN.START_BLOCK:
self.handle_start_block(current_token)
elif current_token.type == TOKEN.END_BLOCK:
self.handle_end_block(current_token)
elif current_token.type == TOKEN.WORD:
self.handle_word(current_token)
elif current_token.type == TOKEN.RESERVED:
self.handle_word(current_token)
elif current_token.type == TOKEN.SEMICOLON:
self.handle_semicolon(current_token)
elif current_token.type == TOKEN.STRING:
self.handle_string(current_token)
elif current_token.type == TOKEN.EQUALS:
self.handle_equals(current_token)
elif current_token.type == TOKEN.OPERATOR:
self.handle_operator(current_token)
elif current_token.type == TOKEN.COMMA:
self.handle_comma(current_token)
elif current_token.type == TOKEN.BLOCK_COMMENT:
self.handle_block_comment(current_token, preserve_statement_flags)
elif current_token.type == TOKEN.COMMENT:
self.handle_comment(current_token, preserve_statement_flags)
elif current_token.type == TOKEN.DOT:
self.handle_dot(current_token)
elif current_token.type == TOKEN.EOF:
self.handle_eof(current_token)
elif current_token.type == TOKEN.UNKNOWN:
self.handle_unknown(current_token, preserve_statement_flags)
else:
self.handle_unknown(current_token, preserve_statement_flags)
def handle_whitespace_and_comments(
self, current_token, preserve_statement_flags=False
):
newlines = current_token.newlines
keep_whitespace = self._options.keep_array_indentation and self.is_array(
self._flags.mode
)
if current_token.comments_before is not None:
for comment_token in current_token.comments_before:
# The cleanest handling of inline comments is to treat them
# as though they aren't there.
# Just continue formatting and the behavior should be logical.
# Also ignore unknown tokens. Again, this should result in better
# behavior.
self.handle_whitespace_and_comments(
comment_token, preserve_statement_flags
)
self.handle_token(comment_token, preserve_statement_flags)
if keep_whitespace:
for i in range(newlines):
self.print_newline(i > 0, preserve_statement_flags)
else: # not keep_whitespace
if (
self._options.max_preserve_newlines != 0
and newlines > self._options.max_preserve_newlines
):
newlines = self._options.max_preserve_newlines
if self._options.preserve_newlines and newlines > 1:
self.print_newline(False, preserve_statement_flags)
for i in range(1, newlines):
self.print_newline(True, preserve_statement_flags)
def unpack(self, source, evalcode=False):
import jsbeautifier.unpackers as unpackers
try:
return unpackers.run(source, evalcode)
except unpackers.UnpackingError:
return source
def is_array(self, mode):
return mode == MODE.ArrayLiteral
def is_expression(self, mode):
return (
mode == MODE.Expression
or mode == MODE.ForInitializer
or mode == MODE.Conditional
)
_newline_restricted_tokens = frozenset(
["async", "break", "continue", "return", "throw", "yield"]
)
def allow_wrap_or_preserved_newline(self, current_token, force_linewrap=False):
# never wrap the first token of a line.
if self._output.just_added_newline():
return
shouldPreserveOrForce = (
self._options.preserve_newlines and current_token.newlines
) or force_linewrap
operatorLogicApplies = (
self._flags.last_token.text in Tokenizer.positionable_operators
or current_token.text in Tokenizer.positionable_operators
)
if operatorLogicApplies:
shouldPrintOperatorNewline = (
self._flags.last_token.text in Tokenizer.positionable_operators
and self._options.operator_position
in OPERATOR_POSITION_BEFORE_OR_PRESERVE
) or current_token.text in Tokenizer.positionable_operators
shouldPreserveOrForce = shouldPreserveOrForce and shouldPrintOperatorNewline
if shouldPreserveOrForce:
self.print_newline(preserve_statement_flags=True)
elif self._options.wrap_line_length > 0:
if reserved_array(self._flags.last_token, self._newline_restricted_tokens):
# These tokens should never have a newline inserted between
# them and the following expression.
return
self._output.set_wrap_point()
def print_newline(self, force_newline=False, preserve_statement_flags=False):
if not preserve_statement_flags:
if (
self._flags.last_token.text != ";"
and self._flags.last_token.text != ","
and self._flags.last_token.text != "="
and (
self._flags.last_token.type != TOKEN.OPERATOR
or self._flags.last_token.text == "--"
or self._flags.last_token.text == "++"
)
):
next_token = self._tokens.peek()
while (
self._flags.mode == MODE.Statement
and not (self._flags.if_block and reserved_word(next_token, "else"))
and not self._flags.do_block
):
self.restore_mode()
if self._output.add_new_line(force_newline):
self._flags.multiline_frame = True
def print_token_line_indentation(self, current_token):
if self._output.just_added_newline():
line = self._output.current_line
if (
self._options.keep_array_indentation
and current_token.newlines
and (self.is_array(self._flags.mode) or current_token.text == "[")
):
line.set_indent(-1)
line.push(current_token.whitespace_before)
self._output.space_before_token = False
elif self._output.set_indent(
self._flags.indentation_level, self._flags.alignment
):
self._flags.line_indent_level = self._flags.indentation_level
def print_token(self, current_token, s=None):
if self._output.raw:
self._output.add_raw_token(current_token)
return
if (
self._options.comma_first
and current_token.previous
and current_token.previous.type == TOKEN.COMMA
and self._output.just_added_newline()
):
if self._output.previous_line.last() == ",":
# if the comma was already at the start of the line,
# pull back onto that line and reprint the indentation
popped = self._output.previous_line.pop()
if self._output.previous_line.is_empty():
self._output.previous_line.push(popped)
self._output.trim(True)
self._output.current_line.pop()
self._output.trim()
# add the comma in front of the next token
self.print_token_line_indentation(current_token)
self._output.add_token(",")
self._output.space_before_token = True
if s is None:
s = current_token.text
self.print_token_line_indentation(current_token)
self._output.non_breaking_space = True
self._output.add_token(s)
if self._output.previous_token_wrapped:
self._flags.multiline_frame = True
def indent(self):
self._flags.indentation_level += 1
self._output.set_indent(self._flags.indentation_level, self._flags.alignment)
def deindent(self):
allow_deindent = self._flags.indentation_level > 0 and (
(self._flags.parent is None)
or self._flags.indentation_level > self._flags.parent.indentation_level
)
if allow_deindent:
self._flags.indentation_level -= 1
self._output.set_indent(self._flags.indentation_level, self._flags.alignment)
def set_mode(self, mode):
if self._flags:
self._flag_store.append(self._flags)
self._previous_flags = self._flags
else:
self._previous_flags = BeautifierFlags(mode)
self._flags = BeautifierFlags(mode)
self._flags.apply_base(self._previous_flags, self._output.just_added_newline())
self._flags.start_line_index = self._output.get_line_number()
self._output.set_indent(self._flags.indentation_level, self._flags.alignment)
def restore_mode(self):
if len(self._flag_store) > 0:
self._previous_flags = self._flags
self._flags = self._flag_store.pop()
if self._previous_flags.mode == MODE.Statement:
remove_redundant_indentation(self._output, self._previous_flags)
self._output.set_indent(self._flags.indentation_level, self._flags.alignment)
def start_of_object_property(self):
return (
self._flags.parent.mode == MODE.ObjectLiteral
and self._flags.mode == MODE.Statement
and (
(self._flags.last_token.text == ":" and self._flags.ternary_depth == 0)
or (reserved_array(self._flags.last_token, ["get", "set"]))
)
)
def start_of_statement(self, current_token):
start = False
start = start or (
reserved_array(self._flags.last_token, ["var", "let", "const"])
and current_token.type == TOKEN.WORD
)
start = start or reserved_word(self._flags.last_token, "do")
start = start or (
not (
self._flags.parent.mode == MODE.ObjectLiteral
and self._flags.mode == MODE.Statement
)
and reserved_array(self._flags.last_token, self._newline_restricted_tokens)
and not current_token.newlines
)
start = start or (
reserved_word(self._flags.last_token, "else")
and not (
reserved_word(current_token, "if")
and current_token.comments_before is None
)
)
start = start or (
self._flags.last_token.type == TOKEN.END_EXPR
and (
self._previous_flags.mode == MODE.ForInitializer
or self._previous_flags.mode == MODE.Conditional
)
)
start = start or (
self._flags.last_token.type == TOKEN.WORD
and self._flags.mode == MODE.BlockStatement
and not self._flags.in_case
and not (current_token.text == "--" or current_token.text == "++")
and self._last_last_text != "function"
and current_token.type != TOKEN.WORD
and current_token.type != TOKEN.RESERVED
)
start = start or (
self._flags.mode == MODE.ObjectLiteral
and (
(self._flags.last_token.text == ":" and self._flags.ternary_depth == 0)
or (reserved_array(self._flags.last_token, ["get", "set"]))
)
)
if start:
self.set_mode(MODE.Statement)
self.indent()
self.handle_whitespace_and_comments(current_token, True)
# Issue #276:
# If starting a new statement with [if, for, while, do], push to a new line.
# if (a) if (b) if(c) d(); else e(); else f();
if not self.start_of_object_property():
self.allow_wrap_or_preserved_newline(
current_token,
reserved_array(current_token, ["do", "for", "if", "while"]),
)
return True
else:
return False
def handle_start_expr(self, current_token):
if self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
pass
else:
self.handle_whitespace_and_comments(current_token)
next_mode = MODE.Expression
if current_token.text == "[":
if (
self._flags.last_token.type == TOKEN.WORD
or self._flags.last_token.text == ")"
):
if reserved_array(self._flags.last_token, Tokenizer.line_starters):
self._output.space_before_token = True
self.print_token(current_token)
self.set_mode(next_mode)
self.indent()
if self._options.space_in_paren:
self._output.space_before_token = True
return
next_mode = MODE.ArrayLiteral
if self.is_array(self._flags.mode):
if self._flags.last_token.text == "[" or (
self._flags.last_token.text == ","
and (self._last_last_text == "]" or self._last_last_text == "}")
):
# ], [ goes to a new line
# }, [ goes to a new line
if not self._options.keep_array_indentation:
self.print_newline()
if self._flags.last_token.type not in [
TOKEN.START_EXPR,
TOKEN.END_EXPR,
TOKEN.WORD,
TOKEN.OPERATOR,
TOKEN.DOT,
]:
self._output.space_before_token = True
else:
if self._flags.last_token.type == TOKEN.RESERVED:
if self._flags.last_token.text == "for":
self._output.space_before_token = (
self._options.space_before_conditional
)
next_mode = MODE.ForInitializer
elif self._flags.last_token.text in ["if", "while", "switch"]:
self._output.space_before_token = (
self._options.space_before_conditional
)
next_mode = MODE.Conditional
elif self._flags.last_word in ["await", "async"]:
# Should be a space between await and an IIFE, or async and
# an arrow function
self._output.space_before_token = True
elif (
self._flags.last_token.text == "import"
and current_token.whitespace_before == ""
):
self._output.space_before_token = False
elif (
self._flags.last_token.text in Tokenizer.line_starters
or self._flags.last_token.text == "catch"
):
self._output.space_before_token = True
elif self._flags.last_token.type in [TOKEN.EQUALS, TOKEN.OPERATOR]:
# Support of this kind of newline preservation:
# a = (b &&
# (c || d));
if not self.start_of_object_property():
self.allow_wrap_or_preserved_newline(current_token)
elif self._flags.last_token.type == TOKEN.WORD:
self._output.space_before_token = False
# function name() vs function name ()
# function* name() vs function* name ()
# async name() vs async name ()
# In ES6, you can also define the method properties of an object
# var obj = {a: function() {}}
# It can be abbreviated
# var obj = {a() {}}
# var obj = { a() {}} vs var obj = { a () {}}
# var obj = { * a() {}} vs var obj = { * a () {}}
peek_back_two = self._tokens.peek(-3)
if self._options.space_after_named_function and peek_back_two:
# peek starts at next character so -1 is current token
peek_back_three = self._tokens.peek(-4)
if reserved_array(peek_back_two, ["async", "function"]) or (
peek_back_two.text == "*"
and reserved_array(peek_back_three, ["async", "function"])
):
self._output.space_before_token = True
elif self._flags.mode == MODE.ObjectLiteral:
if (peek_back_two.text == "{" or peek_back_two.text == ",") or (
peek_back_two.text == "*"
and (
peek_back_three.text == "{"
or peek_back_three.text == ","
)
):
self._output.space_before_token = True
elif self._flags.parent and self._flags.parent.class_start_block:
self._output.space_before_token = True
else:
# Support preserving wrapped arrow function expressions
# a.b('c',
# () => d.e
# )
self.allow_wrap_or_preserved_newline(current_token)
# function() vs function (), typeof() vs typeof ()
# function*() vs function* (), yield*() vs yield* ()
if (
self._flags.last_token.type == TOKEN.RESERVED
and (
self._flags.last_word == "function"
or self._flags.last_word == "typeof"
)
) or (
self._flags.last_token.text == "*"
and (
self._last_last_text in ["function", "yield"]
or (
self._flags.mode == MODE.ObjectLiteral
and self._last_last_text in ["{", ","]
)
)
):
self._output.space_before_token = (
self._options.space_after_anon_function
)
if (
self._flags.last_token.text == ";"
or self._flags.last_token.type == TOKEN.START_BLOCK
):
self.print_newline()
elif (
self._flags.last_token.type
in [TOKEN.END_EXPR, TOKEN.START_EXPR, TOKEN.END_BLOCK, TOKEN.COMMA]
or self._flags.last_token.text == "."
):
# do nothing on (( and )( and ][ and ]( and .(
# TODO: Consider whether forcing this is required. Review failing
# tests when removed.
self.allow_wrap_or_preserved_newline(current_token, current_token.newlines)
self.print_token(current_token)
self.set_mode(next_mode)
if self._options.space_in_paren:
self._output.space_before_token = True
# In all cases, if we newline while inside an expression it should be
# indented.
self.indent()
def handle_end_expr(self, current_token):
# statements inside expressions are not valid syntax, but...
# statements must all be closed when their container closes
while self._flags.mode == MODE.Statement:
self.restore_mode()
self.handle_whitespace_and_comments(current_token)
if self._flags.multiline_frame:
self.allow_wrap_or_preserved_newline(
current_token,
current_token.text == "]"
and self.is_array(self._flags.mode)
and not self._options.keep_array_indentation,
)
if self._options.space_in_paren:
if (
self._flags.last_token.type == TOKEN.START_EXPR
and not self._options.space_in_empty_paren
):
# empty parens are always "()" and "[]", not "( )" or "[ ]"
self._output.space_before_token = False
self._output.trim()
else:
self._output.space_before_token = True
self.deindent()
self.print_token(current_token)
self.restore_mode()
remove_redundant_indentation(self._output, self._previous_flags)
# do {} while () // no statement required after
if self._flags.do_while and self._previous_flags.mode == MODE.Conditional:
self._previous_flags.mode = MODE.Expression
self._flags.do_block = False
self._flags.do_while = False
def handle_start_block(self, current_token):
self.handle_whitespace_and_comments(current_token)
# Check if this is a BlockStatement that should be treated as a
# ObjectLiteral
next_token = self._tokens.peek()
second_token = self._tokens.peek(1)
if (
self._flags.last_word == "switch"
and self._flags.last_token.type == TOKEN.END_EXPR
):
self.set_mode(MODE.BlockStatement)
self._flags.in_case_statement = True
elif self._flags.case_body:
self.set_mode(MODE.BlockStatement)
elif second_token is not None and (
(
second_token.text in [":", ","]
and next_token.type in [TOKEN.STRING, TOKEN.WORD, TOKEN.RESERVED]
)
or (
next_token.text in ["get", "set", "..."]
and second_token.type in [TOKEN.WORD, TOKEN.RESERVED]
)
):
# We don't support TypeScript,but we didn't break it for a very long time.
# We'll try to keep not breaking it.
if self._last_last_text in [
"class",
"interface",
] and second_token.text not in [":", ","]:
self.set_mode(MODE.BlockStatement)
else:
self.set_mode(MODE.ObjectLiteral)
elif (
self._flags.last_token.type == TOKEN.OPERATOR
and self._flags.last_token.text == "=>"
):
# arrow function: (param1, paramN) => { statements }
self.set_mode(MODE.BlockStatement)
elif self._flags.last_token.type in [
TOKEN.EQUALS,
TOKEN.START_EXPR,
TOKEN.COMMA,
TOKEN.OPERATOR,
] or reserved_array(
self._flags.last_token, ["return", "throw", "import", "default"]
):
# Detecting shorthand function syntax is difficult by scanning forward,
# so check the surrounding context.
# If the block is being returned, imported, export default, passed as arg,
# assigned with = or assigned in a nested object, treat as an
# ObjectLiteral.
self.set_mode(MODE.ObjectLiteral)
else:
self.set_mode(MODE.BlockStatement)
if self._flags.last_token:
if reserved_array(self._flags.last_token.previous, ["class", "extends"]):
self._flags.class_start_block = True
empty_braces = (
(next_token is not None)
and next_token.comments_before is None
and next_token.text == "}"
)
empty_anonymous_function = (
empty_braces
and self._flags.last_word == "function"
and self._flags.last_token.type == TOKEN.END_EXPR
)
if (
self._options.brace_preserve_inline
): # check for inline, set inline_frame if so
# search forward for newline wanted inside this block
index = 0
check_token = None
self._flags.inline_frame = True
do_loop = True
while do_loop:
index += 1
check_token = self._tokens.peek(index - 1)
if check_token.newlines:
self._flags.inline_frame = False
do_loop = check_token.type != TOKEN.EOF and not (
check_token.type == TOKEN.END_BLOCK
and check_token.opened == current_token
)
if (
self._options.brace_style == "expand"
or (self._options.brace_style == "none" and current_token.newlines)
) and not self._flags.inline_frame:
if self._flags.last_token.type != TOKEN.OPERATOR and (
empty_anonymous_function
or self._flags.last_token.type == TOKEN.EQUALS
or (
reserved_array(self._flags.last_token, _special_word_set)
and self._flags.last_token.text != "else"
)
):
self._output.space_before_token = True
else:
self.print_newline(preserve_statement_flags=True)
else: # collapse || inline_frame
if self.is_array(self._previous_flags.mode) and (
self._flags.last_token.type == TOKEN.START_EXPR
or self._flags.last_token.type == TOKEN.COMMA
):
# if we're preserving inline,
# allow newline between comma and next brace.
if self._flags.inline_frame:
self.allow_wrap_or_preserved_newline(current_token)
self._flags.inline_frame = True
self._previous_flags.multiline_frame = (
self._previous_flags.multiline_frame
or self._flags.multiline_frame
)
self._flags.multiline_frame = False
elif self._flags.last_token.type == TOKEN.COMMA:
self._output.space_before_token = True
elif self._flags.last_token.type not in [TOKEN.OPERATOR, TOKEN.START_EXPR]:
if (
self._flags.last_token.type in [TOKEN.START_BLOCK, TOKEN.SEMICOLON]
and not self._flags.inline_frame
):
self.print_newline()
else:
self._output.space_before_token = True
self.print_token(current_token)
self.indent()
# Except for specific cases, open braces are followed by a new line.
if not empty_braces and not (
self._options.brace_preserve_inline and self._flags.inline_frame
):
self.print_newline()
def handle_end_block(self, current_token):
# statements must all be closed when their container closes
self.handle_whitespace_and_comments(current_token)
while self._flags.mode == MODE.Statement:
self.restore_mode()
empty_braces = self._flags.last_token.type == TOKEN.START_BLOCK
# try inline_frame (only set if opt.braces-preserve-inline) first
if self._flags.inline_frame and not empty_braces:
self._output.space_before_token = True
elif self._options.brace_style == "expand":
if not empty_braces:
self.print_newline()
else:
# skip {}
if not empty_braces:
if (
self.is_array(self._flags.mode)
and self._options.keep_array_indentation
):
self._options.keep_array_indentation = False
self.print_newline()
self._options.keep_array_indentation = True
else:
self.print_newline()
self.restore_mode()
self.print_token(current_token)
def handle_word(self, current_token):
if current_token.type == TOKEN.RESERVED:
if (
current_token.text in ["set", "get"]
and self._flags.mode != MODE.ObjectLiteral
):
current_token.type = TOKEN.WORD
elif current_token.text == "import" and self._tokens.peek().text in [
"(",
".",
]:
current_token.type = TOKEN.WORD
elif current_token.text in ["as", "from"] and not self._flags.import_block:
current_token.type = TOKEN.WORD
elif self._flags.mode == MODE.ObjectLiteral:
next_token = self._tokens.peek()
if next_token.text == ":":
current_token.type = TOKEN.WORD
if self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
if (
reserved_array(self._flags.last_token, ["var", "let", "const"])
and current_token.type == TOKEN.WORD
):
self._flags.declaration_statement = True
elif (
current_token.newlines
and not self.is_expression(self._flags.mode)
and (
self._flags.last_token.type != TOKEN.OPERATOR
or (
self._flags.last_token.text == "--"
or self._flags.last_token.text == "++"
)
)
and self._flags.last_token.type != TOKEN.EQUALS
and (
self._options.preserve_newlines
or not reserved_array(
self._flags.last_token, ["var", "let", "const", "set", "get"]
)
)
):
self.handle_whitespace_and_comments(current_token)
self.print_newline()
else:
self.handle_whitespace_and_comments(current_token)
if self._flags.do_block and not self._flags.do_while:
if reserved_word(current_token, "while"):
# do {} ## while ()
self._output.space_before_token = True
self.print_token(current_token)
self._output.space_before_token = True
self._flags.do_while = True
return
else:
# do {} should always have while as the next word.
# if we don't see the expected while, recover
self.print_newline()
self._flags.do_block = False
# if may be followed by else, or not
# Bare/inline ifs are tricky
# Need to unwind the modes correctly: if (a) if (b) c(); else d(); else
# e();
if self._flags.if_block:
if (not self._flags.else_block) and reserved_word(current_token, "else"):
self._flags.else_block = True
else:
while self._flags.mode == MODE.Statement:
self.restore_mode()
self._flags.if_block = False
if self._flags.in_case_statement and reserved_array(
current_token, ["case", "default"]
):
self.print_newline()
if (not self._flags.case_block) and (
self._flags.case_body or self._options.jslint_happy
):
self.deindent()
self._flags.case_body = False
self.print_token(current_token)
self._flags.in_case = True
return
if self._flags.last_token.type in [
TOKEN.COMMA,
TOKEN.START_EXPR,
TOKEN.EQUALS,
TOKEN.OPERATOR,
]:
if not self.start_of_object_property() and not (
# start of object property is different for numeric values with +/- prefix operators
self._flags.last_token.text in ["+", "-"]
and self._last_last_text == ":"
and self._flags.parent.mode == MODE.ObjectLiteral
):
self.allow_wrap_or_preserved_newline(current_token)
if reserved_word(current_token, "function"):
if self._flags.last_token.text in ["}", ";"] or (
self._output.just_added_newline()
and not (
self._flags.last_token.text in ["(", "[", "{", ":", "=", ","]
or self._flags.last_token.type == TOKEN.OPERATOR
)
):
# make sure there is a nice clean space of at least one blank line
# before a new function definition, except in arrays
if (
not self._output.just_added_blankline()
and current_token.comments_before is None
):
self.print_newline()
self.print_newline(True)
if (
self._flags.last_token.type == TOKEN.RESERVED
or self._flags.last_token.type == TOKEN.WORD
):
if reserved_array(
self._flags.last_token, ["get", "set", "new", "export"]
) or reserved_array(
self._flags.last_token, self._newline_restricted_tokens
):
self._output.space_before_token = True
elif (
reserved_word(self._flags.last_token, "default")
and self._last_last_text == "export"
):
self._output.space_before_token = True
elif self._flags.last_token.text == "declare":
# accomodates Typescript declare function formatting
self._output.space_before_token = True
else:
self.print_newline()
elif (
self._flags.last_token.type == TOKEN.OPERATOR
or self._flags.last_token.text == "="
):
# foo = function
self._output.space_before_token = True
elif not self._flags.multiline_frame and (
self.is_expression(self._flags.mode) or self.is_array(self._flags.mode)
):
# (function
pass
else:
self.print_newline()
self.print_token(current_token)
self._flags.last_word = current_token.text
return
prefix = "NONE"
if self._flags.last_token.type == TOKEN.END_BLOCK:
if self._previous_flags.inline_frame:
prefix = "SPACE"
elif not reserved_array(
current_token, ["else", "catch", "finally", "from"]
):
prefix = "NEWLINE"
else:
if self._options.brace_style in ["expand", "end-expand"] or (
self._options.brace_style == "none" and current_token.newlines
):
prefix = "NEWLINE"
else:
prefix = "SPACE"
self._output.space_before_token = True
elif (
self._flags.last_token.type == TOKEN.SEMICOLON
and self._flags.mode == MODE.BlockStatement
):
# TODO: Should this be for STATEMENT as well?
prefix = "NEWLINE"
elif self._flags.last_token.type == TOKEN.SEMICOLON and self.is_expression(
self._flags.mode
):
prefix = "SPACE"
elif self._flags.last_token.type == TOKEN.STRING:
prefix = "NEWLINE"
elif (
self._flags.last_token.type == TOKEN.RESERVED
or self._flags.last_token.type == TOKEN.WORD
or (
self._flags.last_token.text == "*"
and (
self._last_last_text in ["function", "yield"]
or (
self._flags.mode == MODE.ObjectLiteral
and self._last_last_text in ["{", ","]
)
)
)
):
prefix = "SPACE"
elif self._flags.last_token.type == TOKEN.START_BLOCK:
if self._flags.inline_frame:
prefix = "SPACE"
else:
prefix = "NEWLINE"
elif self._flags.last_token.type == TOKEN.END_EXPR:
self._output.space_before_token = True
prefix = "NEWLINE"
if (
reserved_array(current_token, Tokenizer.line_starters)
and self._flags.last_token.text != ")"
):
if (
self._flags.inline_frame
or self._flags.last_token.text == "else "
or self._flags.last_token.text == "export"
):
prefix = "SPACE"
else:
prefix = "NEWLINE"
if reserved_array(current_token, ["else", "catch", "finally"]):
if (
(
not (
self._flags.last_token.type == TOKEN.END_BLOCK
and self._previous_flags.mode == MODE.BlockStatement
)
)
or self._options.brace_style == "expand"
or self._options.brace_style == "end-expand"
or (self._options.brace_style == "none" and current_token.newlines)
) and not self._flags.inline_frame:
self.print_newline()
else:
self._output.trim(True)
# If we trimmed and there's something other than a close block before us
# put a newline back in. Handles '} // comment' scenario.
if self._output.current_line.last() != "}":
self.print_newline()
self._output.space_before_token = True
elif prefix == "NEWLINE":
if reserved_array(self._flags.last_token, _special_word_set):
# no newline between return nnn
self._output.space_before_token = True
elif self._flags.last_token.text == "declare" and reserved_array(
current_token, ["var", "let", "const"]
):
# accomodates Typescript declare formatting
self._output.space_before_token = True
elif self._flags.last_token.type != TOKEN.END_EXPR:
if (
self._flags.last_token.type != TOKEN.START_EXPR
or not (reserved_array(current_token, ["var", "let", "const"]))
) and self._flags.last_token.text != ":":
# no need to force newline on VAR -
# for (var x = 0...
if (
reserved_word(current_token, "if")
and self._flags.last_token.text == "else"
):
self._output.space_before_token = True
else:
self.print_newline()
elif (
reserved_array(current_token, Tokenizer.line_starters)
and self._flags.last_token.text != ")"
):
self.print_newline()
elif (
self._flags.multiline_frame
and self.is_array(self._flags.mode)
and self._flags.last_token.text == ","
and self._last_last_text == "}"
):
self.print_newline() # }, in lists get a newline
elif prefix == "SPACE":
self._output.space_before_token = True
if current_token.previous and (
current_token.previous.type == TOKEN.WORD
or current_token.previous.type == TOKEN.RESERVED
):
self._output.space_before_token = True
self.print_token(current_token)
self._flags.last_word = current_token.text
if current_token.type == TOKEN.RESERVED:
if current_token.text == "do":
self._flags.do_block = True
elif current_token.text == "if":
self._flags.if_block = True
elif current_token.text == "import":
self._flags.import_block = True
elif current_token.text == "from" and self._flags.import_block:
self._flags.import_block = False
def handle_semicolon(self, current_token):
if self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
# Semicolon can be the start (and end) of a statement
self._output.space_before_token = False
else:
self.handle_whitespace_and_comments(current_token)
next_token = self._tokens.peek()
while (
self._flags.mode == MODE.Statement
and not (self._flags.if_block and reserved_word(next_token, "else"))
and not self._flags.do_block
):
self.restore_mode()
if self._flags.import_block:
self._flags.import_block = False
self.print_token(current_token)
def handle_string(self, current_token):
if (
current_token.text[0] == "`"
and current_token.newlines == 0
and current_token.whitespace_before == ""
and (
self._flags.last_token.type == TOKEN.WORD
or current_token.previous.text == ")"
)
):
# This conditional checks backtick strings and makes no changes
pass
elif self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
# One difference - strings want at least a space before
self._output.space_before_token = True
else:
self.handle_whitespace_and_comments(current_token)
if (
self._flags.last_token.type in [TOKEN.RESERVED, TOKEN.WORD]
or self._flags.inline_frame
):
self._output.space_before_token = True
elif self._flags.last_token.type in [
TOKEN.COMMA,
TOKEN.START_EXPR,
TOKEN.EQUALS,
TOKEN.OPERATOR,
]:
if not self.start_of_object_property():
self.allow_wrap_or_preserved_newline(current_token)
elif (
current_token.text[0] == "`"
and self._flags.last_token.type == TOKEN.END_EXPR
and current_token.previous.text in ["]", ")"]
and current_token.newlines == 0
):
self._output.space_before_token = True
else:
self.print_newline()
self.print_token(current_token)
def handle_equals(self, current_token):
if self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
pass
else:
self.handle_whitespace_and_comments(current_token)
if self._flags.declaration_statement:
# just got an '=' in a var-line, different line breaking rules will
# apply
self._flags.declaration_assignment = True
self._output.space_before_token = True
self.print_token(current_token)
self._output.space_before_token = True
def handle_comma(self, current_token):
self.handle_whitespace_and_comments(current_token, True)
self.print_token(current_token)
self._output.space_before_token = True
if self._flags.declaration_statement:
if self.is_expression(self._flags.parent.mode):
# do not break on comma, for ( var a = 1, b = 2
self._flags.declaration_assignment = False
if self._flags.declaration_assignment:
self._flags.declaration_assignment = False
self.print_newline(preserve_statement_flags=True)
elif self._options.comma_first:
# for comma-first, we want to allow a newline before the comma
# to turn into a newline after the comma, which we will fixup
# later
self.allow_wrap_or_preserved_newline(current_token)
elif self._flags.mode == MODE.ObjectLiteral or (
self._flags.mode == MODE.Statement
and self._flags.parent.mode == MODE.ObjectLiteral
):
if self._flags.mode == MODE.Statement:
self.restore_mode()
if not self._flags.inline_frame:
self.print_newline()
elif self._options.comma_first:
# EXPR or DO_BLOCK
# for comma-first, we want to allow a newline before the comma
# to turn into a newline after the comma, which we will fixup later
self.allow_wrap_or_preserved_newline(current_token)
def handle_operator(self, current_token):
isGeneratorAsterisk = current_token.text == "*" and (
reserved_array(self._flags.last_token, ["function", "yield"])
or (
self._flags.last_token.type
in [TOKEN.START_BLOCK, TOKEN.COMMA, TOKEN.END_BLOCK, TOKEN.SEMICOLON]
)
)
isUnary = current_token.text in ["+", "-"] and (
self._flags.last_token.type
in [TOKEN.START_BLOCK, TOKEN.START_EXPR, TOKEN.EQUALS, TOKEN.OPERATOR]
or self._flags.last_token.text in Tokenizer.line_starters
or self._flags.last_token.text == ","
)
if self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
pass
else:
preserve_statement_flags = not isGeneratorAsterisk
self.handle_whitespace_and_comments(current_token, preserve_statement_flags)
# hack for actionscript's import .*;
if current_token.text == "*" and self._flags.last_token.type == TOKEN.DOT:
self.print_token(current_token)
return
if current_token.text == "::":
# no spaces around the exotic namespacing syntax operator
self.print_token(current_token)
return
if current_token.text in ["-", "+"] and self.start_of_object_property():
# numeric value with +/- symbol in front as a property
self.print_token(current_token)
return
# Allow line wrapping between operators when operator_position is
# set to before or preserve
if (
self._flags.last_token.type == TOKEN.OPERATOR
and self._options.operator_position in OPERATOR_POSITION_BEFORE_OR_PRESERVE
):
self.allow_wrap_or_preserved_newline(current_token)
if current_token.text == ":" and self._flags.in_case:
self.print_token(current_token)
self._flags.in_case = False
self._flags.case_body = True
if self._tokens.peek().type != TOKEN.START_BLOCK:
self.indent()
self.print_newline()
self._flags.case_block = False
else:
self._output.space_before_token = True
self._flags.case_block = True
return
space_before = True
space_after = True
in_ternary = False
if current_token.text == ":":
if self._flags.ternary_depth == 0:
# Colon is invalid javascript outside of ternary and object,
# but do our best to guess what was meant.
space_before = False
else:
self._flags.ternary_depth -= 1
in_ternary = True
elif current_token.text == "?":
self._flags.ternary_depth += 1
# let's handle the operator_position option prior to any conflicting
# logic
if (
(not isUnary)
and (not isGeneratorAsterisk)
and self._options.preserve_newlines
and current_token.text in Tokenizer.positionable_operators
):
isColon = current_token.text == ":"
isTernaryColon = isColon and in_ternary
isOtherColon = isColon and not in_ternary
if self._options.operator_position == OPERATOR_POSITION["before_newline"]:
# if the current token is : and it's not a ternary statement
# then we set space_before to false
self._output.space_before_token = not isOtherColon
self.print_token(current_token)
if (not isColon) or isTernaryColon:
self.allow_wrap_or_preserved_newline(current_token)
self._output.space_before_token = True
return
elif self._options.operator_position == OPERATOR_POSITION["after_newline"]:
# if the current token is anything but colon, or (via deduction) it's a colon and in a ternary statement,
# then print a newline.
self._output.space_before_token = True
if (not isColon) or isTernaryColon:
if self._tokens.peek().newlines:
self.print_newline(preserve_statement_flags=True)
else:
self.allow_wrap_or_preserved_newline(current_token)
else:
self._output.space_before_token = False
self.print_token(current_token)
self._output.space_before_token = True
return
elif (
self._options.operator_position == OPERATOR_POSITION["preserve_newline"]
):
if not isOtherColon:
self.allow_wrap_or_preserved_newline(current_token)
# if we just added a newline, or the current token is : and it's not a ternary statement,
# then we set space_before to false
self._output.space_before_token = not (
self._output.just_added_newline() or isOtherColon
)
self.print_token(current_token)
self._output.space_before_token = True
return
if isGeneratorAsterisk:
self.allow_wrap_or_preserved_newline(current_token)
space_before = False
next_token = self._tokens.peek()
space_after = next_token and next_token.type in [TOKEN.WORD, TOKEN.RESERVED]
elif current_token.text == "...":
self.allow_wrap_or_preserved_newline(current_token)
space_before = self._flags.last_token.type == TOKEN.START_BLOCK
space_after = False
elif current_token.text in ["--", "++", "!", "~"] or isUnary:
if (
self._flags.last_token.type == TOKEN.COMMA
or self._flags.last_token.type == TOKEN.START_EXPR
):
self.allow_wrap_or_preserved_newline(current_token)
space_before = False
space_after = False
# http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1
# if there is a newline between -- or ++ and anything else we
# should preserve it.
if current_token.newlines and (
current_token.text == "--"
or current_token.text == "++"
or current_token.text == "~"
):
new_line_needed = (
reserved_array(self._flags.last_token, _special_word_set)
and current_token.newlines
)
if new_line_needed and (
self._previous_flags.if_block or self._previous_flags.else_block
):
self.restore_mode()
self.print_newline(new_line_needed, True)
if self._flags.last_token.text == ";" and self.is_expression(
self._flags.mode
):
# for (;; ++i)
# ^^
space_before = True
if self._flags.last_token.type == TOKEN.RESERVED:
space_before = True
elif self._flags.last_token.type == TOKEN.END_EXPR:
space_before = not (
self._flags.last_token.text == "]"
and current_token.text in ["--", "++"]
)
elif self._flags.last_token.type == TOKEN.OPERATOR:
# a++ + ++b
# a - -b
space_before = current_token.text in [
"--",
"-",
"++",
"+",
] and self._flags.last_token.text in ["--", "-", "++", "+"]
# + and - are not unary when preceeded by -- or ++ operator
# a-- + b
# a * +b
# a - -b
if current_token.text in ["-", "+"] and self._flags.last_token.text in [
"--",
"++",
]:
space_after = True
if (
(
self._flags.mode == MODE.BlockStatement
and not self._flags.inline_frame
)
or self._flags.mode == MODE.Statement
) and self._flags.last_token.text in ["{", ";"]:
# { foo: --i }
# foo(): --bar
self.print_newline()
if space_before:
self._output.space_before_token = True
self.print_token(current_token)
if space_after:
self._output.space_before_token = True
def handle_block_comment(self, current_token, preserve_statement_flags):
if self._output.raw:
self._output.add_raw_token(current_token)
if (
current_token.directives
and current_token.directives.get("preserve") == "end"
):
# If we're testing the raw output behavior, do not allow a
# directive to turn it off.
self._output.raw = self._options.test_output_raw
return
if current_token.directives:
self.print_newline(preserve_statement_flags=preserve_statement_flags)
self.print_token(current_token)
if current_token.directives.get("preserve") == "start":
self._output.raw = True
self.print_newline(preserve_statement_flags=True)
return
# inline block
if (
not self.acorn.newline.search(current_token.text)
and not current_token.newlines
):
self._output.space_before_token = True
self.print_token(current_token)
self._output.space_before_token = True
return
lines = self.acorn.allLineBreaks.split(current_token.text)
javadoc = False
starless = False
last_indent = current_token.whitespace_before
last_indent_length = len(last_indent)
# block comment starts with a new line
self.print_newline(preserve_statement_flags=preserve_statement_flags)
# first line always indented
self.print_token(current_token, lines[0])
self.print_newline(preserve_statement_flags=preserve_statement_flags)
if len(lines) > 1:
lines = lines[1:]
javadoc = not any(
l for l in lines if (l.strip() == "" or (l.lstrip())[0] != "*")
)
starless = all(l.startswith(last_indent) or l.strip() == "" for l in lines)
if javadoc:
self._flags.alignment = 1
for line in lines:
if javadoc:
# javadoc: reformat and re-indent
self.print_token(current_token, line.lstrip())
elif starless and len(line) > last_indent_length:
# starless: re-indent non-empty content, avoiding trim
self.print_token(current_token, line[last_indent_length:])
else:
# normal comments output raw
self._output.current_line.set_indent(-1)
self._output.add_token(line)
# for comments on their own line or more than one line,
# make sure there's a new line after
self.print_newline(preserve_statement_flags=preserve_statement_flags)
self._flags.alignment = 0
def handle_comment(self, current_token, preserve_statement_flags):
if current_token.newlines:
self.print_newline(preserve_statement_flags=preserve_statement_flags)
if not current_token.newlines:
self._output.trim(True)
self._output.space_before_token = True
self.print_token(current_token)
self.print_newline(preserve_statement_flags=preserve_statement_flags)
def handle_dot(self, current_token):
if self.start_of_statement(current_token):
# The conditional starts the statement if appropriate.
pass
else:
self.handle_whitespace_and_comments(current_token, True)
if re.search("^([0-9])+$", self._flags.last_token.text):
self._output.space_before_token = True
if reserved_array(self._flags.last_token, _special_word_set):
self._output.space_before_token = False
else:
# allow preserved newlines before dots in general
# force newlines on dots after close paren when break_chained - for
# bar().baz()
self.allow_wrap_or_preserved_newline(
current_token,
self._flags.last_token.text == ")"
and self._options.break_chained_methods,
)
# Only unindent chained method dot if this dot starts a new line.
# Otherwise the automatic extra indentation removal
# will handle any over indent
if self._options.unindent_chained_methods and self._output.just_added_newline():
self.deindent()
self.print_token(current_token)
def handle_unknown(self, current_token, preserve_statement_flags):
self.print_token(current_token)
if current_token.text[-1] == "\n":
self.print_newline(preserve_statement_flags=preserve_statement_flags)
def handle_eof(self, current_token):
# Unwind any open statements
while self._flags.mode == MODE.Statement:
self.restore_mode()
self.handle_whitespace_and_comments(current_token)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/javascript/options.py 0000644 0001751 0000177 00000010606 14522301436 022632 0 ustar 00runner docker # 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.
from ..core.options import Options as BaseOptions
OPERATOR_POSITION = ["before-newline", "after-newline", "preserve-newline"]
class BeautifierOptions(BaseOptions):
def __init__(self, options=None):
BaseOptions.__init__(self, options, "js")
self.css = None
self.js = None
self.html = None
# compatibility, re
raw_brace_style = getattr(self.raw_options, "brace_style", None)
if raw_brace_style == "expand-strict": # graceful handling of deprecated option
setattr(self.raw_options, "brace_style", "expand")
elif (
raw_brace_style == "collapse-preserve-inline"
): # graceful handling of deprecated option
setattr(self.raw_options, "brace_style", "collapse,preserve-inline")
# elif bool(self.raw_options.braces_on_own_line): # graceful handling of deprecated option
# raw_brace_style = "expand": "collapse"
# elif raw_brace_style is None: # Nothing exists to set it
# setattr(self.raw_options, 'brace_style', "collapse")
# preserve-inline in delimited string will trigger brace_preserve_inline, everything
# else is considered a brace_style and the last one only will have an effect
brace_style_split = self._get_selection_list(
"brace_style",
["collapse", "expand", "end-expand", "none", "preserve-inline"],
)
# preserve-inline in delimited string will trigger brace_preserve_inline
# Everything else is considered a brace_style and the last one only will
# have an effect
# specify defaults in case one half of meta-option is missing
self.brace_preserve_inline = False
self.brace_style = "collapse"
for bs in brace_style_split:
if bs == "preserve-inline":
self.brace_preserve_inline = True
else:
self.brace_style = bs
self.unindent_chained_methods = self._get_boolean("unindent_chained_methods")
self.break_chained_methods = self._get_boolean("break_chained_methods")
self.space_in_paren = self._get_boolean("space_in_paren")
self.space_in_empty_paren = self._get_boolean("space_in_empty_paren")
self.jslint_happy = self._get_boolean("jslint_happy")
self.space_after_anon_function = self._get_boolean("space_after_anon_function")
self.space_after_named_function = self._get_boolean(
"space_after_named_function"
)
self.keep_array_indentation = self._get_boolean("keep_array_indentation")
self.space_before_conditional = self._get_boolean(
"space_before_conditional", True
)
self.unescape_strings = self._get_boolean("unescape_strings")
self.e4x = self._get_boolean("e4x")
self.comma_first = self._get_boolean("comma_first")
self.operator_position = self._get_selection(
"operator_position", OPERATOR_POSITION
)
# For testing of beautify preserve:start directive
self.test_output_raw = False
# force opts.space_after_anon_function to true if opts.jslint_happy
if self.jslint_happy:
self.space_after_anon_function = True
self.keep_quiet = False
self.eval_code = False
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/javascript/tokenizer.py 0000644 0001751 0000177 00000054510 14522301436 023153 0 ustar 00runner docker # 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.
import re
from ..core.inputscanner import InputScanner
from ..core.tokenizer import TokenTypes as BaseTokenTypes
from ..core.tokenizer import Tokenizer as BaseTokenizer
from ..core.tokenizer import TokenizerPatterns as BaseTokenizerPatterns
from ..core.directives import Directives
from ..core.pattern import Pattern
from ..core.templatablepattern import TemplatablePattern
__all__ = ["TOKEN", "Tokenizer", "TokenTypes"]
class TokenTypes(BaseTokenTypes):
START_EXPR = "TK_START_EXPR"
END_EXPR = "TK_END_EXPR"
START_BLOCK = "TK_START_BLOCK"
END_BLOCK = "TK_END_BLOCK"
WORD = "TK_WORD"
RESERVED = "TK_RESERVED"
SEMICOLON = "TK_SEMICOLON"
STRING = "TK_STRING"
EQUALS = "TK_EQUALS"
OPERATOR = "TK_OPERATOR"
COMMA = "TK_COMMA"
BLOCK_COMMENT = "TK_BLOCK_COMMENT"
COMMENT = "TK_COMMENT"
DOT = "TK_DOT"
UNKNOWN = "TK_UNKNOWN"
def __init__(self):
pass
TOKEN = TokenTypes()
dot_pattern = re.compile(r"[^\d\.]")
number_pattern = re.compile(
r"0[xX][0123456789abcdefABCDEF_]*n?|0[oO][01234567_]*n?|0[bB][01_]*n?|\d[\d_]*n|(?:\.\d[\d_]*|\d[\d_]*\.?[\d_]*)(?:[eE][+-]?[\d_]+)?"
)
digit = re.compile(r"[0-9]")
positionable_operators = frozenset(
(
">>> === !== &&= ??= ||= "
+ "<< && >= ** != == <= >> || ?? |> "
+ "< / - + > : & % ? ^ | *"
).split(" ")
)
punct = (
">>>= "
+ "... >>= <<= === >>> !== **= &&= ??= ||= "
+ "=> ^= :: /= << <= == && -= >= >> != -- += ** || ?? ++ %= &= *= |= |> "
+ "= ! ? > < : / ^ - + * & % ~ |"
)
punct = re.compile(r"([-[\]{}()*+?.,\\^$|#])").sub(r"\\\1", punct)
# ?. but not if followed by a number
punct = "\\?\\.(?!\\d) " + punct
punct = punct.replace(" ", "|")
punct_pattern = re.compile(punct)
# Words which always should start on a new line
line_starters = frozenset(
(
"continue,try,throw,return,var,let,const,if,switch,case,default,for,"
+ "while,break,function,import,export"
).split(",")
)
reserved_words = line_starters | frozenset(
[
"do",
"in",
"of",
"else",
"get",
"set",
"new",
"catch",
"finally",
"typeof",
"yield",
"async",
"await",
"from",
"as",
"class",
"extends",
]
)
reserved_word_pattern = re.compile(r"^(?:" + "|".join(reserved_words) + r")$")
directives_core = Directives(r"/\*", r"\*/")
xmlRegExp = re.compile(
r'[\s\S]*?<(\/?)([-a-zA-Z:0-9_.]+|{[^}]+?}|!\[CDATA\[[^\]]*?\]\]|)(\s*{[^}]+?}|\s+[-a-zA-Z:0-9_.]+|\s+[-a-zA-Z:0-9_.]+\s*=\s*(\'[^\']*\'|"[^"]*"|{([^{}]|{[^}]+?})+?}))*\s*(\/?)\s*>'
)
class TokenizerPatterns(BaseTokenizerPatterns):
def __init__(self, input_scanner, acorn, options):
BaseTokenizerPatterns.__init__(self, input_scanner)
# This is not pretty, but given how we did the version import
# it is the only way to do this without having setup.py fail on a missing
# six dependency.
six = __import__("six")
# IMPORTANT: This string must be run through six to handle \u chars
self.whitespace = self.whitespace.matching(
six.u(r"\u00A0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff"),
six.u(r"\u2028\u2029"),
)
pattern = Pattern(input_scanner)
templatable = TemplatablePattern(input_scanner).read_options(options)
self.identifier = templatable.starting_with(acorn.identifier).matching(
acorn.identifierMatch
)
self.number = pattern.matching(number_pattern)
self.punct = pattern.matching(punct_pattern)
self.comment = pattern.starting_with(r"//").until(six.u(r"[\n\r\u2028\u2029]"))
self.block_comment = pattern.starting_with(r"/\*").until_after(r"\*/")
self.html_comment_start = pattern.matching(r"")
self.include = pattern.starting_with(r"#include").until_after(acorn.lineBreak)
self.shebang = pattern.starting_with(r"#!").until_after(acorn.lineBreak)
self.xml = pattern.matching(xmlRegExp)
self.single_quote = templatable.until(six.u(r"['\\\n\r\u2028\u2029]"))
self.double_quote = templatable.until(six.u(r'["\\\n\r\u2028\u2029]'))
self.template_text = templatable.until(r"[`\\$]")
self.template_expression = templatable.until(r"[`}\\]")
class Tokenizer(BaseTokenizer):
positionable_operators = positionable_operators
line_starters = line_starters
def __init__(self, input_string, opts):
BaseTokenizer.__init__(self, input_string, opts)
import jsbeautifier.javascript.acorn as acorn
self.acorn = acorn
self.in_html_comment = False
self.has_char_escapes = False
self._patterns = TokenizerPatterns(self._input, self.acorn, opts)
def _reset(self):
self.in_html_comment = False
def _is_comment(self, current_token):
return (
current_token.type == TOKEN.COMMENT
or current_token.type == TOKEN.BLOCK_COMMENT
or current_token.type == TOKEN.UNKNOWN
)
def _is_opening(self, current_token):
return (
current_token.type == TOKEN.START_BLOCK
or current_token.type == TOKEN.START_EXPR
)
def _is_closing(self, current_token, open_token):
return (
current_token.type == TOKEN.END_BLOCK
or current_token.type == TOKEN.END_EXPR
) and (
open_token is not None
and (
(current_token.text == "]" and open_token.text == "[")
or (current_token.text == ")" and open_token.text == "(")
or (current_token.text == "}" and open_token.text == "{")
)
)
def _get_next_token(self, previous_token, open_token):
token = None
self._readWhitespace()
c = self._input.peek()
if c is None:
token = self._create_token(TOKEN.EOF, "")
token = token or self._read_non_javascript(c)
token = token or self._read_string(c)
token = token or self._read_pair(
c, self._input.peek(1)
) # Issue #2062 hack for record type '#{'
token = token or self._read_word(previous_token)
token = token or self._read_singles(c)
token = token or self._read_comment(c)
token = token or self._read_regexp(c, previous_token)
token = token or self._read_xml(c, previous_token)
token = token or self._read_punctuation()
token = token or self._create_token(TOKEN.UNKNOWN, self._input.next())
return token
def _read_singles(self, c):
token = None
if c == "(" or c == "[":
token = self._create_token(TOKEN.START_EXPR, c)
elif c == ")" or c == "]":
token = self._create_token(TOKEN.END_EXPR, c)
elif c == "{":
token = self._create_token(TOKEN.START_BLOCK, c)
elif c == "}":
token = self._create_token(TOKEN.END_BLOCK, c)
elif c == ";":
token = self._create_token(TOKEN.SEMICOLON, c)
elif (
c == "."
and self._input.peek(1) is not None
and bool(dot_pattern.match(self._input.peek(1)))
):
token = self._create_token(TOKEN.DOT, c)
elif c == ",":
token = self._create_token(TOKEN.COMMA, c)
if token is not None:
self._input.next()
return token
def _read_pair(self, c, d):
token = None
if c == "#" and d == "{":
token = self._create_token(TOKEN.START_BLOCK, c + d)
if token is not None:
self._input.next()
self._input.next()
return token
def _read_word(self, previous_token):
resulting_string = self._patterns.identifier.read()
if bool(resulting_string):
resulting_string = re.sub(self.acorn.allLineBreaks, "\n", resulting_string)
if not (
previous_token.type == TOKEN.DOT
or (
previous_token.type == TOKEN.RESERVED
and (previous_token.text == "set" or previous_token.text == "get")
)
) and reserved_word_pattern.match(resulting_string):
if (resulting_string == "in" or resulting_string == "of") and (
previous_token.type == TOKEN.WORD
or previous_token.type == TOKEN.STRING
):
# in and of are operators, need to hack
return self._create_token(TOKEN.OPERATOR, resulting_string)
return self._create_token(TOKEN.RESERVED, resulting_string)
return self._create_token(TOKEN.WORD, resulting_string)
resulting_string = self._patterns.number.read()
if resulting_string != "":
return self._create_token(TOKEN.WORD, resulting_string)
def _read_comment(self, c):
token = None
if c == "/":
comment = ""
if self._input.peek(1) == "*": # peek /* .. */ comment
comment = self._patterns.block_comment.read()
directives = directives_core.get_directives(comment)
if directives and directives.get("ignore") == "start":
comment += directives_core.readIgnored(self._input)
comment = re.sub(self.acorn.allLineBreaks, "\n", comment)
token = self._create_token(TOKEN.BLOCK_COMMENT, comment)
token.directives = directives
elif self._input.peek(1) == "/": # peek // comment
comment = self._patterns.comment.read()
token = self._create_token(TOKEN.COMMENT, comment)
return token
def _read_string(self, c):
if c == "`" or c == "'" or c == '"':
resulting_string = self._input.next()
self.has_char_escapes = False
if c == "`":
resulting_string += self.parse_string("`", True, "${")
else:
resulting_string += self.parse_string(c)
if self.has_char_escapes and self._options.unescape_strings:
resulting_string = self.unescape_string(resulting_string)
if self._input.peek() == c:
resulting_string += self._input.next()
resulting_string = re.sub(self.acorn.allLineBreaks, "\n", resulting_string)
return self._create_token(TOKEN.STRING, resulting_string)
return None
def _read_regexp(self, c, previous_token):
if c == "/" and self.allowRegExOrXML(previous_token):
# handle regexp
resulting_string = self._input.next()
esc = False
in_char_class = False
while (
self._input.hasNext()
and (esc or in_char_class or self._input.peek() != c)
and not self._input.testChar(self.acorn.newline)
):
resulting_string += self._input.peek()
if not esc:
esc = self._input.peek() == "\\"
if self._input.peek() == "[":
in_char_class = True
elif self._input.peek() == "]":
in_char_class = False
else:
esc = False
self._input.next()
if self._input.peek() == c:
resulting_string += self._input.next()
if c == "/":
# regexps may have modifiers /regexp/MOD, so fetch those too
# Only [gim] are valid, but if the user puts in garbage, do
# what we can to take it.
resulting_string += self._input.read(self.acorn.identifier)
return self._create_token(TOKEN.STRING, resulting_string)
return None
def _read_xml(self, c, previous_token):
if self._options.e4x and c == "<" and self.allowRegExOrXML(previous_token):
# handle e4x xml literals
xmlStr = ""
match = self._patterns.xml.read_match()
if match and not match.group(1):
rootTag = match.group(2)
rootTag = re.sub(r"^{\s+", "{", re.sub(r"\s+}$", "}", rootTag))
isCurlyRoot = rootTag.startswith("{")
depth = 0
while bool(match):
isEndTag = match.group(1)
tagName = match.group(2)
isSingletonTag = (match.groups()[-1] != "") or (
match.group(2)[0:8] == "![CDATA["
)
if not isSingletonTag and (
tagName == rootTag
or (
isCurlyRoot
and re.sub(r"^{\s+", "{", re.sub(r"\s+}$", "}", tagName))
)
):
if isEndTag:
depth -= 1
else:
depth += 1
xmlStr += match.group(0)
if depth <= 0:
break
match = self._patterns.xml.read_match()
# if we didn't close correctly, keep unformatted.
if not match:
xmlStr += self._input.match(re.compile(r"[\s\S]*")).group(0)
xmlStr = re.sub(self.acorn.allLineBreaks, "\n", xmlStr)
return self._create_token(TOKEN.STRING, xmlStr)
return None
def _read_non_javascript(self, c):
resulting_string = ""
if c == "#":
# she-bang
if self._is_first_token():
resulting_string = self._patterns.shebang.read()
if resulting_string:
return self._create_token(
TOKEN.UNKNOWN, resulting_string.strip() + "\n"
)
# handles extendscript #includes
resulting_string = self._patterns.include.read()
if resulting_string:
return self._create_token(
TOKEN.UNKNOWN, resulting_string.strip() + "\n"
)
c = self._input.next()
# Spidermonkey-specific sharp variables for circular references
# https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
# http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp
# around line 1935
sharp = "#"
if self._input.hasNext() and self._input.testChar(digit):
while True:
c = self._input.next()
sharp += c
if (not self._input.hasNext()) or c == "#" or c == "=":
break
if c == "#":
pass
elif self._input.peek() == "[" and self._input.peek(1) == "]":
sharp += "[]"
self._input.next()
self._input.next()
elif self._input.peek() == "{" and self._input.peek(1) == "}":
sharp += "{}"
self._input.next()
self._input.next()
return self._create_token(TOKEN.WORD, sharp)
self._input.back()
elif c == "<" and self._is_first_token():
if self._patterns.html_comment_start.read():
c = "")
return None
def _read_punctuation(self):
token = None
resulting_string = self._patterns.punct.read()
if resulting_string != "":
if resulting_string == "=":
token = self._create_token(TOKEN.EQUALS, resulting_string)
elif resulting_string == "?.":
token = self._create_token(TOKEN.DOT, resulting_string)
else:
token = self._create_token(TOKEN.OPERATOR, resulting_string)
return token
__regexTokens = {
TOKEN.COMMENT,
TOKEN.START_EXPR,
TOKEN.START_BLOCK,
TOKEN.START,
TOKEN.END_BLOCK,
TOKEN.OPERATOR,
TOKEN.EQUALS,
TOKEN.EOF,
TOKEN.SEMICOLON,
TOKEN.COMMA,
}
def allowRegExOrXML(self, previous_token):
return (
(
previous_token.type == TOKEN.RESERVED
and previous_token.text
in {"return", "case", "throw", "else", "do", "typeof", "yield"}
)
or (
previous_token.type == TOKEN.END_EXPR
and previous_token.text == ")"
and previous_token.opened.previous.type == TOKEN.RESERVED
and previous_token.opened.previous.text in {"if", "while", "for"}
)
or (previous_token.type in self.__regexTokens)
)
def parse_string(self, delimiter, allow_unescaped_newlines=False, start_sub=None):
if delimiter == "'":
pattern = self._patterns.single_quote
elif delimiter == '"':
pattern = self._patterns.double_quote
elif delimiter == "`":
pattern = self._patterns.template_text
elif delimiter == "}":
pattern = self._patterns.template_expression
resulting_string = pattern.read()
next = ""
while self._input.hasNext():
next = self._input.next()
if next == delimiter or (
not allow_unescaped_newlines and self.acorn.newline.match(next)
):
self._input.back()
break
elif next == "\\" and self._input.hasNext():
current_char = self._input.peek()
if current_char == "x" or current_char == "u":
self.has_char_escapes = True
elif current_char == "\r" and self._input.peek(1) == "\n":
self._input.next()
next += self._input.next()
elif start_sub is not None:
if start_sub == "${" and next == "$" and self._input.peek() == "{":
next += self._input.next()
if start_sub == next:
if delimiter == "`":
next += self.parse_string("}", allow_unescaped_newlines, "`")
else:
next += self.parse_string("`", allow_unescaped_newlines, "${")
if self._input.hasNext():
next += self._input.next()
next += pattern.read()
resulting_string += next
return resulting_string
def unescape_string(self, s):
# You think that a regex would work for this
# return s.replace(/\\x([0-9a-f]{2})/gi, function(match, val) {
# return String.fromCharCode(parseInt(val, 16));
# })
# However, dealing with '\xff', '\\xff', '\\\xff' makes this more fun.
out = self.acorn.six.u("")
escaped = 0
input_scan = InputScanner(s)
matched = None
while input_scan.hasNext():
# Keep any whitespace, non-slash characters
# also keep slash pairs.
matched = input_scan.match(re.compile(r"([\s]|[^\\]|\\\\)+"))
if matched:
out += matched.group(0)
if input_scan.peek() != "\\":
continue
input_scan.next()
if input_scan.peek() == "x":
matched = input_scan.match(re.compile(r"x([0-9A-Fa-f]{2})"))
elif input_scan.peek() == "u":
matched = input_scan.match(re.compile(r"u([0-9A-Fa-f]{4})"))
if not matched:
matched = input_scan.match(re.compile(r"u\{([0-9A-Fa-f]+)\}"))
else:
out += "\\"
if input_scan.hasNext():
out += input_scan.next()
continue
# If there's some error decoding, return the original string
if not matched:
return s
escaped = int(matched.group(1), 16)
if escaped > 0x7E and escaped <= 0xFF and matched.group(0).startswith("x"):
# we bail out on \x7f..\xff,
# leaving whole string escaped,
# as it's probably completely binary
return s
elif escaped >= 0x00 and escaped < 0x20:
# leave 0x00...0x1f escaped
out += "\\" + matched.group(0)
elif escaped > 0x10FFFF:
# If the escape sequence is out of bounds, keep the original sequence and continue conversion
out += "\\" + matched.group(0)
elif escaped == 0x22 or escaped == 0x27 or escaped == 0x5C:
# single-quote, apostrophe, backslash - escape these
out += "\\" + chr(escaped)
else:
out += self.acorn.six.unichr(escaped)
return out
././@PaxHeader 0000000 0000000 0000000 00000000033 00000000000 010211 x ustar 00 27 mtime=1699316581.318391
jsbeautifier-1.14.11/jsbeautifier/tests/ 0000755 0001751 0000177 00000000000 14522301545 017557 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/tests/__init__.py 0000644 0001751 0000177 00000000020 14522301436 021657 0 ustar 00runner docker # Empty file :)
././@PaxHeader 0000000 0000000 0000000 00000000033 00000000000 010211 x ustar 00 27 mtime=1699316581.318391
jsbeautifier-1.14.11/jsbeautifier/tests/generated/ 0000755 0001751 0000177 00000000000 14522301545 021515 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/tests/generated/__init__.py 0000644 0001751 0000177 00000000020 14522301436 023615 0 ustar 00runner docker # Empty file :)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316562.0
jsbeautifier-1.14.11/jsbeautifier/tests/generated/tests.py 0000644 0001751 0000177 00001215204 14522301522 023231 0 ustar 00runner docker #!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
AUTO-GENERATED. DO NOT MODIFY.
Script: test/generate-tests.js
Template: test/data/javascript/python.mustache
Data: test/data/javascript/tests.js
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.
'''
import re
import unittest
import jsbeautifier
import six
import copy
class TestJSBeautifier(unittest.TestCase):
options = None
@classmethod
def setUpClass(cls):
pass
cls.wrapregex = re.compile('^(.+)$', re.MULTILINE)
def reset_options(self):
true = True
false = False
default_options = jsbeautifier.default_options()
default_options.indent_size = 4
default_options.indent_char = ' '
default_options.preserve_newlines = true
default_options.jslint_happy = false
default_options.indent_level = 0
default_options.break_chained_methods = false
default_options.eol = '\n'
default_options.indent_size = 4
default_options.indent_char = ' '
default_options.preserve_newlines = true
default_options.jslint_happy = false
self.options = copy.copy(default_options)
def test_unescape(self):
# Test cases contributed by
test_fragment = self.decodesto
self.reset_options()
bt = self.bt
def unicode_char(value):
return six.unichr(value)
bt('"\\\\s"') # == "\\s" in the js source
bt("'\\\\s'") # == '\\s' in the js source
bt("'\\\\\\s'") # == '\\\s' in the js source
bt("'\\s'") # == '\s' in the js source
bt('"•"')
bt('"—"')
bt('"\\x41\\x42\\x43\\x01"', '"\\x41\\x42\\x43\\x01"')
bt('"\\u2022"', '"\\u2022"')
bt('"\\u{2022}"', '"\\u{2022}"')
bt('a = /\s+/')
#bt('a = /\\x41/','a = /A/')
bt('"\\u2022";a = /\s+/;"\\x41\\x42\\x43\\x01".match(/\\x41/);','"\\u2022";\na = /\s+/;\n"\\x41\\x42\\x43\\x01".match(/\\x41/);')
test_fragment('"\\x41\\x42\\x01\\x43"')
test_fragment('"\\x41\\x42\\u0001\\x43"')
test_fragment('"\\x41\\x42\\u{0001}\\x43"')
test_fragment('"\\x20\\x40\\x4a"')
test_fragment('"\\xff\\x40\\x4a"')
test_fragment('"\\u0072\\u016B\\u0137\\u012B\\u0074\\u0069\\u0073"')
test_fragment('"\\u{0072}\\u{016B}\\u{110000}\\u{137}\\u012B\\x74\\u{0000069}\\u{073}"')
test_fragment('"Google Chrome est\\u00E1 actualizado."')
test_fragment(
'"\\x22\\x27",\'\\x22\\x27\',"\\x5c",\'\\x5c\',"\\xff and \\xzz","unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"',
'"\\x22\\x27", \'\\x22\\x27\', "\\x5c", \'\\x5c\', "\\xff and \\xzz", "unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"')
self.options.unescape_strings = True
bt('"\\x41\\x42\\x01\\x43"', '"AB\\x01C"')
bt('"\\x41\\x42\\u0001\\x43"', '"AB\\u0001C"')
bt('"\\x41\\x42\\u{0001}\\x43"', '"AB\\u{0001}C"')
test_fragment('"\\x20\\x40\\x4a"', '" @J"')
test_fragment('"\\xff\\x40\\x4a"')
test_fragment('"\\u0072\\u016B\\u0137\\u012B\\u0074\\u0069\\u0073"', six.u('"\u0072\u016B\u0137\u012B\u0074\u0069\u0073"'))
test_fragment('"\\u{0072}\\u{016B}\\u{110000}\\u{137}\\u012B\\x74\\u{0000069}\\u{073}"', six.u('"\u0072\u016B\\u{110000}\u0137\u012B\u0074\u0069\u0073"'))
bt('a = /\s+/')
test_fragment('"\\x22\\x27",\'\\x22\\x27\',"\\x5c",\'\\x5c\',"\\xff","unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff"',
'"\\"\\\'", \'\\"\\\'\', "\\\\", \'\\\\\', "\\xff", "unicode \\u0000 \\" \\\' \\\\ ' + unicode_char(0xffff) + '"')
# For error case, return the string unchanged
test_fragment('"\\x22\\x27",\'\\x22\\x27\',"\\x5c",\'\\x5c\',"\\xff and \\xzz","unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"',
'"\\"\\\'", \'\\"\\\'\', "\\\\", \'\\\\\', "\\xff and \\xzz", "unicode \\u0000 \\u0022 \\u0027 \\u005c \\uffff \\uzzzz"')
self.options.unescape_strings = False
def test_beautifier(self):
test_fragment = self.decodesto
bt = self.bt
true = True
false = False
def unicode_char(value):
return six.unichr(value)
##============================================================
# Line wrap test inputs
#....---------1---------2---------3---------4---------5---------6---------7
#....1234567890123456789012345678901234567890123456789012345678901234567890
wrap_input_1=(
'foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'return between_return_and_expression_should_never_wrap.but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' +
'object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
'}');
#....---------1---------2---------3---------4---------5---------6---------7
#....1234567890123456789012345678901234567890123456789012345678901234567890
wrap_input_2=(
'{\n' +
' foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
' return between_return_and_expression_should_never_wrap.but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' +
' object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
' }' +
'}');
#============================================================
# Unicode Support
self.reset_options()
bt('var ' + unicode_char(3232) + '_' + unicode_char(3232) + ' = "hi";')
bt(
'var ' + unicode_char(228) + 'x = {\n' +
' ' + unicode_char(228) + 'rgerlich: true\n' +
'};')
bt(
'var \\u00E4\\u0ca0\\u0cA0\\u0Ca0 = {\n' +
' \\u0ca0rgerlich: true\n' +
'};')
bt(
'var \\u00E4add\\u0025 = {\n' +
' \\u0044rgerlich\\u0ca0: true\n' +
'};')
bt(
'var' + unicode_char(160) + unicode_char(3232) + '_' + unicode_char(3232) + ' = "hi";',
# -- output --
'var ' + unicode_char(3232) + '_' + unicode_char(3232) + ' = "hi";')
# Issue #2159: Invalid prettification of object with unicode escape character as object key - test scenario: object with unicode as key
bt(
'{\\u{1d4b6}:"ascr"}',
# -- output --
'{\n' +
' \\u{1d4b6}: "ascr"\n' +
'}')
bt(
'var \\u{E4}\\u{ca0}\\u{0cA0}\\u{000000Ca0} = {\n' +
' \\u{ca0}rgerlich: true\n' +
'};')
#============================================================
# Test template and continuation strings
self.reset_options()
bt('`This is a ${template} string.`')
bt(
'`This\n' +
' is\n' +
' a\n' +
' ${template}\n' +
' string.`')
bt(
'a = `This is a continuation\\\n' +
'string.`')
bt(
'a = "This is a continuation\\\n' +
'string."')
bt(
'`SELECT\n' +
' nextval(\'${this.options.schema ? `${this.options.schema}.` : \'\'}"${this.tableName}_${this.autoIncrementField}_seq"\'::regclass\n' +
' ) nextval;`')
# Tests for #1030
bt(
'const composeUrl = (host) => {\n' +
' return `${host `test`}`;\n' +
'};')
bt(
'const composeUrl = (host, api, key, data) => {\n' +
' switch (api) {\n' +
' case "Init":\n' +
' return `${host}/vwapi/Init?VWID=${key}&DATA=${encodeURIComponent(\n' +
' Object.keys(data).map((k) => `${k}=${ data[k]}` ).join(";")\n' +
' )}`;\n' +
' case "Pay":\n' +
' return `${host}/vwapi/Pay?SessionId=${par}`;\n' +
' };\n' +
'};')
#============================================================
# Private Class Fields
self.reset_options()
bt('#foo')
bt(
'class X {\n' +
' #foo = null;\n' +
' get foo() {\n' +
' return this.#foo;\n' +
' }\n' +
'}')
bt(
'class X {#foo=null;}',
# -- output --
'class X {\n' +
' #foo = null;\n' +
'}')
#============================================================
# ES7 Decorators
self.reset_options()
bt('@foo')
bt('@foo(bar)')
bt(
'@foo(function(k, v) {\n' +
' implementation();\n' +
'})')
#============================================================
# ES7 exponential
self.reset_options()
bt('x ** 2')
bt('x ** -2')
#============================================================
# Spread operator
self.reset_options()
self.options.brace_style = "collapse,preserve-inline"
bt('const m = { ...item, c: 3 };')
bt(
'const m = {\n' +
' ...item,\n' +
' c: 3\n' +
'};')
bt('const m = { c: 3, ...item };')
bt('const m = [...item, 3];')
bt('const m = [3, ...item];')
#============================================================
# Object literal shorthand functions
self.reset_options()
bt(
'return {\n' +
' foo() {\n' +
' return 42;\n' +
' }\n' +
'}')
bt(
'var foo = {\n' +
' * bar() {\n' +
' yield 42;\n' +
' }\n' +
'};')
bt(
'var foo = {bar(){return 42;},*barGen(){yield 42;}};',
# -- output --
'var foo = {\n' +
' bar() {\n' +
' return 42;\n' +
' },\n' +
' * barGen() {\n' +
' yield 42;\n' +
' }\n' +
'};')
# also handle generator shorthand in class - #1013
bt(
'class A {\n' +
' fn() {\n' +
' return true;\n' +
' }\n' +
'\n' +
' * gen() {\n' +
' return true;\n' +
' }\n' +
'}')
bt(
'class A {\n' +
' * gen() {\n' +
' return true;\n' +
' }\n' +
'\n' +
' fn() {\n' +
' return true;\n' +
' }\n' +
'}')
#============================================================
# End With Newline - (end_with_newline = "true")
self.reset_options()
self.options.end_with_newline = true
test_fragment('', '\n')
test_fragment(' return .5', ' return .5\n')
test_fragment(
' \n' +
'\n' +
'return .5\n' +
'\n' +
'\n' +
'\n',
# -- output --
' return .5\n')
test_fragment('\n')
# End With Newline - (end_with_newline = "false")
self.reset_options()
self.options.end_with_newline = false
test_fragment('')
test_fragment(' return .5')
test_fragment(
' \n' +
'\n' +
'return .5\n' +
'\n' +
'\n' +
'\n',
# -- output --
' return .5')
test_fragment('\n', '')
#============================================================
# Support Indent Level Options and Base Indent Autodetection - ()
self.reset_options()
test_fragment(' a')
test_fragment(
' function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
test_fragment(
' // This is a random comment\n' +
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' // This is a random comment\n' +
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
# Support Indent Level Options and Base Indent Autodetection - (indent_level = "0")
self.reset_options()
self.options.indent_level = 0
test_fragment(' a')
test_fragment(
' function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
test_fragment(
' // This is a random comment\n' +
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' // This is a random comment\n' +
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
# Support Indent Level Options and Base Indent Autodetection - (indent_level = "1")
self.reset_options()
self.options.indent_level = 1
test_fragment(' a', ' a')
test_fragment(
' function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
test_fragment(
' // This is a random comment\n' +
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' // This is a random comment\n' +
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
# Support Indent Level Options and Base Indent Autodetection - (indent_level = "2")
self.reset_options()
self.options.indent_level = 2
test_fragment('a', ' a')
test_fragment(
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
test_fragment(
'// This is a random comment\n' +
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
' // This is a random comment\n' +
' function test() {\n' +
' console.log("this is a test");\n' +
' }')
# Support Indent Level Options and Base Indent Autodetection - (indent_with_tabs = "true", indent_level = "2")
self.reset_options()
self.options.indent_with_tabs = true
self.options.indent_level = 2
test_fragment('a', '\t\ta')
test_fragment(
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
'\t\tfunction test() {\n' +
'\t\t\tconsole.log("this is a test");\n' +
'\t\t}')
test_fragment(
'// This is a random comment\n' +
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
'\t\t// This is a random comment\n' +
'\t\tfunction test() {\n' +
'\t\t\tconsole.log("this is a test");\n' +
'\t\t}')
# Support Indent Level Options and Base Indent Autodetection - (indent_level = "0")
self.reset_options()
self.options.indent_level = 0
test_fragment('\t a')
test_fragment(
'\t function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
'\t function test() {\n' +
'\t console.log("this is a test");\n' +
'\t }')
test_fragment(
'\t // This is a random comment\n' +
'function test(){\n' +
' console.log("this is a test");\n' +
'}',
# -- output --
'\t // This is a random comment\n' +
'\t function test() {\n' +
'\t console.log("this is a test");\n' +
'\t }')
#============================================================
# Support simple language specific option inheritance/overriding - (js = "{ "indent_size": 3 }", css = "{ "indent_size": 5 }")
self.reset_options()
self.options.js = { 'indent_size': 3 }
self.options.css = { 'indent_size': 5 }
bt(
'if (a == b) {\n' +
' test();\n' +
'}')
# Support simple language specific option inheritance/overriding - (html = "{ "js": { "indent_size": 3 }, "css": { "indent_size": 5 } }")
self.reset_options()
self.options.html = { 'js': { 'indent_size': 3 }, 'css': { 'indent_size': 5 } }
bt(
'if (a == b) {\n' +
' test();\n' +
'}')
# Support simple language specific option inheritance/overriding - (indent_size = "9", html = "{ "js": { "indent_size": 3 }, "css": { "indent_size": 5 }, "indent_size": 2}", js = "{ "indent_size": 4 }", css = "{ "indent_size": 3 }")
self.reset_options()
self.options.indent_size = 9
self.options.html = { 'js': { 'indent_size': 3 }, 'css': { 'indent_size': 5 }, 'indent_size': 2}
self.options.js = { 'indent_size': 4 }
self.options.css = { 'indent_size': 3 }
bt(
'if (a == b) {\n' +
' test();\n' +
'}')
#============================================================
# Brace style permutations - (brace_style = ""collapse,preserve-inline"")
self.reset_options()
self.options.brace_style = 'collapse,preserve-inline'
bt(
'var a ={a: 2};\n' +
'var a ={a: 2};',
# -- output --
'var a = { a: 2 };\n' +
'var a = { a: 2 };')
bt(
'//case 1\n' +
'if (a == 1){}\n' +
'//case 2\n' +
'else if (a == 2){}',
# -- output --
'//case 1\n' +
'if (a == 1) {}\n' +
'//case 2\n' +
'else if (a == 2) {}')
bt('if(1){2}else{3}', 'if (1) { 2 } else { 3 }')
bt('try{a();}catch(b){c();}catch(d){}finally{e();}', 'try { a(); } catch (b) { c(); } catch (d) {} finally { e(); }')
# Brace style permutations - (brace_style = ""collapse,preserve-inline"")
self.reset_options()
self.options.brace_style = 'collapse,preserve-inline'
bt(
'var a =\n' +
'{\n' +
'a: 2\n' +
'}\n' +
';\n' +
'var a =\n' +
'{\n' +
'a: 2\n' +
'}\n' +
';',
# -- output --
'var a = {\n' +
' a: 2\n' +
'};\n' +
'var a = {\n' +
' a: 2\n' +
'};')
bt(
'//case 1\n' +
'if (a == 1)\n' +
'{}\n' +
'//case 2\n' +
'else if (a == 2)\n' +
'{}',
# -- output --
'//case 1\n' +
'if (a == 1) {}\n' +
'//case 2\n' +
'else if (a == 2) {}')
bt(
'if(1)\n' +
'{\n' +
'2\n' +
'}\n' +
'else\n' +
'{\n' +
'3\n' +
'}',
# -- output --
'if (1) {\n' +
' 2\n' +
'} else {\n' +
' 3\n' +
'}')
bt(
'try\n' +
'{\n' +
'a();\n' +
'}\n' +
'catch(b)\n' +
'{\n' +
'c();\n' +
'}\n' +
'catch(d)\n' +
'{}\n' +
'finally\n' +
'{\n' +
'e();\n' +
'}',
# -- output --
'try {\n' +
' a();\n' +
'} catch (b) {\n' +
' c();\n' +
'} catch (d) {} finally {\n' +
' e();\n' +
'}')
# Brace style permutations - ()
self.reset_options()
bt(
'var a ={a: 2};\n' +
'var a ={a: 2};',
# -- output --
'var a = {\n' +
' a: 2\n' +
'};\n' +
'var a = {\n' +
' a: 2\n' +
'};')
bt(
'//case 1\n' +
'if (a == 1){}\n' +
'//case 2\n' +
'else if (a == 2){}',
# -- output --
'//case 1\n' +
'if (a == 1) {}\n' +
'//case 2\n' +
'else if (a == 2) {}')
bt(
'if(1){2}else{3}',
# -- output --
'if (1) {\n' +
' 2\n' +
'} else {\n' +
' 3\n' +
'}')
bt(
'try{a();}catch(b){c();}catch(d){}finally{e();}',
# -- output --
'try {\n' +
' a();\n' +
'} catch (b) {\n' +
' c();\n' +
'} catch (d) {} finally {\n' +
' e();\n' +
'}')
# Brace style permutations - (brace_style = ""collapse"")
self.reset_options()
self.options.brace_style = 'collapse'
bt(
'var a ={a: 2};\n' +
'var a ={a: 2};',
# -- output --
'var a = {\n' +
' a: 2\n' +
'};\n' +
'var a = {\n' +
' a: 2\n' +
'};')
bt(
'//case 1\n' +
'if (a == 1){}\n' +
'//case 2\n' +
'else if (a == 2){}',
# -- output --
'//case 1\n' +
'if (a == 1) {}\n' +
'//case 2\n' +
'else if (a == 2) {}')
bt(
'if(1){2}else{3}',
# -- output --
'if (1) {\n' +
' 2\n' +
'} else {\n' +
' 3\n' +
'}')
bt(
'try{a();}catch(b){c();}catch(d){}finally{e();}',
# -- output --
'try {\n' +
' a();\n' +
'} catch (b) {\n' +
' c();\n' +
'} catch (d) {} finally {\n' +
' e();\n' +
'}')
# Brace style permutations - (brace_style = ""collapse"")
self.reset_options()
self.options.brace_style = 'collapse'
bt(
'var a =\n' +
'{\n' +
'a: 2\n' +
'}\n' +
';\n' +
'var a =\n' +
'{\n' +
'a: 2\n' +
'}\n' +
';',
# -- output --
'var a = {\n' +
' a: 2\n' +
'};\n' +
'var a = {\n' +
' a: 2\n' +
'};')
bt(
'//case 1\n' +
'if (a == 1)\n' +
'{}\n' +
'//case 2\n' +
'else if (a == 2)\n' +
'{}',
# -- output --
'//case 1\n' +
'if (a == 1) {}\n' +
'//case 2\n' +
'else if (a == 2) {}')
bt(
'if(1)\n' +
'{\n' +
'2\n' +
'}\n' +
'else\n' +
'{\n' +
'3\n' +
'}',
# -- output --
'if (1) {\n' +
' 2\n' +
'} else {\n' +
' 3\n' +
'}')
bt(
'try\n' +
'{\n' +
'a();\n' +
'}\n' +
'catch(b)\n' +
'{\n' +
'c();\n' +
'}\n' +
'catch(d)\n' +
'{}\n' +
'finally\n' +
'{\n' +
'e();\n' +
'}',
# -- output --
'try {\n' +
' a();\n' +
'} catch (b) {\n' +
' c();\n' +
'} catch (d) {} finally {\n' +
' e();\n' +
'}')
#============================================================
# Comma-first option - (comma_first = "false")
self.reset_options()
self.options.comma_first = false
bt(
'{a:1, b:2}',
# -- output --
'{\n' +
' a: 1,\n' +
' b: 2\n' +
'}')
bt(
'var a=1, b=c[d], e=6;',
# -- output --
'var a = 1,\n' +
' b = c[d],\n' +
' e = 6;')
bt(
'for(var a=1,b=2,c=3;d<3;d++)\n' +
'e',
# -- output --
'for (var a = 1, b = 2, c = 3; d < 3; d++)\n' +
' e')
bt(
'for(var a=1,b=2,\n' +
'c=3;d<3;d++)\n' +
'e',
# -- output --
'for (var a = 1, b = 2,\n' +
' c = 3; d < 3; d++)\n' +
' e')
bt(
'function foo() {\n' +
' return [\n' +
' "one",\n' +
' "two"\n' +
' ];\n' +
'}')
bt(
'a=[[1,2],[4,5],[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],[7,8],]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' [7, 8],\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' function() {},\n' +
' [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' function() {},\n' +
' function() {},\n' +
' [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' function() {},\n' +
' [7, 8]\n' +
']')
bt('a=[b,c,function(){},function(){},d]', 'a = [b, c, function() {}, function() {}, d]')
bt(
'a=[b,c,\n' +
'function(){},function(){},d]',
# -- output --
'a = [b, c,\n' +
' function() {},\n' +
' function() {},\n' +
' d\n' +
']')
bt('a=[a[1],b[4],c[d[7]]]', 'a = [a[1], b[4], c[d[7]]]')
bt('[1,2,[3,4,[5,6],7],8]', '[1, 2, [3, 4, [5, 6], 7], 8]')
bt(
'[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]',
# -- output --
'[\n' +
' [\n' +
' ["1", "2"],\n' +
' ["3", "4"]\n' +
' ],\n' +
' [\n' +
' ["5", "6", "7"],\n' +
' ["8", "9", "0"]\n' +
' ],\n' +
' [\n' +
' ["1", "2", "3"],\n' +
' ["4", "5", "6", "7"],\n' +
' ["8", "9", "0"]\n' +
' ]\n' +
']')
bt(
'changeCollection.add({\n' +
' name: "Jonathan" // New line inserted after this line on every save\n' +
' , age: 25\n' +
'});',
# -- output --
'changeCollection.add({\n' +
' name: "Jonathan" // New line inserted after this line on every save\n' +
' ,\n' +
' age: 25\n' +
'});')
bt(
'changeCollection.add(\n' +
' function() {\n' +
' return true;\n' +
' },\n' +
' function() {\n' +
' return true;\n' +
' }\n' +
');')
# Comma-first option - (comma_first = "true")
self.reset_options()
self.options.comma_first = true
bt(
'{a:1, b:2}',
# -- output --
'{\n' +
' a: 1\n' +
' , b: 2\n' +
'}')
bt(
'var a=1, b=c[d], e=6;',
# -- output --
'var a = 1\n' +
' , b = c[d]\n' +
' , e = 6;')
bt(
'for(var a=1,b=2,c=3;d<3;d++)\n' +
'e',
# -- output --
'for (var a = 1, b = 2, c = 3; d < 3; d++)\n' +
' e')
bt(
'for(var a=1,b=2,\n' +
'c=3;d<3;d++)\n' +
'e',
# -- output --
'for (var a = 1, b = 2\n' +
' , c = 3; d < 3; d++)\n' +
' e')
bt(
'function foo() {\n' +
' return [\n' +
' "one"\n' +
' , "two"\n' +
' ];\n' +
'}')
bt(
'a=[[1,2],[4,5],[7,8]]',
# -- output --
'a = [\n' +
' [1, 2]\n' +
' , [4, 5]\n' +
' , [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],[7,8],]',
# -- output --
'a = [\n' +
' [1, 2]\n' +
' , [4, 5]\n' +
' , [7, 8]\n' +
', ]')
bt(
'a=[[1,2],[4,5],function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2]\n' +
' , [4, 5]\n' +
' , function() {}\n' +
' , [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2]\n' +
' , [4, 5]\n' +
' , function() {}\n' +
' , function() {}\n' +
' , [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2]\n' +
' , [4, 5]\n' +
' , function() {}\n' +
' , [7, 8]\n' +
']')
bt('a=[b,c,function(){},function(){},d]', 'a = [b, c, function() {}, function() {}, d]')
bt(
'a=[b,c,\n' +
'function(){},function(){},d]',
# -- output --
'a = [b, c\n' +
' , function() {}\n' +
' , function() {}\n' +
' , d\n' +
']')
bt('a=[a[1],b[4],c[d[7]]]', 'a = [a[1], b[4], c[d[7]]]')
bt('[1,2,[3,4,[5,6],7],8]', '[1, 2, [3, 4, [5, 6], 7], 8]')
bt(
'[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]',
# -- output --
'[\n' +
' [\n' +
' ["1", "2"]\n' +
' , ["3", "4"]\n' +
' ]\n' +
' , [\n' +
' ["5", "6", "7"]\n' +
' , ["8", "9", "0"]\n' +
' ]\n' +
' , [\n' +
' ["1", "2", "3"]\n' +
' , ["4", "5", "6", "7"]\n' +
' , ["8", "9", "0"]\n' +
' ]\n' +
']')
bt(
'changeCollection.add({\n' +
' name: "Jonathan" // New line inserted after this line on every save\n' +
' , age: 25\n' +
'});')
bt(
'changeCollection.add(\n' +
' function() {\n' +
' return true;\n' +
' },\n' +
' function() {\n' +
' return true;\n' +
' }\n' +
');',
# -- output --
'changeCollection.add(\n' +
' function() {\n' +
' return true;\n' +
' }\n' +
' , function() {\n' +
' return true;\n' +
' }\n' +
');')
#============================================================
# Unindent chained functions - (unindent_chained_methods = "true")
self.reset_options()
self.options.unindent_chained_methods = true
bt(
'f().f().f()\n' +
' .f().f();',
# -- output --
'f().f().f()\n' +
'.f().f();')
bt(
'f()\n' +
' .f()\n' +
' .f();',
# -- output --
'f()\n' +
'.f()\n' +
'.f();')
bt(
'f(function() {\n' +
' f()\n' +
' .f()\n' +
' .f();\n' +
'});',
# -- output --
'f(function() {\n' +
' f()\n' +
' .f()\n' +
' .f();\n' +
'});')
# regression test for fix #1378
bt(
'f(function() {\n' +
' if(g === 1)\n' +
' g = 0;\n' +
' else\n' +
' g = 1;\n' +
'\n' +
' f()\n' +
' .f()\n' +
' .f();\n' +
'});',
# -- output --
'f(function() {\n' +
' if (g === 1)\n' +
' g = 0;\n' +
' else\n' +
' g = 1;\n' +
'\n' +
' f()\n' +
' .f()\n' +
' .f();\n' +
'});')
# regression test for fix #1533
bt(
'angular.module("test").controller("testCtrl", function($scope) {\n' +
' $scope.tnew;\n' +
' $scope.toggle_tnew = function() {\n' +
' $scope.mode = 0;\n' +
' if (!$scope.tnew) {\n' +
' $scope.tnew = {};\n' +
' } else $scope.tnew = null;\n' +
' }\n' +
' $scope.fn = function() {\n' +
' return null;\n' +
' }\n' +
'});')
#============================================================
# Space in parens tests - (space_in_paren = "false", space_in_empty_paren = "false")
self.reset_options()
self.options.space_in_paren = false
self.options.space_in_empty_paren = false
bt('if(p) foo(a,b);', 'if (p) foo(a, b);')
bt(
'try{while(true){willThrow()}}catch(result)switch(result){case 1:++result }',
# -- output --
'try {\n' +
' while (true) {\n' +
' willThrow()\n' +
' }\n' +
'} catch (result) switch (result) {\n' +
' case 1:\n' +
' ++result\n' +
'}')
bt('((e/((a+(b)*c)-d))^2)*5;', '((e / ((a + (b) * c) - d)) ^ 2) * 5;')
bt(
'function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
# -- output --
'function f(a, b) {\n' +
' if (a) b()\n' +
'}\n' +
'\n' +
'function g(a, b) {\n' +
' if (!a) b()\n' +
'}')
bt('a=[][ ]( );', 'a = [][]();')
bt('a=()( )[ ];', 'a = ()()[];')
bt('a=[b,c,d];', 'a = [b, c, d];')
bt('a= f[b];', 'a = f[b];')
# Issue #1151 - inside class methods
bt(
'export default class Test extends Component {\n' +
' render() {\n' +
' someOther();\n' +
' return null;\n' +
' }\n' +
'}')
bt(
'{\n' +
' files: a[][ {\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b(c)[ "im/design_standards/*.*" ],\n' +
' dest: "www/gui/build"\n' +
' } ]\n' +
'}',
# -- output --
'{\n' +
' files: a[][{\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b(c)["im/design_standards/*.*"],\n' +
' dest: "www/gui/build"\n' +
' }]\n' +
'}')
# Space in parens tests - (space_in_paren = "false", space_in_empty_paren = "true")
self.reset_options()
self.options.space_in_paren = false
self.options.space_in_empty_paren = true
bt('if(p) foo(a,b);', 'if (p) foo(a, b);')
bt(
'try{while(true){willThrow()}}catch(result)switch(result){case 1:++result }',
# -- output --
'try {\n' +
' while (true) {\n' +
' willThrow()\n' +
' }\n' +
'} catch (result) switch (result) {\n' +
' case 1:\n' +
' ++result\n' +
'}')
bt('((e/((a+(b)*c)-d))^2)*5;', '((e / ((a + (b) * c) - d)) ^ 2) * 5;')
bt(
'function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
# -- output --
'function f(a, b) {\n' +
' if (a) b()\n' +
'}\n' +
'\n' +
'function g(a, b) {\n' +
' if (!a) b()\n' +
'}')
bt('a=[][ ]( );', 'a = [][]();')
bt('a=()( )[ ];', 'a = ()()[];')
bt('a=[b,c,d];', 'a = [b, c, d];')
bt('a= f[b];', 'a = f[b];')
# Issue #1151 - inside class methods
bt(
'export default class Test extends Component {\n' +
' render() {\n' +
' someOther();\n' +
' return null;\n' +
' }\n' +
'}')
bt(
'{\n' +
' files: a[][ {\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b(c)[ "im/design_standards/*.*" ],\n' +
' dest: "www/gui/build"\n' +
' } ]\n' +
'}',
# -- output --
'{\n' +
' files: a[][{\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b(c)["im/design_standards/*.*"],\n' +
' dest: "www/gui/build"\n' +
' }]\n' +
'}')
# Space in parens tests - (space_in_paren = "true", space_in_empty_paren = "false")
self.reset_options()
self.options.space_in_paren = true
self.options.space_in_empty_paren = false
bt('if(p) foo(a,b);', 'if ( p ) foo( a, b );')
bt(
'try{while(true){willThrow()}}catch(result)switch(result){case 1:++result }',
# -- output --
'try {\n' +
' while ( true ) {\n' +
' willThrow()\n' +
' }\n' +
'} catch ( result ) switch ( result ) {\n' +
' case 1:\n' +
' ++result\n' +
'}')
bt('((e/((a+(b)*c)-d))^2)*5;', '( ( e / ( ( a + ( b ) * c ) - d ) ) ^ 2 ) * 5;')
bt(
'function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
# -- output --
'function f( a, b ) {\n' +
' if ( a ) b()\n' +
'}\n' +
'\n' +
'function g( a, b ) {\n' +
' if ( !a ) b()\n' +
'}')
bt('a=[][ ]( );', 'a = [][]();')
bt('a=()( )[ ];', 'a = ()()[];')
bt('a=[b,c,d];', 'a = [ b, c, d ];')
bt('a= f[b];', 'a = f[ b ];')
# Issue #1151 - inside class methods
bt(
'export default class Test extends Component {\n' +
' render() {\n' +
' someOther();\n' +
' return null;\n' +
' }\n' +
'}')
bt(
'{\n' +
' files: a[][ {\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b(c)[ "im/design_standards/*.*" ],\n' +
' dest: "www/gui/build"\n' +
' } ]\n' +
'}',
# -- output --
'{\n' +
' files: a[][ {\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b( c )[ "im/design_standards/*.*" ],\n' +
' dest: "www/gui/build"\n' +
' } ]\n' +
'}')
# Space in parens tests - (space_in_paren = "true", space_in_empty_paren = "true")
self.reset_options()
self.options.space_in_paren = true
self.options.space_in_empty_paren = true
bt('if(p) foo(a,b);', 'if ( p ) foo( a, b );')
bt(
'try{while(true){willThrow()}}catch(result)switch(result){case 1:++result }',
# -- output --
'try {\n' +
' while ( true ) {\n' +
' willThrow( )\n' +
' }\n' +
'} catch ( result ) switch ( result ) {\n' +
' case 1:\n' +
' ++result\n' +
'}')
bt('((e/((a+(b)*c)-d))^2)*5;', '( ( e / ( ( a + ( b ) * c ) - d ) ) ^ 2 ) * 5;')
bt(
'function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
# -- output --
'function f( a, b ) {\n' +
' if ( a ) b( )\n' +
'}\n' +
'\n' +
'function g( a, b ) {\n' +
' if ( !a ) b( )\n' +
'}')
bt('a=[][ ]( );', 'a = [ ][ ]( );')
bt('a=()( )[ ];', 'a = ( )( )[ ];')
bt('a=[b,c,d];', 'a = [ b, c, d ];')
bt('a= f[b];', 'a = f[ b ];')
# Issue #1151 - inside class methods
bt(
'export default class Test extends Component {\n' +
' render() {\n' +
' someOther();\n' +
' return null;\n' +
' }\n' +
'}',
# -- output --
'export default class Test extends Component {\n' +
' render( ) {\n' +
' someOther( );\n' +
' return null;\n' +
' }\n' +
'}')
bt(
'{\n' +
' files: a[][ {\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b(c)[ "im/design_standards/*.*" ],\n' +
' dest: "www/gui/build"\n' +
' } ]\n' +
'}',
# -- output --
'{\n' +
' files: a[ ][ {\n' +
' expand: true,\n' +
' cwd: "www/gui/",\n' +
' src: b( c )[ "im/design_standards/*.*" ],\n' +
' dest: "www/gui/build"\n' +
' } ]\n' +
'}')
#============================================================
# general preserve_newlines tests - (preserve_newlines = "false")
self.reset_options()
self.options.preserve_newlines = false
bt(
'if (foo) // comment\n' +
' bar();')
bt(
'if (foo) // comment\n' +
' bar();')
bt(
'if (foo) // comment\n' +
' (bar());')
bt(
'if (foo) // comment\n' +
' (bar());')
bt(
'if (foo) // comment\n' +
' /asdf/;')
bt(
'this.oa = new OAuth(\n' +
' _requestToken,\n' +
' _accessToken,\n' +
' consumer_key\n' +
');',
# -- output --
'this.oa = new OAuth(_requestToken, _accessToken, consumer_key);')
bt(
'foo = {\n' +
' x: y, // #44\n' +
' w: z // #44\n' +
'}')
bt(
'switch (x) {\n' +
' case "a":\n' +
' // comment on newline\n' +
' break;\n' +
' case "b": // comment on same line\n' +
' break;\n' +
'}')
bt(
'this.type =\n' +
' this.options =\n' +
' // comment\n' +
' this.enabled null;',
# -- output --
'this.type = this.options =\n' +
' // comment\n' +
' this.enabled null;')
bt(
'someObj\n' +
' .someFunc1()\n' +
' // This comment should not break the indent\n' +
' .someFunc2();',
# -- output --
'someObj.someFunc1()\n' +
' // This comment should not break the indent\n' +
' .someFunc2();')
bt(
'if (true ||\n' +
'!true) return;',
# -- output --
'if (true || !true) return;')
bt(
'if\n' +
'(foo)\n' +
'if\n' +
'(bar)\n' +
'if\n' +
'(baz)\n' +
'whee();\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if\n' +
'(foo)\n' +
'if\n' +
'(bar)\n' +
'if\n' +
'(baz)\n' +
'whee();\n' +
'else\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz) whee();\n' +
' else a();')
bt(
'if (foo)\n' +
'bar();\n' +
'else\n' +
'car();',
# -- output --
'if (foo) bar();\n' +
'else car();')
bt(
'if (foo) if (bar) if (baz);\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz);\n' +
'a();')
bt(
'if (foo) if (bar) if (baz) whee();\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if (foo) a()\n' +
'if (bar) if (baz) whee();\n' +
'a();',
# -- output --
'if (foo) a()\n' +
'if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if (foo);\n' +
'if (bar) if (baz) whee();\n' +
'a();',
# -- output --
'if (foo);\n' +
'if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if (options)\n' +
' for (var p in options)\n' +
' this[p] = options[p];',
# -- output --
'if (options)\n' +
' for (var p in options) this[p] = options[p];')
bt(
'if (options) for (var p in options) this[p] = options[p];',
# -- output --
'if (options)\n' +
' for (var p in options) this[p] = options[p];')
bt(
'if (options) do q(); while (b());',
# -- output --
'if (options)\n' +
' do q(); while (b());')
bt(
'if (options) while (b()) q();',
# -- output --
'if (options)\n' +
' while (b()) q();')
bt(
'if (options) do while (b()) q(); while (a());',
# -- output --
'if (options)\n' +
' do\n' +
' while (b()) q(); while (a());')
bt(
'function f(a, b, c,\n' +
'd, e) {}',
# -- output --
'function f(a, b, c, d, e) {}')
bt(
'function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
# -- output --
'function f(a, b) {\n' +
' if (a) b()\n' +
'}\n' +
'\n' +
'function g(a, b) {\n' +
' if (!a) b()\n' +
'}')
bt(
'function f(a,b) {if(a) b()}\n' +
'\n' +
'\n' +
'\n' +
'function g(a,b) {if(!a) b()}',
# -- output --
'function f(a, b) {\n' +
' if (a) b()\n' +
'}\n' +
'\n' +
'function g(a, b) {\n' +
' if (!a) b()\n' +
'}')
bt(
'(if(a) b())(if(a) b())',
# -- output --
'(\n' +
' if (a) b())(\n' +
' if (a) b())')
bt(
'(if(a) b())\n' +
'\n' +
'\n' +
'(if(a) b())',
# -- output --
'(\n' +
' if (a) b())\n' +
'(\n' +
' if (a) b())')
bt(
'if\n' +
'(a)\n' +
'b();',
# -- output --
'if (a) b();')
bt(
'var a =\n' +
'foo',
# -- output --
'var a = foo')
bt(
'var a = {\n' +
'"a":1,\n' +
'"b":2}',
# -- output --
'var a = {\n' +
' "a": 1,\n' +
' "b": 2\n' +
'}')
bt(
'var a = {\n' +
'\'a\':1,\n' +
'\'b\':2}',
# -- output --
'var a = {\n' +
' \'a\': 1,\n' +
' \'b\': 2\n' +
'}')
bt('var a = /*i*/ "b";')
bt(
'var a = /*i*/\n' +
'"b";',
# -- output --
'var a = /*i*/ "b";')
bt(
'{\n' +
'\n' +
'\n' +
'"x"\n' +
'}',
# -- output --
'{\n' +
' "x"\n' +
'}')
bt(
'if(a &&\n' +
'b\n' +
'||\n' +
'c\n' +
'||d\n' +
'&&\n' +
'e) e = f',
# -- output --
'if (a && b || c || d && e) e = f')
bt(
'if(a &&\n' +
'(b\n' +
'||\n' +
'c\n' +
'||d)\n' +
'&&\n' +
'e) e = f',
# -- output --
'if (a && (b || c || d) && e) e = f')
test_fragment(
'\n' +
'\n' +
'"x"',
# -- output --
'"x"')
test_fragment(
'{\n' +
'\n' +
'"x"\n' +
'h=5;\n' +
'}',
# -- output --
'{\n' +
' "x"\n' +
' h = 5;\n' +
'}')
bt(
'var a = "foo" +\n' +
' "bar";',
# -- output --
'var a = "foo" + "bar";')
bt(
'var a = 42; // foo\n' +
'\n' +
'var b;',
# -- output --
'var a = 42; // foo\n' +
'var b;')
bt(
'var a = 42; // foo\n' +
'\n' +
'\n' +
'var b;',
# -- output --
'var a = 42; // foo\n' +
'var b;')
bt(
'a = 1;\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'b = 2;',
# -- output --
'a = 1;\n' +
'b = 2;')
# general preserve_newlines tests - (preserve_newlines = "true")
self.reset_options()
self.options.preserve_newlines = true
bt(
'if (foo) // comment\n' +
' bar();')
bt(
'if (foo) // comment\n' +
' bar();')
bt(
'if (foo) // comment\n' +
' (bar());')
bt(
'if (foo) // comment\n' +
' (bar());')
bt(
'if (foo) // comment\n' +
' /asdf/;')
bt(
'this.oa = new OAuth(\n' +
' _requestToken,\n' +
' _accessToken,\n' +
' consumer_key\n' +
');')
bt(
'foo = {\n' +
' x: y, // #44\n' +
' w: z // #44\n' +
'}')
bt(
'switch (x) {\n' +
' case "a":\n' +
' // comment on newline\n' +
' break;\n' +
' case "b": // comment on same line\n' +
' break;\n' +
'}')
bt(
'this.type =\n' +
' this.options =\n' +
' // comment\n' +
' this.enabled null;')
bt(
'someObj\n' +
' .someFunc1()\n' +
' // This comment should not break the indent\n' +
' .someFunc2();')
bt(
'if (true ||\n' +
'!true) return;',
# -- output --
'if (true ||\n' +
' !true) return;')
bt(
'if\n' +
'(foo)\n' +
'if\n' +
'(bar)\n' +
'if\n' +
'(baz)\n' +
'whee();\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz)\n' +
' whee();\n' +
'a();')
bt(
'if\n' +
'(foo)\n' +
'if\n' +
'(bar)\n' +
'if\n' +
'(baz)\n' +
'whee();\n' +
'else\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz)\n' +
' whee();\n' +
' else\n' +
' a();')
bt(
'if (foo)\n' +
'bar();\n' +
'else\n' +
'car();',
# -- output --
'if (foo)\n' +
' bar();\n' +
'else\n' +
' car();')
bt(
'if (foo) if (bar) if (baz);\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz);\n' +
'a();')
bt(
'if (foo) if (bar) if (baz) whee();\n' +
'a();',
# -- output --
'if (foo)\n' +
' if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if (foo) a()\n' +
'if (bar) if (baz) whee();\n' +
'a();',
# -- output --
'if (foo) a()\n' +
'if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if (foo);\n' +
'if (bar) if (baz) whee();\n' +
'a();',
# -- output --
'if (foo);\n' +
'if (bar)\n' +
' if (baz) whee();\n' +
'a();')
bt(
'if (options)\n' +
' for (var p in options)\n' +
' this[p] = options[p];')
bt(
'if (options) for (var p in options) this[p] = options[p];',
# -- output --
'if (options)\n' +
' for (var p in options) this[p] = options[p];')
bt(
'if (options) do q(); while (b());',
# -- output --
'if (options)\n' +
' do q(); while (b());')
bt(
'if (options) while (b()) q();',
# -- output --
'if (options)\n' +
' while (b()) q();')
bt(
'if (options) do while (b()) q(); while (a());',
# -- output --
'if (options)\n' +
' do\n' +
' while (b()) q(); while (a());')
bt(
'function f(a, b, c,\n' +
'd, e) {}',
# -- output --
'function f(a, b, c,\n' +
' d, e) {}')
bt(
'function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
# -- output --
'function f(a, b) {\n' +
' if (a) b()\n' +
'}\n' +
'\n' +
'function g(a, b) {\n' +
' if (!a) b()\n' +
'}')
bt(
'function f(a,b) {if(a) b()}\n' +
'\n' +
'\n' +
'\n' +
'function g(a,b) {if(!a) b()}',
# -- output --
'function f(a, b) {\n' +
' if (a) b()\n' +
'}\n' +
'\n' +
'\n' +
'\n' +
'function g(a, b) {\n' +
' if (!a) b()\n' +
'}')
bt(
'(if(a) b())(if(a) b())',
# -- output --
'(\n' +
' if (a) b())(\n' +
' if (a) b())')
bt(
'(if(a) b())\n' +
'\n' +
'\n' +
'(if(a) b())',
# -- output --
'(\n' +
' if (a) b())\n' +
'\n' +
'\n' +
'(\n' +
' if (a) b())')
bt(
'if\n' +
'(a)\n' +
'b();',
# -- output --
'if (a)\n' +
' b();')
bt(
'var a =\n' +
'foo',
# -- output --
'var a =\n' +
' foo')
bt(
'var a = {\n' +
'"a":1,\n' +
'"b":2}',
# -- output --
'var a = {\n' +
' "a": 1,\n' +
' "b": 2\n' +
'}')
bt(
'var a = {\n' +
'\'a\':1,\n' +
'\'b\':2}',
# -- output --
'var a = {\n' +
' \'a\': 1,\n' +
' \'b\': 2\n' +
'}')
bt('var a = /*i*/ "b";')
bt(
'var a = /*i*/\n' +
'"b";',
# -- output --
'var a = /*i*/\n' +
' "b";')
bt(
'{\n' +
'\n' +
'\n' +
'"x"\n' +
'}',
# -- output --
'{\n' +
'\n' +
'\n' +
' "x"\n' +
'}')
bt(
'if(a &&\n' +
'b\n' +
'||\n' +
'c\n' +
'||d\n' +
'&&\n' +
'e) e = f',
# -- output --
'if (a &&\n' +
' b ||\n' +
' c ||\n' +
' d &&\n' +
' e) e = f')
bt(
'if(a &&\n' +
'(b\n' +
'||\n' +
'c\n' +
'||d)\n' +
'&&\n' +
'e) e = f',
# -- output --
'if (a &&\n' +
' (b ||\n' +
' c ||\n' +
' d) &&\n' +
' e) e = f')
test_fragment(
'\n' +
'\n' +
'"x"',
# -- output --
'"x"')
test_fragment(
'{\n' +
'\n' +
'"x"\n' +
'h=5;\n' +
'}',
# -- output --
'{\n' +
'\n' +
' "x"\n' +
' h = 5;\n' +
'}')
bt(
'var a = "foo" +\n' +
' "bar";')
bt(
'var a = 42; // foo\n' +
'\n' +
'var b;')
bt(
'var a = 42; // foo\n' +
'\n' +
'\n' +
'var b;')
bt(
'a = 1;\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'b = 2;')
#============================================================
# break chained methods - (break_chained_methods = "false", preserve_newlines = "false")
self.reset_options()
self.options.break_chained_methods = false
self.options.preserve_newlines = false
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'foo.bar().baz().cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat); foo.bar().baz().cucumber(fat)',
# -- output --
'foo.bar().baz().cucumber(fat);\n' +
'foo.bar().baz().cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)\n' +
' foo.bar().baz().cucumber(fat)',
# -- output --
'foo.bar().baz().cucumber(fat)\n' +
'foo.bar().baz().cucumber(fat)')
bt(
'this\n' +
'.something = foo.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'this.something = foo.bar().baz().cucumber(fat)')
bt('this.something.xxx = foo.moo.bar()')
bt(
'this\n' +
'.something\n' +
'.xxx = foo.moo\n' +
'.bar()',
# -- output --
'this.something.xxx = foo.moo.bar()')
# optional chaining operator
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'foo?.bar()?.baz()?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat); foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo?.bar()?.baz()?.cucumber(fat);\n' +
'foo?.bar()?.baz()?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)\n' +
' foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo?.bar()?.baz()?.cucumber(fat)\n' +
'foo?.bar()?.baz()?.cucumber(fat)')
bt(
'this\n' +
'?.something = foo?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'this?.something = foo?.bar()?.baz()?.cucumber(fat)')
bt('this?.something?.xxx = foo?.moo?.bar()')
bt(
'this\n' +
'?.something\n' +
'?.xxx = foo?.moo\n' +
'?.bar()',
# -- output --
'this?.something?.xxx = foo?.moo?.bar()')
# break chained methods - (break_chained_methods = "false", preserve_newlines = "true")
self.reset_options()
self.options.break_chained_methods = false
self.options.preserve_newlines = true
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'foo\n' +
' .bar()\n' +
' .baz().cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat); foo.bar().baz().cucumber(fat)',
# -- output --
'foo\n' +
' .bar()\n' +
' .baz().cucumber(fat);\n' +
'foo.bar().baz().cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)\n' +
' foo.bar().baz().cucumber(fat)',
# -- output --
'foo\n' +
' .bar()\n' +
' .baz().cucumber(fat)\n' +
'foo.bar().baz().cucumber(fat)')
bt(
'this\n' +
'.something = foo.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'this\n' +
' .something = foo.bar()\n' +
' .baz().cucumber(fat)')
bt('this.something.xxx = foo.moo.bar()')
bt(
'this\n' +
'.something\n' +
'.xxx = foo.moo\n' +
'.bar()',
# -- output --
'this\n' +
' .something\n' +
' .xxx = foo.moo\n' +
' .bar()')
# optional chaining operator
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'foo\n' +
' ?.bar()\n' +
' ?.baz()?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat); foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo\n' +
' ?.bar()\n' +
' ?.baz()?.cucumber(fat);\n' +
'foo?.bar()?.baz()?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)\n' +
' foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo\n' +
' ?.bar()\n' +
' ?.baz()?.cucumber(fat)\n' +
'foo?.bar()?.baz()?.cucumber(fat)')
bt(
'this\n' +
'?.something = foo?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'this\n' +
' ?.something = foo?.bar()\n' +
' ?.baz()?.cucumber(fat)')
bt('this?.something?.xxx = foo?.moo?.bar()')
bt(
'this\n' +
'?.something\n' +
'?.xxx = foo?.moo\n' +
'?.bar()',
# -- output --
'this\n' +
' ?.something\n' +
' ?.xxx = foo?.moo\n' +
' ?.bar()')
# break chained methods - (break_chained_methods = "true", preserve_newlines = "false")
self.reset_options()
self.options.break_chained_methods = true
self.options.preserve_newlines = false
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat); foo.bar().baz().cucumber(fat)',
# -- output --
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat);\n' +
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)\n' +
' foo.bar().baz().cucumber(fat)',
# -- output --
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)\n' +
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt(
'this\n' +
'.something = foo.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'this.something = foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt('this.something.xxx = foo.moo.bar()')
bt(
'this\n' +
'.something\n' +
'.xxx = foo.moo\n' +
'.bar()',
# -- output --
'this.something.xxx = foo.moo.bar()')
# optional chaining operator
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat); foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat);\n' +
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)\n' +
' foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)\n' +
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt(
'this\n' +
'?.something = foo?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'this?.something = foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt('this?.something?.xxx = foo?.moo?.bar()')
bt(
'this\n' +
'?.something\n' +
'?.xxx = foo?.moo\n' +
'?.bar()',
# -- output --
'this?.something?.xxx = foo?.moo?.bar()')
# break chained methods - (break_chained_methods = "true", preserve_newlines = "true")
self.reset_options()
self.options.break_chained_methods = true
self.options.preserve_newlines = true
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'foo\n' +
' .bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat); foo.bar().baz().cucumber(fat)',
# -- output --
'foo\n' +
' .bar()\n' +
' .baz()\n' +
' .cucumber(fat);\n' +
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt(
'foo\n' +
'.bar()\n' +
'.baz().cucumber(fat)\n' +
' foo.bar().baz().cucumber(fat)',
# -- output --
'foo\n' +
' .bar()\n' +
' .baz()\n' +
' .cucumber(fat)\n' +
'foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt(
'this\n' +
'.something = foo.bar()\n' +
'.baz().cucumber(fat)',
# -- output --
'this\n' +
' .something = foo.bar()\n' +
' .baz()\n' +
' .cucumber(fat)')
bt('this.something.xxx = foo.moo.bar()')
bt(
'this\n' +
'.something\n' +
'.xxx = foo.moo\n' +
'.bar()',
# -- output --
'this\n' +
' .something\n' +
' .xxx = foo.moo\n' +
' .bar()')
# optional chaining operator
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'foo\n' +
' ?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat); foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo\n' +
' ?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat);\n' +
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt(
'foo\n' +
'?.bar()\n' +
'?.baz()?.cucumber(fat)\n' +
' foo?.bar()?.baz()?.cucumber(fat)',
# -- output --
'foo\n' +
' ?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)\n' +
'foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt(
'this\n' +
'?.something = foo?.bar()\n' +
'?.baz()?.cucumber(fat)',
# -- output --
'this\n' +
' ?.something = foo?.bar()\n' +
' ?.baz()\n' +
' ?.cucumber(fat)')
bt('this?.something?.xxx = foo?.moo?.bar()')
bt(
'this\n' +
'?.something\n' +
'?.xxx = foo?.moo\n' +
'?.bar()',
# -- output --
'this\n' +
' ?.something\n' +
' ?.xxx = foo?.moo\n' +
' ?.bar()')
#============================================================
# line wrapping 0
self.reset_options()
self.options.preserve_newlines = false
self.options.wrap_line_length = 0
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
'return between_return_and_expression_should_never_wrap.but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_.okay();\n' +
'object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
' return between_return_and_expression_should_never_wrap.but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_.okay();\n' +
' object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 70
self.reset_options()
self.options.preserve_newlines = false
self.options.wrap_line_length = 70
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
'return between_return_and_expression_should_never_wrap.but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_.okay();\n' +
'object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_.okay();\n' +
' object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 40
self.reset_options()
self.options.preserve_newlines = false
self.options.wrap_line_length = 40
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f &&\n' +
' "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();\n' +
'object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
'}')
# Issue #1932 - Javascript object property with -/+ symbol wraps issue
bt(
'{\n' +
' "1234567891234567891234567891234": -433,\n' +
' "abcdefghijklmnopqrstuvwxyz12345": +11\n' +
'}',
# -- output --
'{\n' +
' "1234567891234567891234567891234": -433,\n' +
' "abcdefghijklmnopqrstuvwxyz12345": +11\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f &&\n' +
' "sass") || (leans &&\n' +
' mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 41
self.reset_options()
self.options.preserve_newlines = false
self.options.wrap_line_length = 41
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") ||\n' +
' (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();\n' +
'object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f &&\n' +
' "sass") || (leans &&\n' +
' mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 45
self.reset_options()
self.options.preserve_newlines = false
self.options.wrap_line_length = 45
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") || (\n' +
' leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block)\n' +
' that_is_.okay();\n' +
'object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f && "sass") ||\n' +
' (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();\n' +
' object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 0
self.reset_options()
self.options.preserve_newlines = true
self.options.wrap_line_length = 0
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap.but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();\n' +
'object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap.but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 70
self.reset_options()
self.options.preserve_newlines = true
self.options.wrap_line_length = 70
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap.but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();\n' +
'object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f && "sass") || (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token + 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap + but_this_can,\n' +
' propertz: first_token_should_never_wrap + !but_this_can,\n' +
' proper: "first_token_should_never_wrap" + "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 40
self.reset_options()
self.options.preserve_newlines = true
self.options.wrap_line_length = 40
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f &&\n' +
' "sass") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
'object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f &&\n' +
' "sass") || (leans &&\n' +
' mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 41
self.reset_options()
self.options.preserve_newlines = true
self.options.wrap_line_length = 41
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") ||\n' +
' (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
'object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f &&\n' +
' "sass") || (leans &&\n' +
' mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# line wrapping 45
self.reset_options()
self.options.preserve_newlines = true
self.options.wrap_line_length = 45
test_fragment(
'' + wrap_input_1 + '',
# -- output --
'foo.bar().baz().cucumber((f && "sass") || (\n' +
' leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block)\n' +
' that_is_\n' +
' .okay();\n' +
'object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
'}')
test_fragment(
'' + wrap_input_2 + '',
# -- output --
'{\n' +
' foo.bar().baz().cucumber((f && "sass") ||\n' +
' (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' return between_return_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' throw between_throw_and_expression_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
' object_literal = {\n' +
' propertx: first_token +\n' +
' 12345678.99999E-6,\n' +
' property: first_token_should_never_wrap +\n' +
' but_this_can,\n' +
' propertz: first_token_should_never_wrap +\n' +
' !but_this_can,\n' +
' proper: "first_token_should_never_wrap" +\n' +
' "but_this_can"\n' +
' }\n' +
'}')
#============================================================
# general preserve_newlines tests preserve limit
self.reset_options()
self.options.preserve_newlines = true
self.options.max_preserve_newlines = 8
bt(
'a = 1;\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'b = 2;',
# -- output --
'a = 1;\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'\n' +
'b = 2;')
#============================================================
# more random test
self.reset_options()
bt('return function();')
bt('var a = function();')
bt('var a = 5 + function();')
# actionscript import
bt('import foo.*;')
# actionscript
bt('function f(a: a, b: b)')
bt(
'function a(a) {} function b(b) {} function c(c) {}',
# -- output --
'function a(a) {}\n' +
'\n' +
'function b(b) {}\n' +
'\n' +
'function c(c) {}')
bt('foo(a, function() {})')
bt('foo(a, /regex/)')
bt(
'/* foo */\n' +
'"x"')
test_fragment(
'roo = {\n' +
' /*\n' +
' ****\n' +
' FOO\n' +
' ****\n' +
' */\n' +
' BAR: 0\n' +
'};')
test_fragment(
'if (zz) {\n' +
' // ....\n' +
'}\n' +
'(function')
bt(
'a = //comment\n' +
' /regex/;')
bt('var a = new function();')
bt('new function')
bt(
'if (a)\n' +
'{\n' +
'b;\n' +
'}\n' +
'else\n' +
'{\n' +
'c;\n' +
'}',
# -- output --
'if (a) {\n' +
' b;\n' +
'} else {\n' +
' c;\n' +
'}')
bt('fn`tagged`')
bt('fn()`tagged`')
bt('fn`${algo} ${`6string`}`')
bt('fn`${fn2()} more text ${`${`more text`}`} banana ${fn3`test`} ${fn4()`moretest banana2`}`')
bt('`untagged`+`untagged`', '`untagged` + `untagged`')
bt('fun() `taggedd`')
bt('fn[0]`tagged`', 'fn[0] `tagged`')
#============================================================
# operator_position option - ensure no newlines if preserve_newlines is false - (preserve_newlines = "false")
self.reset_options()
self.options.preserve_newlines = false
bt(
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
# operator_position option - ensure no newlines if preserve_newlines is false - (operator_position = ""before-newline"", preserve_newlines = "false")
self.reset_options()
self.options.operator_position = 'before-newline'
self.options.preserve_newlines = false
bt(
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
# operator_position option - ensure no newlines if preserve_newlines is false - (operator_position = ""after-newline"", preserve_newlines = "false")
self.reset_options()
self.options.operator_position = 'after-newline'
self.options.preserve_newlines = false
bt(
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
# operator_position option - ensure no newlines if preserve_newlines is false - (operator_position = ""preserve-newline"", preserve_newlines = "false")
self.reset_options()
self.options.operator_position = 'preserve-newline'
self.options.preserve_newlines = false
bt(
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b - c / d * e % f;\n' +
'var res = g & h | i ^ j |> console.log;\n' +
'var res = (k && l || m) ? n ?? nn : o;\n' +
'var res = p >> q << r >>> s;\n' +
'var res = t === u !== v != w == x >= y <= z > aa < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac + -ad')
#============================================================
# operator_position option - set to "before-newline" (default value) - ()
self.reset_options()
# comprehensive, various newlines
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b -\n' +
' c /\n' +
' d * e %\n' +
' f;\n' +
'var res = g & h |\n' +
' i ^\n' +
' j |>\n' +
' console.log;\n' +
'var res = (k &&\n' +
' l ||\n' +
' m) ?\n' +
' n ??\n' +
' nn :\n' +
' o;\n' +
'var res = p >>\n' +
' q <<\n' +
' r >>>\n' +
' s;\n' +
'var res = t\n' +
'\n' +
' ===\n' +
' u !== v !=\n' +
' w ==\n' +
' x >=\n' +
' y <= z > aa <\n' +
' ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac +\n' +
' -ad')
# colon special case
bt(
'var a = {\n' +
' b\n' +
': bval,\n' +
' c:\n' +
'cval\n' +
' ,d: dval\n' +
'};\n' +
'var e = f ? g\n' +
': h;\n' +
'var i = j ? k :\n' +
'l;',
# -- output --
'var a = {\n' +
' b: bval,\n' +
' c: cval,\n' +
' d: dval\n' +
'};\n' +
'var e = f ? g :\n' +
' h;\n' +
'var i = j ? k :\n' +
' l;')
# catch-all, includes brackets and other various code
bt(
'var d = 1;\n' +
'if (a === b\n' +
' && c) {\n' +
' d = (c * everything\n' +
' / something_else) %\n' +
' b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple) ||\n' +
' (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many ||\n' +
' anOcean\n' +
' || aRiver);\n' +
'}',
# -- output --
'var d = 1;\n' +
'if (a === b &&\n' +
' c) {\n' +
' d = (c * everything /\n' +
' something_else) %\n' +
' b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple) ||\n' +
' (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many ||\n' +
' anOcean ||\n' +
' aRiver);\n' +
'}')
# operator_position option - set to "before-newline" (default value) - (operator_position = ""before-newline"")
self.reset_options()
self.options.operator_position = 'before-newline'
# comprehensive, various newlines
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b -\n' +
' c /\n' +
' d * e %\n' +
' f;\n' +
'var res = g & h |\n' +
' i ^\n' +
' j |>\n' +
' console.log;\n' +
'var res = (k &&\n' +
' l ||\n' +
' m) ?\n' +
' n ??\n' +
' nn :\n' +
' o;\n' +
'var res = p >>\n' +
' q <<\n' +
' r >>>\n' +
' s;\n' +
'var res = t\n' +
'\n' +
' ===\n' +
' u !== v !=\n' +
' w ==\n' +
' x >=\n' +
' y <= z > aa <\n' +
' ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac +\n' +
' -ad')
# colon special case
bt(
'var a = {\n' +
' b\n' +
': bval,\n' +
' c:\n' +
'cval\n' +
' ,d: dval\n' +
'};\n' +
'var e = f ? g\n' +
': h;\n' +
'var i = j ? k :\n' +
'l;',
# -- output --
'var a = {\n' +
' b: bval,\n' +
' c: cval,\n' +
' d: dval\n' +
'};\n' +
'var e = f ? g :\n' +
' h;\n' +
'var i = j ? k :\n' +
' l;')
# catch-all, includes brackets and other various code
bt(
'var d = 1;\n' +
'if (a === b\n' +
' && c) {\n' +
' d = (c * everything\n' +
' / something_else) %\n' +
' b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple) ||\n' +
' (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many ||\n' +
' anOcean\n' +
' || aRiver);\n' +
'}',
# -- output --
'var d = 1;\n' +
'if (a === b &&\n' +
' c) {\n' +
' d = (c * everything /\n' +
' something_else) %\n' +
' b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple) ||\n' +
' (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many ||\n' +
' anOcean ||\n' +
' aRiver);\n' +
'}')
#============================================================
# operator_position option - set to "after_newline"
self.reset_options()
self.options.operator_position = 'after-newline'
# comprehensive, various newlines
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b\n' +
' - c\n' +
' / d * e\n' +
' % f;\n' +
'var res = g & h\n' +
' | i\n' +
' ^ j\n' +
' |> console.log;\n' +
'var res = (k\n' +
' && l\n' +
' || m)\n' +
' ? n\n' +
' ?? nn\n' +
' : o;\n' +
'var res = p\n' +
' >> q\n' +
' << r\n' +
' >>> s;\n' +
'var res = t\n' +
'\n' +
' === u !== v\n' +
' != w\n' +
' == x\n' +
' >= y <= z > aa\n' +
' < ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac\n' +
' + -ad')
# colon special case
bt(
'var a = {\n' +
' b\n' +
': bval,\n' +
' c:\n' +
'cval\n' +
' ,d: dval\n' +
'};\n' +
'var e = f ? g\n' +
': h;\n' +
'var i = j ? k :\n' +
'l;',
# -- output --
'var a = {\n' +
' b: bval,\n' +
' c: cval,\n' +
' d: dval\n' +
'};\n' +
'var e = f ? g\n' +
' : h;\n' +
'var i = j ? k\n' +
' : l;')
# catch-all, includes brackets and other various code
bt(
'var d = 1;\n' +
'if (a === b\n' +
' && c) {\n' +
' d = (c * everything\n' +
' / something_else) %\n' +
' b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple) ||\n' +
' (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many ||\n' +
' anOcean\n' +
' || aRiver);\n' +
'}',
# -- output --
'var d = 1;\n' +
'if (a === b\n' +
' && c) {\n' +
' d = (c * everything\n' +
' / something_else)\n' +
' % b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple)\n' +
' || (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many\n' +
' || anOcean\n' +
' || aRiver);\n' +
'}')
#============================================================
# operator_position option - set to "preserve-newline"
self.reset_options()
self.options.operator_position = 'preserve-newline'
# comprehensive, various newlines
bt(
'var res = a + b\n' +
'- c /\n' +
'd * e\n' +
'%\n' +
'f;\n' +
' var res = g & h\n' +
'| i ^\n' +
'j\n' +
'|> console.log;\n' +
'var res = (k &&\n' +
'l\n' +
'|| m) ?\n' +
'n\n' +
'?? nn\n' +
': o\n' +
';\n' +
'var res = p\n' +
'>> q <<\n' +
'r\n' +
'>>> s;\n' +
'var res\n' +
' = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
'w\n' +
'== x >=\n' +
'y <= z > aa <\n' +
'ab;\n' +
'res??=a;res||=b;res&&=c;\n' +
'ac +\n' +
'-ad',
# -- output --
'var res = a + b\n' +
' - c /\n' +
' d * e\n' +
' %\n' +
' f;\n' +
'var res = g & h\n' +
' | i ^\n' +
' j\n' +
' |> console.log;\n' +
'var res = (k &&\n' +
' l\n' +
' || m) ?\n' +
' n\n' +
' ?? nn\n' +
' : o;\n' +
'var res = p\n' +
' >> q <<\n' +
' r\n' +
' >>> s;\n' +
'var res = t\n' +
'\n' +
' === u !== v\n' +
' !=\n' +
' w\n' +
' == x >=\n' +
' y <= z > aa <\n' +
' ab;\n' +
'res ??= a;\n' +
'res ||= b;\n' +
'res &&= c;\n' +
'ac +\n' +
' -ad')
# colon special case
bt(
'var a = {\n' +
' b\n' +
': bval,\n' +
' c:\n' +
'cval\n' +
' ,d: dval\n' +
'};\n' +
'var e = f ? g\n' +
': h;\n' +
'var i = j ? k :\n' +
'l;',
# -- output --
'var a = {\n' +
' b: bval,\n' +
' c: cval,\n' +
' d: dval\n' +
'};\n' +
'var e = f ? g\n' +
' : h;\n' +
'var i = j ? k :\n' +
' l;')
# catch-all, includes brackets and other various code
bt(
'var d = 1;\n' +
'if (a === b\n' +
' && c) {\n' +
' d = (c * everything\n' +
' / something_else) %\n' +
' b;\n' +
' e\n' +
' += d;\n' +
'\n' +
'} else if (!(complex && simple) ||\n' +
' (emotion && emotion.name === "happy")) {\n' +
' cryTearsOfJoy(many ||\n' +
' anOcean\n' +
' || aRiver);\n' +
'}')
#============================================================
# Yield tests
self.reset_options()
bt('yield /foo\\//;')
bt('result = yield pgClient.query_(queryString);')
bt('yield [1, 2]')
bt('yield function() {};')
bt('yield* bar();')
# yield should have no space between yield and star
bt('yield * bar();', 'yield* bar();')
# yield should have space between star and generator
bt('yield *bar();', 'yield* bar();')
#============================================================
# Async / await tests
self.reset_options()
bt('async function foo() {}')
bt('let w = async function foo() {}')
bt(
'async function foo() {}\n' +
'var x = await foo();')
# async function as an input to another function
bt('wrapper(async function foo() {})')
# await on inline anonymous function. should have a space after await
bt(
'async function() {\n' +
' var w = await(async function() {\n' +
' return await foo();\n' +
' })();\n' +
'}',
# -- output --
'async function() {\n' +
' var w = await (async function() {\n' +
' return await foo();\n' +
' })();\n' +
'}')
# Regression test #1228
bt('const module = await import("...")')
# Regression test #1658
bt('.')
# ensure that this doesn't break anyone with the async library
bt('async.map(function(t) {})')
# async on arrow function. should have a space after async
bt(
'async() => {}',
# -- output --
'async () => {}')
# async on arrow function. should have a space after async
bt(
'async() => {\n' +
' return 5;\n' +
'}',
# -- output --
'async () => {\n' +
' return 5;\n' +
'}')
# async on arrow function returning expression. should have a space after async
bt(
'async() => 5;',
# -- output --
'async () => 5;')
# async on arrow function returning object literal. should have a space after async
bt(
'async(x) => ({\n' +
' foo: "5"\n' +
'})',
# -- output --
'async (x) => ({\n' +
' foo: "5"\n' +
'})')
bt(
'async (x) => {\n' +
' return x * 2;\n' +
'}')
bt('async () => 5;')
bt('async x => x * 2;')
bt(
'async function() {\n' +
' const obj = {\n' +
' a: 1,\n' +
' b: await fn(),\n' +
' c: 2\n' +
' };\n' +
'}')
bt(
'const a = 1,\n' +
' b = a ? await foo() : b,\n' +
' c = await foo(),\n' +
' d = 3,\n' +
' e = (await foo()),\n' +
' f = 4;')
bt(
'a = {\n' +
' myVar: async function() {\n' +
' return a;\n' +
' },\n' +
' myOtherVar: async function() {\n' +
' yield b;\n' +
' }\n' +
'}')
bt(
'a = {\n' +
' myVar: async () => {\n' +
' return a;\n' +
' },\n' +
' myOtherVar: async async () => {\n' +
' yield b;\n' +
' }\n' +
'}')
#============================================================
# e4x - Test that e4x literals passed through when e4x-option is enabled
self.reset_options()
self.options.e4x = true
bt(
'xml=\n' +
' foo x ;',
# -- output --
'xml = \n' +
' foo x ;')
bt(' ')
bt(' ')
bt(' ')
bt(' ')
bt(' ')
# Handles inline expressions
bt(
'xml=<{a} b="c">\n' +
' foo x{a}>;',
# -- output --
'xml = <{a} b="c">\n' +
' foo x{a}>;')
bt(
'xml=<{a} b="c">\n' +
' \n' +
' foo x{a}>;',
# -- output --
'xml = <{a} b="c">\n' +
' \n' +
' foo x{a}>;')
# xml literals with special characters in elem names - see http://www.w3.org/TR/REC-xml/#NT-NameChar
bt('xml = <_:.valid.xml- _:.valid.xml-="123"/>;')
# xml literals with attributes without equal sign
bt('xml = ;')
# Handles CDATA
bt(
'xml=\n' +
' foo x/]]>;',
# -- output --
'xml = \n' +
' foo x/]]>;')
bt('xml=;', 'xml = ;')
bt('xml= {}]]>;', 'xml = {}]]>;')
# JSX - working jsx from http://prettydiff.com/unit_tests/beautification_javascript_jsx.txt
bt(
'var ListItem = React.createClass({\n' +
' render: function() {\n' +
' return (\n' +
' \n' +
' \n' +
' this.props.item.name\n' +
' \n' +
' \n' +
' );\n' +
' }\n' +
'});')
bt(
'var List = React.createClass({\n' +
' renderList: function() {\n' +
' return this.props.items.map(function(item) {\n' +
' return ;\n' +
' });\n' +
' },\n' +
'\n' +
' render: function() {\n' +
' return \n' +
' this.renderList()\n' +
' \n' +
' }\n' +
'});')
bt(
'var Mist = React.createClass({\n' +
' renderList: function() {\n' +
' return this.props.items.map(function(item) {\n' +
' return {item}} key={item.id} />;\n' +
' });\n' +
' }\n' +
'});')
bt(
'// JSX\n' +
'var box = \n' +
' {shouldShowAnswer(user) ?\n' +
' no : \n' +
' Text Content\n' +
' }\n' +
' ;\n' +
'var a = function() {\n' +
' return asdf ;\n' +
'};\n' +
'\n' +
'var HelloMessage = React.createClass({\n' +
' render: function() {\n' +
' return Hello {this.props.name}
;\n' +
' }\n' +
'});\n' +
'React.render( , mountNode);')
bt(
'var Timer = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {\n' +
' secondsElapsed: 0\n' +
' };\n' +
' },\n' +
' tick: function() {\n' +
' this.setState({\n' +
' secondsElapsed: this.state.secondsElapsed + 1\n' +
' });\n' +
' },\n' +
' componentDidMount: function() {\n' +
' this.interval = setInterval(this.tick, 1000);\n' +
' },\n' +
' componentWillUnmount: function() {\n' +
' clearInterval(this.interval);\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' Seconds Elapsed: {this.state.secondsElapsed}
\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render( , mountNode);')
bt(
'var TodoList = React.createClass({\n' +
' render: function() {\n' +
' var createItem = function(itemText) {\n' +
' return {itemText} ;\n' +
' };\n' +
' return {this.props.items.map(createItem)} ;\n' +
' }\n' +
'});')
bt(
'var TodoApp = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {\n' +
' items: [],\n' +
' text: \'\'\n' +
' };\n' +
' },\n' +
' onChange: function(e) {\n' +
' this.setState({\n' +
' text: e.target.value\n' +
' });\n' +
' },\n' +
' handleSubmit: function(e) {\n' +
' e.preventDefault();\n' +
' var nextItems = this.state.items.concat([this.state.text]);\n' +
' var nextText = \'\';\n' +
' this.setState({\n' +
' items: nextItems,\n' +
' text: nextText\n' +
' });\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' \n' +
'
TODO \n' +
' \n' +
' \n' +
'
\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render( , mountNode);')
bt(
'var converter = new Showdown.converter();\n' +
'var MarkdownEditor = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {value: \'Type some *markdown* here!\'};\n' +
' },\n' +
' handleChange: function() {\n' +
' this.setState({value: this.refs.textarea.getDOMNode().value});\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' \n' +
'
Input \n' +
'
\n' +
'
Output \n' +
'
\n' +
'
\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render( , mountNode);',
# -- output --
'var converter = new Showdown.converter();\n' +
'var MarkdownEditor = React.createClass({\n' +
' getInitialState: function() {\n' +
' return {\n' +
' value: \'Type some *markdown* here!\'\n' +
' };\n' +
' },\n' +
' handleChange: function() {\n' +
' this.setState({\n' +
' value: this.refs.textarea.getDOMNode().value\n' +
' });\n' +
' },\n' +
' render: function() {\n' +
' return (\n' +
' \n' +
'
Input \n' +
'
\n' +
'
Output \n' +
'
\n' +
'
\n' +
' );\n' +
' }\n' +
'});\n' +
'React.render( , mountNode);')
# JSX - Not quite correct jsx formatting that still works
bt(
'var content = (\n' +
' \n' +
' {/* child comment, put {} around */}\n' +
' \n' +
' \n' +
' );\n' +
'var qwer = A dropdown list Do Something Do Something Fun! Do Something Else ;\n' +
'render(dropdown);',
# -- output --
'var content = (\n' +
' \n' +
' {/* child comment, put {} around */}\n' +
' \n' +
' \n' +
');\n' +
'var qwer = A dropdown list Do Something Do Something Fun! Do Something Else ;\n' +
'render(dropdown);')
# Handles messed up tags, as long as it isn't the same name
# as the root tag. Also handles tags of same name as root tag
# as long as nesting matches.
bt(
'xml= ;',
# -- output --
'xml = ;')
# If xml is not terminated, the remainder of the file is treated
# as part of the xml-literal (passed through unaltered)
test_fragment(
'xml=\n' +
'c \n' +
'c\n' +
' c \n' +
' \n' +
' );\n' +
' }\n' +
'});')
bt(
'let a = React.createClass({\n' +
' render() {\n' +
' return (\n' +
' \n' +
' c \n' +
'
\n' +
' );\n' +
' }\n' +
'});')
bt(
'let a = React.createClass({\n' +
' render() {\n' +
' return (\n' +
' \n' +
' c \n' +
'
\n' +
' );\n' +
' }\n' +
'});')
bt(
'let a = React.createClass({\n' +
' render() {\n' +
' return (\n' +
' <{e} className = {d}>\n' +
' c \n' +
' {e}>\n' +
' );\n' +
' }\n' +
'});')
# Issue #914 - Multiline attribute in root tag
bt(
'return (\n' +
' {\n' +
' e.preventDefault()\n' +
' onClick()\n' +
' }}>\n' +
' {children}\n' +
' \n' +
');')
bt(
'return (\n' +
' <{\n' +
' a + b\n' +
' } href="#"\n' +
' onClick={e => {\n' +
' e.preventDefault()\n' +
' onClick()\n' +
' }}>\n' +
' {children}\n' +
' {\n' +
' a + b\n' +
' }>\n' +
');')
bt(
'return (\n' +
' <{\n' +
' a + b\n' +
' } href="#"\n' +
' onClick={e => {\n' +
' e.preventDefault()\n' +
' onClick()\n' +
' }}>\n' +
' {children}\n' +
' {a + b}>\n' +
' );',
# -- output --
'return (\n' +
' <{\n' +
' a + b\n' +
' } href="#"\n' +
' onClick={e => {\n' +
' e.preventDefault()\n' +
' onClick()\n' +
' }}>\n' +
' {children}\n' +
' {a + b}>\n' +
');')
bt(
'class Columns extends React.Component {\n' +
' render() {\n' +
' return (\n' +
' <>\n' +
' Hello \n' +
' World \n' +
' >\n' +
' );\n' +
' }\n' +
'}')
#============================================================
#
self.reset_options()
#============================================================
# e4x disabled
self.reset_options()
self.options.e4x = false
bt(
'xml=\n' +
' foo x ;',
# -- output --
'xml = < a b = "c" > < d / > < e >\n' +
' foo < /e>x ;')
#============================================================
# Multiple braces
self.reset_options()
bt(
'{{}/z/}',
# -- output --
'{\n' +
' {}\n' +
' /z/\n' +
'}')
#============================================================
# Space before conditional - (space_before_conditional = "false")
self.reset_options()
self.options.space_before_conditional = false
bt('if(a) b()')
bt('while(a) b()')
bt(
'do\n' +
' c();\n' +
'while(a) b()')
bt('switch(a) b()')
bt(
'if(a)\n' +
'b();',
# -- output --
'if(a)\n' +
' b();')
bt(
'while(a)\n' +
'b();',
# -- output --
'while(a)\n' +
' b();')
bt(
'do\n' +
'c();\n' +
'while(a);',
# -- output --
'do\n' +
' c();\n' +
'while(a);')
bt(
'switch(a)\n' +
'b()',
# -- output --
'switch(a)\n' +
' b()')
bt('return [];')
bt('return ();')
# Space before conditional - (space_before_conditional = "true")
self.reset_options()
self.options.space_before_conditional = true
bt('if (a) b()')
bt('while (a) b()')
bt(
'do\n' +
' c();\n' +
'while (a) b()')
bt('switch (a) b()')
bt(
'if(a)\n' +
'b();',
# -- output --
'if (a)\n' +
' b();')
bt(
'while(a)\n' +
'b();',
# -- output --
'while (a)\n' +
' b();')
bt(
'do\n' +
'c();\n' +
'while(a);',
# -- output --
'do\n' +
' c();\n' +
'while (a);')
bt(
'switch(a)\n' +
'b()',
# -- output --
'switch (a)\n' +
' b()')
bt('return [];')
bt('return ();')
#============================================================
# Beautify preserve formatting
self.reset_options()
bt(
'/* beautify preserve:start */\n' +
'/* beautify preserve:end */')
bt(
'/* beautify preserve:start */\n' +
' var a = 1;\n' +
'/* beautify preserve:end */')
bt(
'var a = 1;\n' +
'/* beautify preserve:start */\n' +
' var a = 1;\n' +
'/* beautify preserve:end */')
bt('/* beautify preserve:start */ {asdklgh;y;;{}dd2d}/* beautify preserve:end */')
bt(
'var a = 1;\n' +
'/* beautify preserve:start */\n' +
' var a = 1;\n' +
'/* beautify preserve:end */',
# -- output --
'var a = 1;\n' +
'/* beautify preserve:start */\n' +
' var a = 1;\n' +
'/* beautify preserve:end */')
bt(
'var a = 1;\n' +
' /* beautify preserve:start */\n' +
' var a = 1;\n' +
'/* beautify preserve:end */',
# -- output --
'var a = 1;\n' +
'/* beautify preserve:start */\n' +
' var a = 1;\n' +
'/* beautify preserve:end */')
bt(
'var a = {\n' +
' /* beautify preserve:start */\n' +
' one : 1\n' +
' two : 2,\n' +
' three : 3,\n' +
' ten : 10\n' +
' /* beautify preserve:end */\n' +
'};')
bt(
'var a = {\n' +
'/* beautify preserve:start */\n' +
' one : 1,\n' +
' two : 2,\n' +
' three : 3,\n' +
' ten : 10\n' +
'/* beautify preserve:end */\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify preserve:start */\n' +
' one : 1,\n' +
' two : 2,\n' +
' three : 3,\n' +
' ten : 10\n' +
'/* beautify preserve:end */\n' +
'};')
# one space before and after required, only single spaces inside.
bt(
'var a = {\n' +
'/* beautify preserve:start */\n' +
' one : 1,\n' +
' two : 2,\n' +
' three : 3,\n' +
' ten : 10\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify preserve:start */\n' +
' one: 1,\n' +
' two: 2,\n' +
' three: 3,\n' +
' ten: 10\n' +
'};')
bt(
'var a = {\n' +
'/*beautify preserve:start*/\n' +
' one : 1,\n' +
' two : 2,\n' +
' three : 3,\n' +
' ten : 10\n' +
'};',
# -- output --
'var a = {\n' +
' /*beautify preserve:start*/\n' +
' one: 1,\n' +
' two: 2,\n' +
' three: 3,\n' +
' ten: 10\n' +
'};')
bt(
'var a = {\n' +
'/*beautify preserve:start*/\n' +
' one : 1,\n' +
' two : 2,\n' +
' three : 3,\n' +
' ten : 10\n' +
'};',
# -- output --
'var a = {\n' +
' /*beautify preserve:start*/\n' +
' one: 1,\n' +
' two: 2,\n' +
' three: 3,\n' +
' ten: 10\n' +
'};')
# Directive: ignore
bt(
'/* beautify ignore:start */\n' +
'/* beautify ignore:end */')
bt(
'/* beautify ignore:start */\n' +
' var a,,,{ 1;\n' +
' /* beautify ignore:end */')
bt(
'var a = 1;\n' +
'/* beautify ignore:start */\n' +
' var a = 1;\n' +
'/* beautify ignore:end */')
# ignore starts _after_ the start comment, ends after the end comment
bt('/* beautify ignore:start */ {asdklgh;y;+++;dd2d}/* beautify ignore:end */')
bt('/* beautify ignore:start */ {asdklgh;y;+++;dd2d} /* beautify ignore:end */')
bt(
'var a = 1;\n' +
'/* beautify ignore:start */\n' +
' var a,,,{ 1;\n' +
'/*beautify ignore:end*/',
# -- output --
'var a = 1;\n' +
'/* beautify ignore:start */\n' +
' var a,,,{ 1;\n' +
'/*beautify ignore:end*/')
bt(
'var a = 1;\n' +
' /* beautify ignore:start */\n' +
' var a,,,{ 1;\n' +
'/* beautify ignore:end */',
# -- output --
'var a = 1;\n' +
'/* beautify ignore:start */\n' +
' var a,,,{ 1;\n' +
'/* beautify ignore:end */')
bt(
'var a = {\n' +
' /* beautify ignore:start */\n' +
' one : 1\n' +
' two : 2,\n' +
' three : {\n' +
' ten : 10\n' +
' /* beautify ignore:end */\n' +
'};')
bt(
'var a = {\n' +
'/* beautify ignore:start */\n' +
' one : 1\n' +
' two : 2,\n' +
' three : {\n' +
' ten : 10\n' +
'/* beautify ignore:end */\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify ignore:start */\n' +
' one : 1\n' +
' two : 2,\n' +
' three : {\n' +
' ten : 10\n' +
'/* beautify ignore:end */\n' +
'};')
# Directives - multiple and interacting
bt(
'var a = {\n' +
'/* beautify preserve:start */\n' +
'/* beautify preserve:start */\n' +
' one : 1,\n' +
' /* beautify preserve:end */\n' +
' two : 2,\n' +
' three : 3,\n' +
'/* beautify preserve:start */\n' +
' ten : 10\n' +
'/* beautify preserve:end */\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify preserve:start */\n' +
'/* beautify preserve:start */\n' +
' one : 1,\n' +
' /* beautify preserve:end */\n' +
' two: 2,\n' +
' three: 3,\n' +
' /* beautify preserve:start */\n' +
' ten : 10\n' +
'/* beautify preserve:end */\n' +
'};')
bt(
'var a = {\n' +
'/* beautify ignore:start */\n' +
' one : 1\n' +
' /* beautify ignore:end */\n' +
' two : 2,\n' +
'/* beautify ignore:start */\n' +
' three : {\n' +
' ten : 10\n' +
'/* beautify ignore:end */\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify ignore:start */\n' +
' one : 1\n' +
' /* beautify ignore:end */\n' +
' two: 2,\n' +
' /* beautify ignore:start */\n' +
' three : {\n' +
' ten : 10\n' +
'/* beautify ignore:end */\n' +
'};')
# Starts can occur together, ignore:end must occur alone.
bt(
'var a = {\n' +
'/* beautify ignore:start */\n' +
' one : 1\n' +
' NOTE: ignore end block does not support starting other directives\n' +
' This does not match the ending the ignore...\n' +
' /* beautify ignore:end preserve:start */\n' +
' two : 2,\n' +
'/* beautify ignore:start */\n' +
' three : {\n' +
' ten : 10\n' +
' ==The next comment ends the starting ignore==\n' +
'/* beautify ignore:end */\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify ignore:start */\n' +
' one : 1\n' +
' NOTE: ignore end block does not support starting other directives\n' +
' This does not match the ending the ignore...\n' +
' /* beautify ignore:end preserve:start */\n' +
' two : 2,\n' +
'/* beautify ignore:start */\n' +
' three : {\n' +
' ten : 10\n' +
' ==The next comment ends the starting ignore==\n' +
'/* beautify ignore:end */\n' +
'};')
bt(
'var a = {\n' +
'/* beautify ignore:start preserve:start */\n' +
' one : {\n' +
' /* beautify ignore:end */\n' +
' two : 2,\n' +
' /* beautify ignore:start */\n' +
' three : {\n' +
'/* beautify ignore:end */\n' +
' ten : 10\n' +
' // This is all preserved\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify ignore:start preserve:start */\n' +
' one : {\n' +
' /* beautify ignore:end */\n' +
' two : 2,\n' +
' /* beautify ignore:start */\n' +
' three : {\n' +
'/* beautify ignore:end */\n' +
' ten : 10\n' +
' // This is all preserved\n' +
'};')
bt(
'var a = {\n' +
'/* beautify ignore:start preserve:start */\n' +
' one : {\n' +
' /* beautify ignore:end */\n' +
' two : 2,\n' +
' /* beautify ignore:start */\n' +
' three : {\n' +
'/* beautify ignore:end */\n' +
' ten : 10,\n' +
'/* beautify preserve:end */\n' +
' eleven: 11\n' +
'};',
# -- output --
'var a = {\n' +
' /* beautify ignore:start preserve:start */\n' +
' one : {\n' +
' /* beautify ignore:end */\n' +
' two : 2,\n' +
' /* beautify ignore:start */\n' +
' three : {\n' +
'/* beautify ignore:end */\n' +
' ten : 10,\n' +
'/* beautify preserve:end */\n' +
' eleven: 11\n' +
'};')
#============================================================
# Comments and tests
self.reset_options()
# #913
bt(
'class test {\n' +
' method1() {\n' +
' let resp = null;\n' +
' }\n' +
' /**\n' +
' * @param {String} id\n' +
' */\n' +
' method2(id) {\n' +
' let resp2 = null;\n' +
' }\n' +
'}')
# #1090
bt(
'for (var i = 0; i < 20; ++i) // loop\n' +
' if (i % 3) {\n' +
' console.log(i);\n' +
' }\n' +
'console.log("done");')
# #1043
bt(
'var o = {\n' +
' k: 0\n' +
'}\n' +
'// ...\n' +
'foo(o)')
# #713 and #964
bt(
'Meteor.call("foo", bar, function(err, result) {\n' +
' Session.set("baz", result.lorem)\n' +
'})\n' +
'//blah blah')
# #815
bt(
'foo()\n' +
'// this is a comment\n' +
'bar()\n' +
'\n' +
'const foo = 5\n' +
'// comment\n' +
'bar()')
# This shows current behavior. Note #1069 is not addressed yet.
bt(
'if (modulus === 2) {\n' +
' // i might be odd here\n' +
' i += (i & 1);\n' +
' // now i is guaranteed to be even\n' +
' // this block is obviously about the statement above\n' +
'\n' +
' // #1069 This should attach to the block below\n' +
' // this comment is about the block after it.\n' +
'} else {\n' +
' // rounding up using integer arithmetic only\n' +
' if (i % modulus)\n' +
' i += modulus - (i % modulus);\n' +
' // now i is divisible by modulus\n' +
' // behavior of comments should be different for single statements vs block statements/expressions\n' +
'}\n' +
'\n' +
'if (modulus === 2)\n' +
' // i might be odd here\n' +
' i += (i & 1);\n' +
'// now i is guaranteed to be even\n' +
'// non-braced comments unindent immediately\n' +
'\n' +
'// this comment is about the block after it.\n' +
'else\n' +
' // rounding up using integer arithmetic only\n' +
' if (i % modulus)\n' +
' i += modulus - (i % modulus);\n' +
'// behavior of comments should be different for single statements vs block statements/expressions')
#============================================================
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = ;', 'var a = ;')
bt(
'a = abc");\n' +
'}\n' +
'?>;')
test_fragment(
'\n' +
'test.method();')
bt(
'abc;\n' +
'.test();\n' +
'" "')
bt(
';\n' +
'test.method();')
bt('"";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = =$view["name"]; ?>;', 'var a = =$view["name"]; ?>;')
bt(
'a = abc=\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'?>;')
test_fragment(
'= ?>\n' +
'test.met= someValue ?>hod();')
bt(
'= "A" ?>abc= "D" ?>;\n' +
'= "B" ?>.test();\n' +
'" = "C" \'D\' ?> "')
bt(
'=\n' +
'echo "A";\n' +
'?>;\n' +
'test.method();')
bt('"=";if(0){}"?>";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = <%$view["name"]; %>;', 'var a = <%$view["name"]; %>;')
bt(
'a = abc<%\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'%>;')
test_fragment(
'<% %>\n' +
'test.met<% someValue %>hod();')
bt(
'<% "A" %>abc<% "D" %>;\n' +
'<% "B" %>.test();\n' +
'" <% "C" \'D\' %> "')
bt(
'<%\n' +
'echo "A";\n' +
'%>;\n' +
'test.method();')
bt('"<%";if(0){}"%>";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = <%=$view["name"]; %>;', 'var a = <%=$view["name"]; %>;')
bt(
'a = abc<%=\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'%>;')
test_fragment(
'<%= %>\n' +
'test.met<%= someValue %>hod();')
bt(
'<%= "A" %>abc<%= "D" %>;\n' +
'<%= "B" %>.test();\n' +
'" <%= "C" \'D\' %> "')
bt(
'<%=\n' +
'echo "A";\n' +
'%>;\n' +
'test.method();')
bt('"<%=";if(0){}"%>";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{$view["name"]; }};', 'var a = {{$view["name"]; }};')
bt(
'a = abc{{\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'}};')
test_fragment(
'{{ }}\n' +
'test.met{{ someValue }}hod();')
bt(
'{{ "A" }}abc{{ "D" }};\n' +
'{{ "B" }}.test();\n' +
'" {{ "C" \'D\' }} "')
bt(
'{{\n' +
'echo "A";\n' +
'}};\n' +
'test.method();')
bt('"{{";if(0){}"}}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {#$view["name"]; #};', 'var a = {#$view["name"]; #};')
bt(
'a = abc{#\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'#};')
test_fragment(
'{# #}\n' +
'test.met{# someValue #}hod();')
bt(
'{# "A" #}abc{# "D" #};\n' +
'{# "B" #}.test();\n' +
'" {# "C" \'D\' #} "')
bt(
'{#\n' +
'echo "A";\n' +
'#};\n' +
'test.method();')
bt('"{#";if(0){}"#}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {%$view["name"]; %};', 'var a = {%$view["name"]; %};')
bt(
'a = abc{%\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'%};')
test_fragment(
'{% %}\n' +
'test.met{% someValue %}hod();')
bt(
'{% "A" %}abc{% "D" %};\n' +
'{% "B" %}.test();\n' +
'" {% "C" \'D\' %} "')
bt(
'{%\n' +
'echo "A";\n' +
'%};\n' +
'test.method();')
bt('"{%";if(0){}"%}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{$view["name"]; }};', 'var a = {{$view["name"]; }};')
bt(
'a = abc{{\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'}};')
test_fragment(
'{{ }}\n' +
'test.met{{ someValue }}hod();')
bt(
'{{ "A" }}abc{{ "D" }};\n' +
'{{ "B" }}.test();\n' +
'" {{ "C" \'D\' }} "')
bt(
'{{\n' +
'echo "A";\n' +
'}};\n' +
'test.method();')
bt('"{{";if(0){}"}}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{{$view["name"]; }}};', 'var a = {{{$view["name"]; }}};')
bt(
'a = abc{{{\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'}}};')
test_fragment(
'{{{ }}}\n' +
'test.met{{{ someValue }}}hod();')
bt(
'{{{ "A" }}}abc{{{ "D" }}};\n' +
'{{{ "B" }}}.test();\n' +
'" {{{ "C" \'D\' }}} "')
bt(
'{{{\n' +
'echo "A";\n' +
'}}};\n' +
'test.method();')
bt('"{{{";if(0){}"}}}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{^$view["name"]; }};', 'var a = {{^$view["name"]; }};')
bt(
'a = abc{{^\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'}};')
test_fragment(
'{{^ }}\n' +
'test.met{{^ someValue }}hod();')
bt(
'{{^ "A" }}abc{{^ "D" }};\n' +
'{{^ "B" }}.test();\n' +
'" {{^ "C" \'D\' }} "')
bt(
'{{^\n' +
'echo "A";\n' +
'}};\n' +
'test.method();')
bt('"{{^";if(0){}"}}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{#$view["name"]; }};', 'var a = {{#$view["name"]; }};')
bt(
'a = abc{{#\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'}};')
test_fragment(
'{{# }}\n' +
'test.met{{# someValue }}hod();')
bt(
'{{# "A" }}abc{{# "D" }};\n' +
'{{# "B" }}.test();\n' +
'" {{# "C" \'D\' }} "')
bt(
'{{#\n' +
'echo "A";\n' +
'}};\n' +
'test.method();')
bt('"{{#";if(0){}"}}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{!$view["name"]; }};', 'var a = {{!$view["name"]; }};')
bt(
'a = abc{{!\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'}};')
test_fragment(
'{{! }}\n' +
'test.met{{! someValue }}hod();')
bt(
'{{! "A" }}abc{{! "D" }};\n' +
'{{! "B" }}.test();\n' +
'" {{! "C" \'D\' }} "')
bt(
'{{!\n' +
'echo "A";\n' +
'}};\n' +
'test.method();')
bt('"{{!";if(0){}"}}";')
# minimal template handling - ()
self.reset_options()
self.options.templating = ['django', 'erb', 'handlebars', 'php']
bt('var a = {{!--$view["name"]; --}};', 'var a = {{!--$view["name"]; --}};')
bt(
'a = abc{{!--\n' +
'for($i = 1; $i <= 100; $i++;) {\n' +
' #count to 100!\n' +
' echo($i . "");\n' +
'}\n' +
'--}};')
test_fragment(
'{{!-- --}}\n' +
'test.met{{!-- someValue --}}hod();')
bt(
'{{!-- "A" --}}abc{{!-- "D" --}};\n' +
'{{!-- "B" --}}.test();\n' +
'" {{!-- "C" \'D\' --}} "')
bt(
'{{!--\n' +
'echo "A";\n' +
'--}};\n' +
'test.method();')
bt('"{{!--";if(0){}"--}}";')
#============================================================
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"";',
# -- output --
'"";')
bt(
'"";',
# -- output --
'"=";\n' +
'if (0) {}\n' +
'"?>";')
bt(
'"=";if(0){}',
# -- output --
'"=";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"<%";if(0){}"%>";',
# -- output --
'"<%";\n' +
'if (0) {}\n' +
'"%>";')
bt(
'"<%";if(0){}',
# -- output --
'"<%";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"<%=";if(0){}"%>";',
# -- output --
'"<%=";\n' +
'if (0) {}\n' +
'"%>";')
bt(
'"<%=";if(0){}',
# -- output --
'"<%=";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{";if(0){}"}}";',
# -- output --
'"{{";\n' +
'if (0) {}\n' +
'"}}";')
bt(
'"{{";if(0){}',
# -- output --
'"{{";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{#";if(0){}"#}";',
# -- output --
'"{#";\n' +
'if (0) {}\n' +
'"#}";')
bt(
'"{#";if(0){}',
# -- output --
'"{#";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{%";if(0){}"%}";',
# -- output --
'"{%";\n' +
'if (0) {}\n' +
'"%}";')
bt(
'"{%";if(0){}',
# -- output --
'"{%";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{";if(0){}"}}";',
# -- output --
'"{{";\n' +
'if (0) {}\n' +
'"}}";')
bt(
'"{{";if(0){}',
# -- output --
'"{{";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{{";if(0){}"}}}";',
# -- output --
'"{{{";\n' +
'if (0) {}\n' +
'"}}}";')
bt(
'"{{{";if(0){}',
# -- output --
'"{{{";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{^";if(0){}"}}";',
# -- output --
'"{{^";\n' +
'if (0) {}\n' +
'"}}";')
bt(
'"{{^";if(0){}',
# -- output --
'"{{^";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{#";if(0){}"}}";',
# -- output --
'"{{#";\n' +
'if (0) {}\n' +
'"}}";')
bt(
'"{{#";if(0){}',
# -- output --
'"{{#";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{!";if(0){}"}}";',
# -- output --
'"{{!";\n' +
'if (0) {}\n' +
'"}}";')
bt(
'"{{!";if(0){}',
# -- output --
'"{{!";\n' +
'if (0) {}')
# Templating disabled - ensure formatting - ()
self.reset_options()
self.options.templating = ['auto']
bt(
'"{{!--";if(0){}"--}}";',
# -- output --
'"{{!--";\n' +
'if (0) {}\n' +
'"--}}";')
bt(
'"{{!--";if(0){}',
# -- output --
'"{{!--";\n' +
'if (0) {}')
#============================================================
# jslint and space after anon function - (jslint_happy = "true", space_after_anon_function = "true")
self.reset_options()
self.options.jslint_happy = true
self.options.space_after_anon_function = true
bt(
'a=typeof(x)',
# -- output --
'a = typeof (x)')
bt(
'x();\n' +
'\n' +
'function(){}',
# -- output --
'x();\n' +
'\n' +
'function () {}')
bt(
'x();\n' +
'\n' +
'function y(){}',
# -- output --
'x();\n' +
'\n' +
'function y() {}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function () {}\n' +
'}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function y(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function y() {}\n' +
'}')
bt(
'function () {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}')
bt(
'switch(x) {case 0: case 1: a(); break; default: break}',
# -- output --
'switch (x) {\n' +
'case 0:\n' +
'case 1:\n' +
' a();\n' +
' break;\n' +
'default:\n' +
' break\n' +
'}')
bt(
'switch(x){case -1:break;case !y:break;}',
# -- output --
'switch (x) {\n' +
'case -1:\n' +
' break;\n' +
'case !y:\n' +
' break;\n' +
'}')
# Issue #1357
bt(
'switch(x) {case 0: case 1:{a(); break;} default: break}',
# -- output --
'switch (x) {\n' +
'case 0:\n' +
'case 1: {\n' +
' a();\n' +
' break;\n' +
'}\n' +
'default:\n' +
' break\n' +
'}')
# Issue #1357
bt(
'switch(x){case -1:break;case !y:{break;}}',
# -- output --
'switch (x) {\n' +
'case -1:\n' +
' break;\n' +
'case !y: {\n' +
' break;\n' +
'}\n' +
'}')
# Issue #1622 - basic class with function definitions
bt(
'class blah {\n' +
' constructor() {\n' +
' this.doStuff()\n' +
' }\n' +
' doStuff() {\n' +
' console.log("stuff")\n' +
' }\n' +
'}')
# Issue #1622 - class with extends and function definitions
bt(
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
'this.y = 1;\n' +
' }\n' +
'}',
# -- output --
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
' this.y = 1;\n' +
' }\n' +
'}')
# Issue #1622 - class/extends as a property
bt(
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})',
# -- output --
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})')
# typical greasemonkey start
test_fragment(
'// comment 2\n' +
'(function ()')
bt(
'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function () {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function yoohoo() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function yoohoo() {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function() {},\n' +
'd = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function () {},\n' +
' d = \'\';')
bt(
'var o2=$.extend(a);function(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function () {\n' +
' alert(x);\n' +
'}')
bt(
'var o2=$.extend(a);function yoohoo(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function yoohoo() {\n' +
' alert(x);\n' +
'}')
bt(
'function*() {\n' +
' yield 1;\n' +
'}',
# -- output --
'function* () {\n' +
' yield 1;\n' +
'}')
bt(
'function* yoohoo() {\n' +
' yield 1;\n' +
'}')
bt(
'function* x() {\n' +
' yield 1;\n' +
'}')
bt(
'async x() {\n' +
' yield 1;\n' +
'}')
bt(
'var a={data(){},\n' +
'data2(){}}',
# -- output --
'var a = {\n' +
' data() {},\n' +
' data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'data(){},\n' +
'data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {data(){},\n' +
'data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'}')
bt(
'var a={*data(){},*data2(){}}',
# -- output --
'var a = {\n' +
' * data() {},\n' +
' * data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'*data(){},*data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {*data(){},*data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'}')
# jslint and space after anon function - (jslint_happy = "true", space_after_anon_function = "false")
self.reset_options()
self.options.jslint_happy = true
self.options.space_after_anon_function = false
bt(
'a=typeof(x)',
# -- output --
'a = typeof (x)')
bt(
'x();\n' +
'\n' +
'function(){}',
# -- output --
'x();\n' +
'\n' +
'function () {}')
bt(
'x();\n' +
'\n' +
'function y(){}',
# -- output --
'x();\n' +
'\n' +
'function y() {}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function () {}\n' +
'}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function y(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function y() {}\n' +
'}')
bt(
'function () {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}')
bt(
'switch(x) {case 0: case 1: a(); break; default: break}',
# -- output --
'switch (x) {\n' +
'case 0:\n' +
'case 1:\n' +
' a();\n' +
' break;\n' +
'default:\n' +
' break\n' +
'}')
bt(
'switch(x){case -1:break;case !y:break;}',
# -- output --
'switch (x) {\n' +
'case -1:\n' +
' break;\n' +
'case !y:\n' +
' break;\n' +
'}')
# Issue #1357
bt(
'switch(x) {case 0: case 1:{a(); break;} default: break}',
# -- output --
'switch (x) {\n' +
'case 0:\n' +
'case 1: {\n' +
' a();\n' +
' break;\n' +
'}\n' +
'default:\n' +
' break\n' +
'}')
# Issue #1357
bt(
'switch(x){case -1:break;case !y:{break;}}',
# -- output --
'switch (x) {\n' +
'case -1:\n' +
' break;\n' +
'case !y: {\n' +
' break;\n' +
'}\n' +
'}')
# Issue #1622 - basic class with function definitions
bt(
'class blah {\n' +
' constructor() {\n' +
' this.doStuff()\n' +
' }\n' +
' doStuff() {\n' +
' console.log("stuff")\n' +
' }\n' +
'}')
# Issue #1622 - class with extends and function definitions
bt(
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
'this.y = 1;\n' +
' }\n' +
'}',
# -- output --
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
' this.y = 1;\n' +
' }\n' +
'}')
# Issue #1622 - class/extends as a property
bt(
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})',
# -- output --
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})')
# typical greasemonkey start
test_fragment(
'// comment 2\n' +
'(function ()')
bt(
'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function () {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function yoohoo() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function yoohoo() {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function() {},\n' +
'd = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function () {},\n' +
' d = \'\';')
bt(
'var o2=$.extend(a);function(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function () {\n' +
' alert(x);\n' +
'}')
bt(
'var o2=$.extend(a);function yoohoo(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function yoohoo() {\n' +
' alert(x);\n' +
'}')
bt(
'function*() {\n' +
' yield 1;\n' +
'}',
# -- output --
'function* () {\n' +
' yield 1;\n' +
'}')
bt(
'function* yoohoo() {\n' +
' yield 1;\n' +
'}')
bt(
'function* x() {\n' +
' yield 1;\n' +
'}')
bt(
'async x() {\n' +
' yield 1;\n' +
'}')
bt(
'var a={data(){},\n' +
'data2(){}}',
# -- output --
'var a = {\n' +
' data() {},\n' +
' data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'data(){},\n' +
'data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {data(){},\n' +
'data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'}')
bt(
'var a={*data(){},*data2(){}}',
# -- output --
'var a = {\n' +
' * data() {},\n' +
' * data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'*data(){},*data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {*data(){},*data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'}')
# jslint and space after anon function - (jslint_happy = "false", space_after_anon_function = "true")
self.reset_options()
self.options.jslint_happy = false
self.options.space_after_anon_function = true
bt(
'a=typeof(x)',
# -- output --
'a = typeof (x)')
bt(
'x();\n' +
'\n' +
'function(){}',
# -- output --
'x();\n' +
'\n' +
'function () {}')
bt(
'x();\n' +
'\n' +
'function y(){}',
# -- output --
'x();\n' +
'\n' +
'function y() {}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function () {}\n' +
'}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function y(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function y() {}\n' +
'}')
bt(
'function () {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}')
bt(
'switch(x) {case 0: case 1: a(); break; default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1:\n' +
' a();\n' +
' break;\n' +
' default:\n' +
' break\n' +
'}')
bt(
'switch(x){case -1:break;case !y:break;}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y:\n' +
' break;\n' +
'}')
# Issue #1357
bt(
'switch(x) {case 0: case 1:{a(); break;} default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1: {\n' +
' a();\n' +
' break;\n' +
' }\n' +
' default:\n' +
' break\n' +
'}')
# Issue #1357
bt(
'switch(x){case -1:break;case !y:{break;}}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y: {\n' +
' break;\n' +
' }\n' +
'}')
# Issue #1622 - basic class with function definitions
bt(
'class blah {\n' +
' constructor() {\n' +
' this.doStuff()\n' +
' }\n' +
' doStuff() {\n' +
' console.log("stuff")\n' +
' }\n' +
'}')
# Issue #1622 - class with extends and function definitions
bt(
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
'this.y = 1;\n' +
' }\n' +
'}',
# -- output --
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
' this.y = 1;\n' +
' }\n' +
'}')
# Issue #1622 - class/extends as a property
bt(
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})',
# -- output --
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})')
# typical greasemonkey start
test_fragment(
'// comment 2\n' +
'(function ()')
bt(
'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function () {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function yoohoo() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function yoohoo() {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function() {},\n' +
'd = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function () {},\n' +
' d = \'\';')
bt(
'var o2=$.extend(a);function(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function () {\n' +
' alert(x);\n' +
'}')
bt(
'var o2=$.extend(a);function yoohoo(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function yoohoo() {\n' +
' alert(x);\n' +
'}')
bt(
'function*() {\n' +
' yield 1;\n' +
'}',
# -- output --
'function* () {\n' +
' yield 1;\n' +
'}')
bt(
'function* yoohoo() {\n' +
' yield 1;\n' +
'}')
bt(
'function* x() {\n' +
' yield 1;\n' +
'}')
bt(
'async x() {\n' +
' yield 1;\n' +
'}')
bt(
'var a={data(){},\n' +
'data2(){}}',
# -- output --
'var a = {\n' +
' data() {},\n' +
' data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'data(){},\n' +
'data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {data(){},\n' +
'data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'}')
bt(
'var a={*data(){},*data2(){}}',
# -- output --
'var a = {\n' +
' * data() {},\n' +
' * data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'*data(){},*data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {*data(){},*data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'}')
# jslint and space after anon function - (jslint_happy = "false", space_after_anon_function = "false")
self.reset_options()
self.options.jslint_happy = false
self.options.space_after_anon_function = false
bt(
'a=typeof(x)',
# -- output --
'a = typeof(x)')
bt(
'x();\n' +
'\n' +
'function(){}',
# -- output --
'x();\n' +
'\n' +
'function() {}')
bt(
'x();\n' +
'\n' +
'function y(){}',
# -- output --
'x();\n' +
'\n' +
'function y() {}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function() {}\n' +
'}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function y(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function y() {}\n' +
'}')
bt(
'function () {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}',
# -- output --
'function() {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}')
bt(
'switch(x) {case 0: case 1: a(); break; default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1:\n' +
' a();\n' +
' break;\n' +
' default:\n' +
' break\n' +
'}')
bt(
'switch(x){case -1:break;case !y:break;}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y:\n' +
' break;\n' +
'}')
# Issue #1357
bt(
'switch(x) {case 0: case 1:{a(); break;} default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1: {\n' +
' a();\n' +
' break;\n' +
' }\n' +
' default:\n' +
' break\n' +
'}')
# Issue #1357
bt(
'switch(x){case -1:break;case !y:{break;}}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y: {\n' +
' break;\n' +
' }\n' +
'}')
# Issue #1622 - basic class with function definitions
bt(
'class blah {\n' +
' constructor() {\n' +
' this.doStuff()\n' +
' }\n' +
' doStuff() {\n' +
' console.log("stuff")\n' +
' }\n' +
'}')
# Issue #1622 - class with extends and function definitions
bt(
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
'this.y = 1;\n' +
' }\n' +
'}',
# -- output --
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
' this.y = 1;\n' +
' }\n' +
'}')
# Issue #1622 - class/extends as a property
bt(
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})',
# -- output --
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})')
# typical greasemonkey start
test_fragment(
'// comment 2\n' +
'(function()')
bt(
'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function() {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function yoohoo() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function yoohoo() {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function() {},\n' +
'd = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function() {},\n' +
' d = \'\';')
bt(
'var o2=$.extend(a);function(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function() {\n' +
' alert(x);\n' +
'}')
bt(
'var o2=$.extend(a);function yoohoo(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function yoohoo() {\n' +
' alert(x);\n' +
'}')
bt(
'function*() {\n' +
' yield 1;\n' +
'}')
bt(
'function* yoohoo() {\n' +
' yield 1;\n' +
'}')
bt(
'function* x() {\n' +
' yield 1;\n' +
'}')
bt(
'async x() {\n' +
' yield 1;\n' +
'}')
bt(
'var a={data(){},\n' +
'data2(){}}',
# -- output --
'var a = {\n' +
' data() {},\n' +
' data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'data(){},\n' +
'data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {data(){},\n' +
'data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' data() {},\n' +
' data2() {},\n' +
' a: 1\n' +
'}')
bt(
'var a={*data(){},*data2(){}}',
# -- output --
'var a = {\n' +
' * data() {},\n' +
' * data2() {}\n' +
'}')
bt(
'new Vue({\n' +
'*data(){},*data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'})')
bt(
'export default {*data(){},*data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' * data() {},\n' +
' * data2() {},\n' +
' a: 1\n' +
'}')
# jslint and space after anon function - (space_after_named_function = "true")
self.reset_options()
self.options.space_after_named_function = true
bt(
'a=typeof(x)',
# -- output --
'a = typeof(x)')
bt(
'x();\n' +
'\n' +
'function(){}',
# -- output --
'x();\n' +
'\n' +
'function() {}')
bt(
'x();\n' +
'\n' +
'function y(){}',
# -- output --
'x();\n' +
'\n' +
'function y () {}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function() {}\n' +
'}')
bt(
'x();\n' +
'\n' +
'var x = {\n' +
'x: function y(){}\n' +
'}',
# -- output --
'x();\n' +
'\n' +
'var x = {\n' +
' x: function y () {}\n' +
'}')
bt(
'function () {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}',
# -- output --
'function() {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}')
bt(
'switch(x) {case 0: case 1: a(); break; default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1:\n' +
' a();\n' +
' break;\n' +
' default:\n' +
' break\n' +
'}')
bt(
'switch(x){case -1:break;case !y:break;}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y:\n' +
' break;\n' +
'}')
# Issue #1357
bt(
'switch(x) {case 0: case 1:{a(); break;} default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1: {\n' +
' a();\n' +
' break;\n' +
' }\n' +
' default:\n' +
' break\n' +
'}')
# Issue #1357
bt(
'switch(x){case -1:break;case !y:{break;}}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y: {\n' +
' break;\n' +
' }\n' +
'}')
# Issue #1622 - basic class with function definitions
bt(
'class blah {\n' +
' constructor() {\n' +
' this.doStuff()\n' +
' }\n' +
' doStuff() {\n' +
' console.log("stuff")\n' +
' }\n' +
'}',
# -- output --
'class blah {\n' +
' constructor () {\n' +
' this.doStuff()\n' +
' }\n' +
' doStuff () {\n' +
' console.log("stuff")\n' +
' }\n' +
'}')
# Issue #1622 - class with extends and function definitions
bt(
'class blah extends something {\n' +
' constructor() {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction() {\n' +
'this.y = 1;\n' +
' }\n' +
'}',
# -- output --
'class blah extends something {\n' +
' constructor () {\n' +
' this.zz = 2 + 2;\n' +
' }\n' +
' someOtherFunction () {\n' +
' this.y = 1;\n' +
' }\n' +
'}')
# Issue #1622 - class/extends as a property
bt(
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})',
# -- output --
'var a.class = {\n' +
' ...abc(),\n' +
'}\n' +
'b.extends({\n' +
' bb.s(),\n' +
'})')
# typical greasemonkey start
test_fragment(
'// comment 2\n' +
'(function()')
bt(
'var a2, b2, c2, d2 = 0, c = function() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function() {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function yoohoo() {}, d = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function yoohoo () {},\n' +
' d = \'\';')
bt(
'var a2, b2, c2, d2 = 0, c = function() {},\n' +
'd = \'\';',
# -- output --
'var a2, b2, c2, d2 = 0,\n' +
' c = function() {},\n' +
' d = \'\';')
bt(
'var o2=$.extend(a);function(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function() {\n' +
' alert(x);\n' +
'}')
bt(
'var o2=$.extend(a);function yoohoo(){alert(x);}',
# -- output --
'var o2 = $.extend(a);\n' +
'\n' +
'function yoohoo () {\n' +
' alert(x);\n' +
'}')
bt(
'function*() {\n' +
' yield 1;\n' +
'}')
bt(
'function* yoohoo() {\n' +
' yield 1;\n' +
'}',
# -- output --
'function* yoohoo () {\n' +
' yield 1;\n' +
'}')
bt(
'function* x() {\n' +
' yield 1;\n' +
'}',
# -- output --
'function* x () {\n' +
' yield 1;\n' +
'}')
bt(
'async x() {\n' +
' yield 1;\n' +
'}',
# -- output --
'async x () {\n' +
' yield 1;\n' +
'}')
bt(
'var a={data(){},\n' +
'data2(){}}',
# -- output --
'var a = {\n' +
' data () {},\n' +
' data2 () {}\n' +
'}')
bt(
'new Vue({\n' +
'data(){},\n' +
'data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' data () {},\n' +
' data2 () {},\n' +
' a: 1\n' +
'})')
bt(
'export default {data(){},\n' +
'data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' data () {},\n' +
' data2 () {},\n' +
' a: 1\n' +
'}')
bt(
'var a={*data(){},*data2(){}}',
# -- output --
'var a = {\n' +
' * data () {},\n' +
' * data2 () {}\n' +
'}')
bt(
'new Vue({\n' +
'*data(){},*data2(){}, a:1})',
# -- output --
'new Vue({\n' +
' * data () {},\n' +
' * data2 () {},\n' +
' a: 1\n' +
'})')
bt(
'export default {*data(){},*data2(){},\n' +
'a:1}',
# -- output --
'export default {\n' +
' * data () {},\n' +
' * data2 () {},\n' +
' a: 1\n' +
'}')
#============================================================
# Regression tests
self.reset_options()
# Issue 241
bt(
'obj\n' +
' .last({\n' +
' foo: 1,\n' +
' bar: 2\n' +
' });\n' +
'var test = 1;')
# Issue #1852 - semicolon followed by block statement
bt(
'(function() {\n' +
' some_code_here();\n' +
' {\n' +
' /* IE11 let bug bypass */\n' +
' let index;\n' +
' for (index in a) {\n' +
' a[index];\n' +
' }\n' +
' }\n' +
'})();')
# Issue #1852 - semicolon followed by block statement 2
bt(
'let x = { A: 1 }; { console.log("hello"); }',
# -- output --
'let x = {\n' +
' A: 1\n' +
'};\n' +
'{\n' +
' console.log("hello");\n' +
'}')
# Issue #772
bt(
'this.initAttributes([\n' +
'"name",\n' +
'["parent", null, "parentName"],\n' +
'"length",\n' +
'["id", this.name],\n' +
']);',
# -- output --
'this.initAttributes([\n' +
' "name",\n' +
' ["parent", null, "parentName"],\n' +
' "length",\n' +
' ["id", this.name],\n' +
']);')
# Issue #1663
bt(
'{\n' +
' /* howdy\n' +
' \n' +
' */\n' +
'}')
# #1095 - Return without semicolon followed by prefix on a new line
bt(
'function x(){\n' +
'return\n' +
'++a\n' +
'}\n' +
'\n' +
'while(true) {\n' +
'return\n' +
'--b\n' +
'}',
# -- output --
'function x() {\n' +
' return\n' +
' ++a\n' +
'}\n' +
'\n' +
'while (true) {\n' +
' return\n' +
' --b\n' +
'}')
# #1095
bt(
'function test(){\n' +
'if(x) return\n' +
'++x\n' +
'var y= 1;\n' +
'}\n' +
'function t1(){\n' +
'if(cc) return;\n' +
'else return\n' +
'--cc\n' +
'}',
# -- output --
'function test() {\n' +
' if (x) return\n' +
' ++x\n' +
' var y = 1;\n' +
'}\n' +
'\n' +
'function t1() {\n' +
' if (cc) return;\n' +
' else return\n' +
' --cc\n' +
'}')
# #1095 - Return with semicolon followed by a prefix on a new line
bt(
'function x(){\n' +
'return; ++a\n' +
'}\n' +
'\n' +
'while(true){return; --b\n' +
'}',
# -- output --
'function x() {\n' +
' return;\n' +
' ++a\n' +
'}\n' +
'\n' +
'while (true) {\n' +
' return;\n' +
' --b\n' +
'}')
# #1838 - handle class and interface word as an object property
bt(
'{\n' +
' class: {\n' +
' a: 1,\n' +
' b: 2,\n' +
' c: 3,\n' +
' }\n' +
' interface: {\n' +
' a: 1,\n' +
' b: 2,\n' +
' c: 3,\n' +
' }\n' +
'}')
# #1838 - handle class word as an object property but with space after colon
bt(
'{\n' +
' class : { a: 1,\n' +
'b: 2,c : 3\n' +
' }\n' +
'}',
# -- output --
'{\n' +
' class: {\n' +
' a: 1,\n' +
' b: 2,\n' +
' c: 3\n' +
' }\n' +
'}')
# #1838 - handle class word as an object property but without spaces
bt(
'{class:{a:1,b:2,c:3,}}',
# -- output --
'{\n' +
' class: {\n' +
' a: 1,\n' +
' b: 2,\n' +
' c: 3,\n' +
' }\n' +
'}')
# #1838 - handle class word as a nested object property
bt(
'{x:{a:1,class:2,c:3,}}',
# -- output --
'{\n' +
' x: {\n' +
' a: 1,\n' +
' class: 2,\n' +
' c: 3,\n' +
' }\n' +
'}')
bt(
'obj\n' +
' .last(a, function() {\n' +
' var test;\n' +
' });\n' +
'var test = 1;')
bt(
'obj.first()\n' +
' .second()\n' +
' .last(function(err, response) {\n' +
' console.log(err);\n' +
' });')
# Issue 268 and 275
bt(
'obj.last(a, function() {\n' +
' var test;\n' +
'});\n' +
'var test = 1;')
bt(
'obj.last(a,\n' +
' function() {\n' +
' var test;\n' +
' });\n' +
'var test = 1;')
bt(
'(function() {if (!window.FOO) window.FOO || (window.FOO = function() {var b = {bar: "zort"};});})();',
# -- output --
'(function() {\n' +
' if (!window.FOO) window.FOO || (window.FOO = function() {\n' +
' var b = {\n' +
' bar: "zort"\n' +
' };\n' +
' });\n' +
'})();')
# Issue 281
bt(
'define(["dojo/_base/declare", "my/Employee", "dijit/form/Button",\n' +
' "dojo/_base/lang", "dojo/Deferred"\n' +
'], function(declare, Employee, Button, lang, Deferred) {\n' +
' return declare(Employee, {\n' +
' constructor: function() {\n' +
' new Button({\n' +
' onClick: lang.hitch(this, function() {\n' +
' new Deferred().then(lang.hitch(this, function() {\n' +
' this.salary * 0.25;\n' +
' }));\n' +
' })\n' +
' });\n' +
' }\n' +
' });\n' +
'});')
bt(
'define(["dojo/_base/declare", "my/Employee", "dijit/form/Button",\n' +
' "dojo/_base/lang", "dojo/Deferred"\n' +
' ],\n' +
' function(declare, Employee, Button, lang, Deferred) {\n' +
' return declare(Employee, {\n' +
' constructor: function() {\n' +
' new Button({\n' +
' onClick: lang.hitch(this, function() {\n' +
' new Deferred().then(lang.hitch(this, function() {\n' +
' this.salary * 0.25;\n' +
' }));\n' +
' })\n' +
' });\n' +
' }\n' +
' });\n' +
' });')
# Issue 459
bt(
'(function() {\n' +
' return {\n' +
' foo: function() {\n' +
' return "bar";\n' +
' },\n' +
' bar: ["bar"]\n' +
' };\n' +
'}());')
# Issue 505 - strings should end at newline unless continued by backslash
bt(
'var name = "a;\n' +
'name = "b";')
bt(
'var name = "a;\\\n' +
' name = b";')
# Issue 514 - some operators require spaces to distinguish them
bt('var c = "_ACTION_TO_NATIVEAPI_" + ++g++ + +new Date;')
bt('var c = "_ACTION_TO_NATIVEAPI_" - --g-- - -new Date;')
# Issue 440 - reserved words can be used as object property names
bt(
'a = {\n' +
' function: {},\n' +
' "function": {},\n' +
' throw: {},\n' +
' "throw": {},\n' +
' var: {},\n' +
' "var": {},\n' +
' set: {},\n' +
' "set": {},\n' +
' get: {},\n' +
' "get": {},\n' +
' if: {},\n' +
' "if": {},\n' +
' then: {},\n' +
' "then": {},\n' +
' else: {},\n' +
' "else": {},\n' +
' yay: {}\n' +
'};')
# Issue 331 - if-else with braces edge case
bt(
'if(x){a();}else{b();}if(y){c();}',
# -- output --
'if (x) {\n' +
' a();\n' +
'} else {\n' +
' b();\n' +
'}\n' +
'if (y) {\n' +
' c();\n' +
'}')
# Issue #1683 - switch-case wrong indentation
bt(
'switch (x) { case 0: if (y == z) { a(); } else { b(); } case 1: c(); }',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' if (y == z) {\n' +
' a();\n' +
' } else {\n' +
' b();\n' +
' }\n' +
' case 1:\n' +
' c();\n' +
'}')
# Issue 485 - ensure function declarations behave the same in arrays as elsewhere
bt(
'var v = ["a",\n' +
' function() {\n' +
' return;\n' +
' }, {\n' +
' id: 1\n' +
' }\n' +
'];')
bt(
'var v = ["a", function() {\n' +
' return;\n' +
'}, {\n' +
' id: 1\n' +
'}];')
# Issue 382 - initial totally cursory support for es6 module export
bt(
'module "Even" {\n' +
' import odd from "Odd";\n' +
' export function sum(x, y) {\n' +
' return x + y;\n' +
' }\n' +
' export var pi = 3.141593;\n' +
' export default moduleName;\n' +
'}')
bt(
'module "Even" {\n' +
' export default function div(x, y) {}\n' +
'}')
# Issue 889 - export default { ... }
bt(
'export default {\n' +
' func1() {},\n' +
' func2() {}\n' +
' func3() {}\n' +
'}')
bt(
'export default {\n' +
' a() {\n' +
' return 1;\n' +
' },\n' +
' b() {\n' +
' return 2;\n' +
' },\n' +
' c() {\n' +
' return 3;\n' +
' }\n' +
'}')
# Issue 508
bt('set["name"]')
bt('get["name"]')
test_fragment(
'a = {\n' +
' set b(x) {},\n' +
' c: 1,\n' +
' d: function() {}\n' +
'};')
test_fragment(
'a = {\n' +
' get b() {\n' +
' retun 0;\n' +
' },\n' +
' c: 1,\n' +
' d: function() {}\n' +
'};')
# Issue 298 - do not under indent if/while/for condtionals experesions
bt(
'\'use strict\';\n' +
'if ([].some(function() {\n' +
' return false;\n' +
' })) {\n' +
' console.log("hello");\n' +
'}')
# Issue 298 - do not under indent if/while/for condtionals experesions
bt(
'\'use strict\';\n' +
'if ([].some(function() {\n' +
' return false;\n' +
' })) {\n' +
' console.log("hello");\n' +
'}')
# Issue 552 - Typescript? Okay... we didn't break it before, so try not to break it now.
bt(
'class Test {\n' +
' blah: string[];\n' +
' foo(): number {\n' +
' return 0;\n' +
' }\n' +
' bar(): number {\n' +
' return 0;\n' +
' }\n' +
'}')
# Issue 1544 - Typescript declare formatting (no newline).
bt(
'declare const require: any;\n' +
'declare function greet(greeting: string): void;\n' +
'declare var foo: number;\n' +
'declare namespace myLib {\n' +
' function makeGreeting(s: string): string;\n' +
' let numberOfGreetings: number;\n' +
'}\n' +
'declare let test: any;')
bt(
'interface Test {\n' +
' blah: string[];\n' +
' foo(): number {\n' +
' return 0;\n' +
' }\n' +
' bar(): number {\n' +
' return 0;\n' +
' }\n' +
'}')
# Issue 583 - Functions with comments after them should still indent correctly.
bt(
'function exit(code) {\n' +
' setTimeout(function() {\n' +
' phantom.exit(code);\n' +
' }, 0);\n' +
' phantom.onError = function() {};\n' +
'}\n' +
'// Comment')
# Issue 806 - newline arrow functions
bt(
'a.b("c",\n' +
' () => d.e\n' +
')')
# Issue 810 - es6 object literal detection
bt(
'function badFormatting() {\n' +
' return {\n' +
' a,\n' +
' b: c,\n' +
' d: e,\n' +
' f: g,\n' +
' h,\n' +
' i,\n' +
' j: k\n' +
' }\n' +
'}\n' +
'\n' +
'function goodFormatting() {\n' +
' return {\n' +
' a: b,\n' +
' c,\n' +
' d: e,\n' +
' f: g,\n' +
' h,\n' +
' i,\n' +
' j: k\n' +
' }\n' +
'}')
# Issue 602 - ES6 object literal shorthand functions
bt(
'return {\n' +
' fn1() {},\n' +
' fn2() {}\n' +
'}')
bt(
'throw {\n' +
' fn1() {},\n' +
' fn2() {}\n' +
'}')
bt(
'foo({\n' +
' fn1(a) {}\n' +
' fn2(a) {}\n' +
'})')
bt(
'foo("text", {\n' +
' fn1(a) {}\n' +
' fn2(a) {}\n' +
'})')
bt(
'oneArg = {\n' +
' fn1(a) {\n' +
' do();\n' +
' },\n' +
' fn2() {}\n' +
'}')
bt(
'multiArg = {\n' +
' fn1(a, b, c) {\n' +
' do();\n' +
' },\n' +
' fn2() {}\n' +
'}')
bt(
'noArgs = {\n' +
' fn1() {\n' +
' do();\n' +
' },\n' +
' fn2() {}\n' +
'}')
bt(
'emptyFn = {\n' +
' fn1() {},\n' +
' fn2() {}\n' +
'}')
bt(
'nested = {\n' +
' fns: {\n' +
' fn1() {},\n' +
' fn2() {}\n' +
' }\n' +
'}')
bt(
'array = [{\n' +
' fn1() {},\n' +
' prop: val,\n' +
' fn2() {}\n' +
'}]')
bt(
'expr = expr ? expr : {\n' +
' fn1() {},\n' +
' fn2() {}\n' +
'}')
bt(
'strange = valid + {\n' +
' fn1() {},\n' +
' fn2() {\n' +
' return 1;\n' +
' }\n' +
'}.fn2()')
# Issue 854 - Arrow function with statement block
bt(
'test(() => {\n' +
' var a = {}\n' +
'\n' +
' a.what = () => true ? 1 : 2\n' +
'\n' +
' a.thing = () => {\n' +
' b();\n' +
' }\n' +
'})')
# Issue 1727 - Optional chaining
bt('true?.1:.2', 'true ? .1 : .2')
# Issue 406 - Multiline array
bt(
'var tempName = [\n' +
' "temp",\n' +
' process.pid,\n' +
' (Math.random() * 0x1000000000).toString(36),\n' +
' new Date().getTime()\n' +
'].join("-");')
# Issue 1801 - Optional chaining w/ obj?.[expr] syntax
bt(
'let nestedProp = obj?.["prop" + "Name"];\n' +
'let arrayItem = arr?.[42];')
# Issue 1374 - Parameters starting with ! or [ merged into single line
bt(
'fn(\n' +
' 1,\n' +
' !1,\n' +
' 1,\n' +
' [1]\n' +
')')
# Issue 1288 - Negative numbers remove newlines in array
bt(
'var array = [\n' +
' -1,\n' +
' 0,\n' +
' "a",\n' +
' -2,\n' +
' 1,\n' +
' -3,\n' +
'];')
# Issue 1229 - Negated expressions in array
bt(
'a = [\n' +
' true && 1,\n' +
' true && 1,\n' +
' true && 1\n' +
']\n' +
'a = [\n' +
' !true && 1,\n' +
' !true && 1,\n' +
' !true && 1\n' +
']')
# Issue #996 - Input ends with backslash throws exception
test_fragment(
'sd = 1;\n' +
'/')
# Issue #1079 - unbraced if with comments should still look right
bt(
'if (console.log)\n' +
' for (var i = 0; i < 20; ++i)\n' +
' if (i % 3)\n' +
' console.log(i);\n' +
'// all done\n' +
'console.log("done");')
# Issue #1085 - function should not have blank line in a number of cases
bt(
'var transformer =\n' +
' options.transformer ||\n' +
' globalSettings.transformer ||\n' +
' function(x) {\n' +
' return x;\n' +
' };')
# Issue #1794 - support nullish-coalescing
bt('a = b ?? c')
# Issue #569 - function should not have blank line in a number of cases
bt(
'(function(global) {\n' +
' "use strict";\n' +
'\n' +
' /* jshint ignore:start */\n' +
' include "somefile.js"\n' +
' /* jshint ignore:end */\n' +
'}(this));')
bt(
'function bindAuthEvent(eventName) {\n' +
' self.auth.on(eventName, function(event, meta) {\n' +
' self.emit(eventName, event, meta);\n' +
' });\n' +
'}\n' +
'["logged_in", "logged_out", "signed_up", "updated_user"].forEach(bindAuthEvent);\n' +
'\n' +
'function bindBrowserEvent(eventName) {\n' +
' browser.on(eventName, function(event, meta) {\n' +
' self.emit(eventName, event, meta);\n' +
' });\n' +
'}\n' +
'["navigating"].forEach(bindBrowserEvent);')
# Issue #892 - new line between chained methods
bt(
'foo\n' +
' .who()\n' +
'\n' +
' .knows()\n' +
' // comment\n' +
' .nothing() // comment\n' +
'\n' +
' .more()')
# Issue #1107 - Missing space between words for label
bt(
'function f(a) {c: do if (x) {} else if (y) {} while(0); return 0;}',
# -- output --
'function f(a) {\n' +
' c: do\n' +
' if (x) {} else if (y) {}\n' +
' while (0);\n' +
' return 0;\n' +
'}')
bt(
'function f(a) {c: if (x) {} else if (y) {} return 0;}',
# -- output --
'function f(a) {\n' +
' c: if (x) {} else if (y) {}\n' +
' return 0;\n' +
'}')
#============================================================
# Test non-positionable-ops
self.reset_options()
bt('a += 2;')
bt('a -= 2;')
bt('a *= 2;')
bt('a /= 2;')
bt('a %= 2;')
bt('a &= 2;')
bt('a ^= 2;')
bt('a |= 2;')
bt('a **= 2;')
bt('a <<= 2;')
bt('a >>= 2;')
#============================================================
#
self.reset_options()
# exponent literals
bt('a = 1e10')
bt('a = 1.3e10')
bt('a = 1.3e-10')
bt('a = -12345.3e-10')
bt('a = .12345e-10')
bt('a = 06789e-10')
bt('a = e - 10')
bt('a = 1.3e+10')
bt('a = 1.e-7')
bt('a = -12345.3e+10')
bt('a = .12345e+10')
bt('a = 06789e+10')
bt('a = e + 10')
bt('a=0e-12345.3e-10', 'a = 0e-12345 .3e-10')
bt('a=0.e-12345.3e-10', 'a = 0.e-12345 .3e-10')
bt('a=0x.e-12345.3e-10', 'a = 0x.e - 12345.3e-10')
bt('a=0x0.e-12345.3e-10', 'a = 0x0.e - 12345.3e-10')
bt('a=0x0.0e-12345.3e-10', 'a = 0x0 .0e-12345 .3e-10')
bt('a=0g-12345.3e-10', 'a = 0 g - 12345.3e-10')
bt('a=0.g-12345.3e-10', 'a = 0. g - 12345.3e-10')
bt('a=0x.g-12345.3e-10', 'a = 0x.g - 12345.3e-10')
bt('a=0x0.g-12345.3e-10', 'a = 0x0.g - 12345.3e-10')
bt('a=0x0.0g-12345.3e-10', 'a = 0x0 .0 g - 12345.3e-10')
# exponent literals with underscore
bt('a = 1_1e10')
bt('a = 1_.3e10')
bt('a = 1_1.3e10')
bt('a = 1__1.3e10')
bt('a = 1._3e10')
bt('a = 1.3_e10')
bt('a = 1.3e_10')
bt('a = 1.3e1_0')
bt('a = 1.3e10_')
# Decimal literals
bt('a = 0123456789;')
bt('a = 9876543210;')
bt('a = 5647308291;')
bt('a=030e-5', 'a = 030e-5')
bt('a=00+4', 'a = 00 + 4')
bt('a=32+4', 'a = 32 + 4')
bt('a=0.6g+4', 'a = 0.6 g + 4')
bt('a=01.10', 'a = 01.10')
bt('a=a.10', 'a = a .10')
bt('a=00B0x0', 'a = 00 B0x0')
bt('a=00B0xb0', 'a = 00 B0xb0')
bt('a=00B0x0b0', 'a = 00 B0x0b0')
bt('a=0090x0', 'a = 0090 x0')
bt('a=0g0b0o0', 'a = 0 g0b0o0')
# Decimal literals with underscore
bt('a = 0_123456789')
bt('a = 0__123456789')
bt('a = 0__')
bt('a = 0_1_2_3')
bt('a = 0_1_2_3_')
# Hexadecimal literals
bt('a = 0x0123456789abcdef;')
bt('a = 0X0123456789ABCDEF;')
bt('a = 0xFeDcBa9876543210;')
bt('a=0x30e-5', 'a = 0x30e - 5')
bt('a=0xF0+4', 'a = 0xF0 + 4')
bt('a=0Xff+4', 'a = 0Xff + 4')
bt('a=0Xffg+4', 'a = 0Xff g + 4')
bt('a=0x01.10', 'a = 0x01 .10')
bt('a = 0xb0ce;')
bt('a = 0x0b0;')
bt('a=0x0B0x0', 'a = 0x0B0 x0')
bt('a=0x0B0xb0', 'a = 0x0B0 xb0')
bt('a=0x0B0x0b0', 'a = 0x0B0 x0b0')
bt('a=0X090x0', 'a = 0X090 x0')
bt('a=0Xg0b0o0', 'a = 0X g0b0o0')
# Hexadecimal literals with underscore
bt('a = 0x0_123456789abcdef')
bt('a = 0x0__0123456789abcdef')
bt('a = 0x_0123456789abcdef')
bt('a = 0x__')
bt('a = 0x0_1_a_3')
bt('a = 0x_1_2_F_')
# Octal literals
bt('a = 0o01234567;')
bt('a = 0O01234567;')
bt('a = 0o34120675;')
bt('a=0o30e-5', 'a = 0o30 e - 5')
bt('a=0o70+4', 'a = 0o70 + 4')
bt('a=0O77+4', 'a = 0O77 + 4')
bt('a=0O778+4', 'a = 0O77 8 + 4')
bt('a=0O77a+4', 'a = 0O77 a + 4')
bt('a=0o01.10', 'a = 0o01 .10')
bt('a=0o0B0x0', 'a = 0o0 B0x0')
bt('a=0o0B0xb0', 'a = 0o0 B0xb0')
bt('a=0o0B0x0b0', 'a = 0o0 B0x0b0')
bt('a=0O090x0', 'a = 0O0 90 x0')
bt('a=0Og0b0o0', 'a = 0O g0b0o0')
# Octal literals with underscore
bt('a = 0o0_1234567')
bt('a = 0o0__1234567')
bt('a = 0o_01234567')
bt('a = 0o__')
bt('a = 0o0_1_2_3')
bt('a = 0o_1_2_3_')
# Binary literals
bt('a = 0b010011;')
bt('a = 0B010011;')
bt('a = 0b01001100001111;')
bt('a=0b10e-5', 'a = 0b10 e - 5')
bt('a=0b10+4', 'a = 0b10 + 4')
bt('a=0B11+4', 'a = 0B11 + 4')
bt('a=0B112+4', 'a = 0B11 2 + 4')
bt('a=0B11a+4', 'a = 0B11 a + 4')
bt('a=0b01.10', 'a = 0b01 .10')
bt('a=0b0B0x0', 'a = 0b0 B0x0')
bt('a=0b0B0xb0', 'a = 0b0 B0xb0')
bt('a=0b0B0x0b0', 'a = 0b0 B0x0b0')
bt('a=0B090x0', 'a = 0B0 90 x0')
bt('a=0Bg0b0o0', 'a = 0B g0b0o0')
# Binary literals with underscore
bt('a = 0b0_10011')
bt('a = 0b0__10011')
bt('a = 0b_010011')
bt('a = 0b__')
bt('a = 0b0_1_1_1')
bt('a = 0b_1_0_1_')
bt('a = 0B010_0_11;')
bt('a = 0b01_0011_0000_1111;')
# BigInt literals
bt('a = 1n;')
bt('a = 1234567890123456789n;')
bt('a = -1234567890123456789n;')
bt('a = 1234567890123456789 N;')
bt('a=0b10e-5n', 'a = 0b10 e - 5n')
bt('a=.0n', 'a = .0 n')
bt('a=1.0n', 'a = 1.0 n')
bt('a=1e0n', 'a = 1e0 n')
bt('a=0n11a+4', 'a = 0n 11 a + 4')
# BigInt literals with underscore
bt('a = 0_123456789n')
bt('a = 0__123456789n')
bt('a = 0__n')
bt('a = 0_1_2_3n')
bt('a = 0_1_2_3_n')
# BigInt hexadecimal literals
bt('a = 0x0123456789abcdefn;')
bt('a = 0X0123456789ABCDEFn;')
bt('a = 0xFeDcBa9876543210n;')
bt('a=0x30en-5', 'a = 0x30en - 5')
bt('a=0xF0n+4', 'a = 0xF0n + 4')
bt('a=0Xffn+4', 'a = 0Xffn + 4')
bt('a=0Xffng+4', 'a = 0Xffn g + 4')
bt('a=0x01n.10', 'a = 0x01n .10')
bt('a = 0xb0cen;')
bt('a = 0x0b0n;')
bt('a=0x0B0nx0', 'a = 0x0B0n x0')
bt('a=0x0B0nxb0', 'a = 0x0B0n xb0')
bt('a=0x0B0nx0b0', 'a = 0x0B0n x0b0')
bt('a=0X090nx0', 'a = 0X090n x0')
# BigInt hexadecimal literals with underscore
bt('a = 0x0_123456789abcdefn')
bt('a = 0x0__0123456789abcdefn')
bt('a = 0x_0123456789abcdefn')
bt('a = 0x__n')
bt('a = 0x0_1_a_3n')
bt('a = 0x_1_2_F_n')
# BigInt octal literals
bt('a = 0o01234567n;')
bt('a = 0O01234567n;')
bt('a = 0o34120675n;')
bt('a=0o30ne-5', 'a = 0o30n e - 5')
bt('a=0o70n+4', 'a = 0o70n + 4')
bt('a=0O77n+4', 'a = 0O77n + 4')
bt('a=0O77n8+4', 'a = 0O77n 8 + 4')
bt('a=0O77na+4', 'a = 0O77n a + 4')
bt('a=0o01n.10', 'a = 0o01n .10')
bt('a=0o0nB0x0', 'a = 0o0n B0x0')
bt('a=0o0nB0xb0', 'a = 0o0n B0xb0')
bt('a=0o0nB0x0b0', 'a = 0o0n B0x0b0')
bt('a=0O0n90x0', 'a = 0O0n 90 x0')
# BigInt octal literals with underscore
bt('a = 0o0_1234567n')
bt('a = 0o0__1234567n')
bt('a = 0o_01234567n')
bt('a = 0o__n')
bt('a = 0o0_1_2_3n')
bt('a = 0o_1_2_3_n')
# BigInt binary literals
bt('a = 0b010011n;')
bt('a = 0B010011n;')
bt('a = 0b01001100001111n;')
bt('a=0b10ne-5', 'a = 0b10n e - 5')
bt('a=0b10n+4', 'a = 0b10n + 4')
bt('a=0B11n+4', 'a = 0B11n + 4')
bt('a=0B11n2+4', 'a = 0B11n 2 + 4')
bt('a=0B11na+4', 'a = 0B11n a + 4')
bt('a=0b01n.10', 'a = 0b01n .10')
bt('a=0b0nB0x0', 'a = 0b0n B0x0')
bt('a=0b0nB0xb0', 'a = 0b0n B0xb0')
bt('a=0b0nB0x0b0', 'a = 0b0n B0x0b0')
bt('a=0B0n90x0', 'a = 0B0n 90 x0')
# BigInt binary literals with underscore
bt('a = 0b0_10011n')
bt('a = 0b0__10011n')
bt('a = 0b_010011')
bt('a = 0b__n')
bt('a = 0b0_1_1_1n')
bt('a = 0b_1_0_1_n')
bt('a = 0B010_0_11n;')
bt('a = 0b01_0011_0000_1111n;')
#============================================================
# brace_style ,preserve-inline tests - (brace_style = ""collapse,preserve-inline"")
self.reset_options()
self.options.brace_style = 'collapse,preserve-inline'
bt('import { asdf } from "asdf";')
bt('import { get } from "asdf";')
bt('function inLine() { console.log("oh em gee"); }')
bt('if (cancer) { console.log("Im sorry but you only have so long to live..."); }')
bt('if (ding) { console.log("dong"); } else { console.log("dang"); }')
bt(
'function kindaComplex() {\n' +
' var a = 2;\n' +
' var obj = {};\n' +
' var obj2 = { a: "a", b: "b" };\n' +
' var obj3 = {\n' +
' c: "c",\n' +
' d: "d",\n' +
' e: "e"\n' +
' };\n' +
'}')
bt(
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}',
# -- output --
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}')
# brace_style ,preserve-inline tests - (brace_style = ""expand,preserve-inline"")
self.reset_options()
self.options.brace_style = 'expand,preserve-inline'
bt('import { asdf } from "asdf";')
bt('import { get } from "asdf";')
bt('function inLine() { console.log("oh em gee"); }')
bt('if (cancer) { console.log("Im sorry but you only have so long to live..."); }')
bt(
'if (ding) { console.log("dong"); } else { console.log("dang"); }',
# -- output --
'if (ding) { console.log("dong"); }\n' +
'else { console.log("dang"); }')
bt(
'function kindaComplex() {\n' +
' var a = 2;\n' +
' var obj = {};\n' +
' var obj2 = { a: "a", b: "b" };\n' +
' var obj3 = {\n' +
' c: "c",\n' +
' d: "d",\n' +
' e: "e"\n' +
' };\n' +
'}',
# -- output --
'function kindaComplex()\n' +
'{\n' +
' var a = 2;\n' +
' var obj = {};\n' +
' var obj2 = { a: "a", b: "b" };\n' +
' var obj3 = {\n' +
' c: "c",\n' +
' d: "d",\n' +
' e: "e"\n' +
' };\n' +
'}')
bt(
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}',
# -- output --
'function complex()\n' +
'{\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b()\n' +
' {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}')
# brace_style ,preserve-inline tests - (brace_style = ""end-expand,preserve-inline"")
self.reset_options()
self.options.brace_style = 'end-expand,preserve-inline'
bt('import { asdf } from "asdf";')
bt('import { get } from "asdf";')
bt('function inLine() { console.log("oh em gee"); }')
bt('if (cancer) { console.log("Im sorry but you only have so long to live..."); }')
bt(
'if (ding) { console.log("dong"); } else { console.log("dang"); }',
# -- output --
'if (ding) { console.log("dong"); }\n' +
'else { console.log("dang"); }')
bt(
'function kindaComplex() {\n' +
' var a = 2;\n' +
' var obj = {};\n' +
' var obj2 = { a: "a", b: "b" };\n' +
' var obj3 = {\n' +
' c: "c",\n' +
' d: "d",\n' +
' e: "e"\n' +
' };\n' +
'}')
bt(
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}',
# -- output --
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}')
# brace_style ,preserve-inline tests - (brace_style = ""none,preserve-inline"")
self.reset_options()
self.options.brace_style = 'none,preserve-inline'
bt('import { asdf } from "asdf";')
bt('import { get } from "asdf";')
bt('function inLine() { console.log("oh em gee"); }')
bt('if (cancer) { console.log("Im sorry but you only have so long to live..."); }')
bt('if (ding) { console.log("dong"); } else { console.log("dang"); }')
bt(
'function kindaComplex() {\n' +
' var a = 2;\n' +
' var obj = {};\n' +
' var obj2 = { a: "a", b: "b" };\n' +
' var obj3 = {\n' +
' c: "c",\n' +
' d: "d",\n' +
' e: "e"\n' +
' };\n' +
'}')
bt(
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}',
# -- output --
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}')
# brace_style ,preserve-inline tests - (brace_style = ""collapse-preserve-inline"")
self.reset_options()
self.options.brace_style = 'collapse-preserve-inline'
bt('import { asdf } from "asdf";')
bt('import { get } from "asdf";')
bt('function inLine() { console.log("oh em gee"); }')
bt('if (cancer) { console.log("Im sorry but you only have so long to live..."); }')
bt('if (ding) { console.log("dong"); } else { console.log("dang"); }')
bt(
'function kindaComplex() {\n' +
' var a = 2;\n' +
' var obj = {};\n' +
' var obj2 = { a: "a", b: "b" };\n' +
' var obj3 = {\n' +
' c: "c",\n' +
' d: "d",\n' +
' e: "e"\n' +
' };\n' +
'}')
bt(
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}',
# -- output --
'function complex() {\n' +
' console.log("wowe");\n' +
' (function() { var a = 2; var b = 3; })();\n' +
' $.each(arr, function(el, idx) { return el; });\n' +
' var obj = {\n' +
' a: function() { console.log("test"); },\n' +
' b() {\n' +
' console.log("test2");\n' +
' }\n' +
' };\n' +
'}')
#============================================================
# Destructured and related
self.reset_options()
self.options.brace_style = 'collapse,preserve-inline'
# Issue 382 - import destructured
bt(
'module "Even" {\n' +
' import { odd, oddly } from "Odd";\n' +
'}')
bt(
'import defaultMember from "module-name";\n' +
'import * as name from "module-name";\n' +
'import { member } from "module-name";\n' +
'import { member as alias } from "module-name";\n' +
'import { member1, member2 } from "module-name";\n' +
'import { member1, member2 as alias2 } from "module-name";\n' +
'import defaultMember, { member, member2 } from "module-name";\n' +
'import defaultMember, * as name from "module-name";\n' +
'import "module-name";\n' +
'import("module-name")')
# Issue #1393 - dynamic import()
bt(
'if (from < to) {\n' +
' import(`dynamic${library}`);\n' +
'} else {\n' +
' import("otherdynamic");\n' +
'}')
# Issue #1197 - dynamic import() arrow syntax
bt('frontend = Async(() => import("../frontend").then(m => m.default ))', 'frontend = Async(() => import("../frontend").then(m => m.default))')
# Issue #1978 - import.meta syntax support
bt('let x = import.meta', 'let x = import.meta')
# Issue 858 - from is a keyword only after import
bt(
'if (from < to) {\n' +
' from++;\n' +
'} else {\n' +
' from--;\n' +
'}')
# Issue 511 - destrutured
bt(
'var { b, c } = require("../stores");\n' +
'var { ProjectStore } = require("../stores");\n' +
'\n' +
'function takeThing({ prop }) {\n' +
' console.log("inner prop", prop)\n' +
'}')
# Issue 315 - Short objects
bt('var a = { b: { c: { d: e } } };')
bt(
'var a = {\n' +
' b: {\n' +
' c: { d: e }\n' +
' c3: { d: e }\n' +
' },\n' +
' b2: { c: { d: e } }\n' +
'};')
# Issue 370 - Short objects in array
bt(
'var methods = [\n' +
' { name: "to" },\n' +
' { name: "step" },\n' +
' { name: "move" },\n' +
' { name: "min" },\n' +
' { name: "max" }\n' +
'];')
# Issue 838 - Short objects in array
bt(
'function(url, callback) {\n' +
' var script = document.createElement("script")\n' +
' if (true) script.onreadystatechange = function() {\n' +
' foo();\n' +
' }\n' +
' else script.onload = callback;\n' +
'}')
# Issue 578 - Odd indenting after function
bt(
'function bindAuthEvent(eventName) {\n' +
' self.auth.on(eventName, function(event, meta) {\n' +
' self.emit(eventName, event, meta);\n' +
' });\n' +
'}\n' +
'["logged_in", "logged_out", "signed_up", "updated_user"].forEach(bindAuthEvent);')
# Issue #487 - some short expressions examples
bt(
'if (a == 1) { a++; }\n' +
'a = { a: a };\n' +
'UserDB.findOne({ username: "xyz" }, function(err, user) {});\n' +
'import { fs } from "fs";')
# Issue #982 - Fixed return expression collapse-preserve-inline
bt(
'function foo(arg) {\n' +
' if (!arg) { a(); }\n' +
' if (!arg) { return false; }\n' +
' if (!arg) { throw "inline"; }\n' +
' return true;\n' +
'}')
# Issue #338 - Short expressions
bt(
'if (someCondition) { return something; }\n' +
'if (someCondition) {\n' +
' return something;\n' +
'}\n' +
'if (someCondition) { break; }\n' +
'if (someCondition) {\n' +
' return something;\n' +
'}')
# Issue #1283 - Javascript ++ Operator get wrong indent
bt(
'{this.foo++\n' +
'bar}',
# -- output --
'{\n' +
' this.foo++\n' +
' bar\n' +
'}')
# Issue #1283 - Javascript ++ Operator get wrong indent (2)
bt(
'axios.interceptors.request.use(\n' +
' config => {\n' +
' // loading\n' +
' window.store.loading++\n' +
' let extraParams = {}\n' +
' }\n' +
')')
# Issue ##1846 - in keyword in class method causes indentation problem
bt(
'class {\n' +
' get a() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' in() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' b() {\n' +
'\n' +
'\n' +
' }\n' +
'}',
# -- output --
'class {\n' +
' get a() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' in() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' b() {\n' +
'\n' +
'\n' +
' }\n' +
'}')
# Related to Issue ##1846 - Do not indent 'in' keyword if not a class method
bt(
'function test() {\n' +
'for x in nums {}\n' +
'"make" in car\n' +
'3 in number;\n' +
'}',
# -- output --
'function test() {\n' +
' for x in nums {}\n' +
' "make" in car\n' +
' 3 in number;\n' +
'}')
# Related to Issue ##1846 - of keyword in class method causes indentation problem
bt(
'class {\n' +
' get a() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' of() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' b() {\n' +
'\n' +
'\n' +
' }\n' +
'}',
# -- output --
'class {\n' +
' get a() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' of() {\n' +
'\n' +
'\n' +
' }\n' +
'\n' +
'\n' +
' b() {\n' +
'\n' +
'\n' +
' }\n' +
'}')
# Issue #1950: Do not remove whitespace after number - test scenario: number before a dot
bt('1000000000000001000 .toFixed(0)!==1000000000000001024', '1000000000000001000 .toFixed(0) !== 1000000000000001024')
# Issue #1950: Do not remove whitespace after number - test scenario: variable ends with a number before a dot
bt('a.b21 . performAction()', 'a.b21.performAction()')
#============================================================
# keep_array_indentation false
self.reset_options()
self.options.keep_array_indentation = false
bt(
'a = ["a", "b", "c",\n' +
' "d", "e", "f"]',
# -- output --
'a = ["a", "b", "c",\n' +
' "d", "e", "f"\n' +
']')
bt(
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"]',
# -- output --
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"\n' +
']')
bt(
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"]',
# -- output --
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"\n' +
']')
bt(
'var x = [{}\n' +
']',
# -- output --
'var x = [{}]')
bt(
'var x = [{foo:bar}\n' +
']',
# -- output --
'var x = [{\n' +
' foo: bar\n' +
'}]')
bt(
'a = ["something",\n' +
' "completely",\n' +
' "different"];\n' +
'if (x);',
# -- output --
'a = ["something",\n' +
' "completely",\n' +
' "different"\n' +
'];\n' +
'if (x);')
bt('a = ["a","b","c"]', 'a = ["a", "b", "c"]')
bt('a = ["a", "b","c"]', 'a = ["a", "b", "c"]')
bt(
'x = [{"a":0}]',
# -- output --
'x = [{\n' +
' "a": 0\n' +
'}]')
bt(
'{a([[a1]], {b;});}',
# -- output --
'{\n' +
' a([\n' +
' [a1]\n' +
' ], {\n' +
' b;\n' +
' });\n' +
'}')
bt(
'a ();\n' +
' [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ].toString();',
# -- output --
'a();\n' +
'[\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
'].toString();')
bt(
'a ();\n' +
'a = [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ].toString();',
# -- output --
'a();\n' +
'a = [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
'].toString();')
bt(
'function() {\n' +
' Foo([\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ]);\n' +
'}',
# -- output --
'function() {\n' +
' Foo([\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ]);\n' +
'}')
bt(
'function foo() {\n' +
' return [\n' +
' "one",\n' +
' "two"\n' +
' ];\n' +
'}',
# -- output --
'function foo() {\n' +
' return [\n' +
' "one",\n' +
' "two"\n' +
' ];\n' +
'}')
bt(
'function foo() {\n' +
' return [\n' +
' {\n' +
' one: "x",\n' +
' two: [\n' +
' {\n' +
' id: "a",\n' +
' name: "apple"\n' +
' }, {\n' +
' id: "b",\n' +
' name: "banana"\n' +
' }\n' +
' ]\n' +
' }\n' +
' ];\n' +
'}',
# -- output --
'function foo() {\n' +
' return [{\n' +
' one: "x",\n' +
' two: [{\n' +
' id: "a",\n' +
' name: "apple"\n' +
' }, {\n' +
' id: "b",\n' +
' name: "banana"\n' +
' }]\n' +
' }];\n' +
'}')
bt(
'function foo() {\n' +
' return [\n' +
' {\n' +
' one: "x",\n' +
' two: [\n' +
' {\n' +
' id: "a",\n' +
' name: "apple"\n' +
' }, {\n' +
' id: "b",\n' +
' name: "banana"\n' +
' }\n' +
' ]\n' +
' }\n' +
' ];\n' +
'}',
# -- output --
'function foo() {\n' +
' return [{\n' +
' one: "x",\n' +
' two: [{\n' +
' id: "a",\n' +
' name: "apple"\n' +
' }, {\n' +
' id: "b",\n' +
' name: "banana"\n' +
' }]\n' +
' }];\n' +
'}')
#============================================================
# keep_array_indentation true
self.reset_options()
self.options.keep_array_indentation = true
bt(
'a = ["a", "b", "c",\n' +
' "d", "e", "f"]',
# -- output --
'a = ["a", "b", "c",\n' +
' "d", "e", "f"]')
bt(
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"]',
# -- output --
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"]')
bt(
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"]',
# -- output --
'a = ["a", "b", "c",\n' +
' "d", "e", "f",\n' +
' "g", "h", "i"]')
bt(
'var x = [{}\n' +
']',
# -- output --
'var x = [{}\n' +
']')
bt(
'var x = [{foo:bar}\n' +
']',
# -- output --
'var x = [{\n' +
' foo: bar\n' +
' }\n' +
']')
bt(
'a = ["something",\n' +
' "completely",\n' +
' "different"];\n' +
'if (x);',
# -- output --
'a = ["something",\n' +
' "completely",\n' +
' "different"];\n' +
'if (x);')
bt('a = ["a","b","c"]', 'a = ["a", "b", "c"]')
bt('a = ["a", "b","c"]', 'a = ["a", "b", "c"]')
bt(
'x = [{"a":0}]',
# -- output --
'x = [{\n' +
' "a": 0\n' +
'}]')
bt(
'{a([[a1]], {b;});}',
# -- output --
'{\n' +
' a([[a1]], {\n' +
' b;\n' +
' });\n' +
'}')
bt(
'a ();\n' +
' [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ].toString();',
# -- output --
'a();\n' +
' [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ].toString();')
bt(
'a ();\n' +
'a = [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ].toString();',
# -- output --
'a();\n' +
'a = [\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ].toString();')
bt(
'function() {\n' +
' Foo([\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ]);\n' +
'}',
# -- output --
'function() {\n' +
' Foo([\n' +
' ["sdfsdfsd"],\n' +
' ["sdfsdfsdf"]\n' +
' ]);\n' +
'}')
bt(
'function foo() {\n' +
' return [\n' +
' "one",\n' +
' "two"\n' +
' ];\n' +
'}',
# -- output --
'function foo() {\n' +
' return [\n' +
' "one",\n' +
' "two"\n' +
' ];\n' +
'}')
bt(
'function foo() {\n' +
' return [\n' +
' {\n' +
' one: "x",\n' +
' two: [\n' +
' {\n' +
' id: "a",\n' +
' name: "apple"\n' +
' }, {\n' +
' id: "b",\n' +
' name: "banana"\n' +
' }\n' +
' ]\n' +
' }\n' +
' ];\n' +
'}',
# -- output --
'function foo() {\n' +
' return [\n' +
' {\n' +
' one: "x",\n' +
' two: [\n' +
' {\n' +
' id: "a",\n' +
' name: "apple"\n' +
' }, {\n' +
' id: "b",\n' +
' name: "banana"\n' +
' }\n' +
' ]\n' +
' }\n' +
' ];\n' +
'}')
#============================================================
# indent_empty_lines true
self.reset_options()
self.options.indent_empty_lines = true
test_fragment(
'var a = 1;\n' +
'\n' +
'var b = 1;')
test_fragment(
'var a = 1;\n' +
' \n' +
'var b = 1;',
# -- output --
'var a = 1;\n' +
'\n' +
'var b = 1;')
test_fragment(
'{\n' +
' var a = 1;\n' +
' \n' +
' var b = 1;\n' +
'\n' +
'}',
# -- output --
'{\n' +
' var a = 1;\n' +
' \n' +
' var b = 1;\n' +
' \n' +
'}')
test_fragment(
'{\n' +
'\n' +
' var a = 1;\n' +
'\n' +
'\n' +
'\n' +
' var b = 1;\n' +
'\n' +
'}',
# -- output --
'{\n' +
' \n' +
' var a = 1;\n' +
' \n' +
' \n' +
' \n' +
' var b = 1;\n' +
' \n' +
'}')
test_fragment(
'{\n' +
'\n' +
' var a = 1;\n' +
'\n' +
'function A() {\n' +
'\n' +
'}\n' +
'\n' +
' var b = 1;\n' +
'\n' +
'}',
# -- output --
'{\n' +
' \n' +
' var a = 1;\n' +
' \n' +
' function A() {\n' +
' \n' +
' }\n' +
' \n' +
' var b = 1;\n' +
' \n' +
'}')
#============================================================
# indent_empty_lines false
self.reset_options()
self.options.indent_empty_lines = false
test_fragment(
'var a = 1;\n' +
'\n' +
'var b = 1;')
test_fragment(
'var a = 1;\n' +
' \n' +
'var b = 1;',
# -- output --
'var a = 1;\n' +
'\n' +
'var b = 1;')
test_fragment(
'{\n' +
' var a = 1;\n' +
' \n' +
' var b = 1;\n' +
'\n' +
'}',
# -- output --
'{\n' +
' var a = 1;\n' +
'\n' +
' var b = 1;\n' +
'\n' +
'}')
test_fragment(
'{\n' +
'\n' +
' var a = 1;\n' +
'\n' +
'\n' +
'\n' +
' var b = 1;\n' +
'\n' +
'}')
test_fragment(
'{\n' +
'\n' +
' var a = 1;\n' +
'\n' +
'function A() {\n' +
'\n' +
'}\n' +
'\n' +
' var b = 1;\n' +
'\n' +
'}',
# -- output --
'{\n' +
'\n' +
' var a = 1;\n' +
'\n' +
' function A() {\n' +
'\n' +
' }\n' +
'\n' +
' var b = 1;\n' +
'\n' +
'}')
#============================================================
# Record data type
self.reset_options()
# regular record with primitive
bt(
'a = #{ b:"c", d:1, e:true };',
# -- output --
'a = #{\n' +
' b: "c",\n' +
' d: 1,\n' +
' e: true\n' +
'};')
# nested record
bt(
'a = #{b:#{ c:1,d:2,}, e:"f"};',
# -- output --
'a = #{\n' +
' b: #{\n' +
' c: 1,\n' +
' d: 2,\n' +
' },\n' +
' e: "f"\n' +
'};')
# # not directly followed by { is not handled as record
bt(
'a = # {\n' +
' b: 1,\n' +
' d: true\n' +
'};')
# example of already valid and beautified record
bt(
'a = #{\n' +
' b: 1,\n' +
' d: true\n' +
'};')
#============================================================
# Old tests
self.reset_options()
bt('')
test_fragment(' return .5')
test_fragment(
' return .5;\n' +
' a();')
test_fragment(
' return .5;\n' +
' a();')
test_fragment(
' return .5;\n' +
' a();')
test_fragment(' < div')
bt('a = 1', 'a = 1')
bt('a=1', 'a = 1')
bt('(3) / 2')
bt('["a", "b"].join("")')
bt(
'a();\n' +
'\n' +
'b();')
bt(
'var a = 1 var b = 2',
# -- output --
'var a = 1\n' +
'var b = 2')
bt(
'var a=1, b=c[d], e=6;',
# -- output --
'var a = 1,\n' +
' b = c[d],\n' +
' e = 6;')
bt(
'var a,\n' +
' b,\n' +
' c;')
bt(
'let a = 1 let b = 2',
# -- output --
'let a = 1\n' +
'let b = 2')
bt(
'let a=1, b=c[d], e=6;',
# -- output --
'let a = 1,\n' +
' b = c[d],\n' +
' e = 6;')
bt(
'let a,\n' +
' b,\n' +
' c;')
bt(
'const a = 1 const b = 2',
# -- output --
'const a = 1\n' +
'const b = 2')
bt(
'const a=1, b=c[d], e=6;',
# -- output --
'const a = 1,\n' +
' b = c[d],\n' +
' e = 6;')
bt(
'const a,\n' +
' b,\n' +
' c;')
bt('a = " 12345 "')
bt('a = \' 12345 \'')
bt('if (a == 1) b = 2;')
bt(
'if(1){2}else{3}',
# -- output --
'if (1) {\n' +
' 2\n' +
'} else {\n' +
' 3\n' +
'}')
bt('if(1||2);', 'if (1 || 2);')
bt('(a==1)||(b==2)', '(a == 1) || (b == 2)')
bt(
'var a = 1 if (2) 3;',
# -- output --
'var a = 1\n' +
'if (2) 3;')
bt('a = a + 1')
bt('a = a == 1')
bt('/12345[^678]*9+/.match(a)')
bt('a /= 5')
bt('a = 0.5 * 3')
bt('a *= 10.55')
bt('a < .5')
bt('a <= .5')
bt('a<.5', 'a < .5')
bt('a<=.5', 'a <= .5')
bt('a = [1, 2, 3, 4]')
bt('F*(g/=f)*g+b', 'F * (g /= f) * g + b')
bt(
'a.b({c:d})',
# -- output --
'a.b({\n' +
' c: d\n' +
'})')
bt(
'a.b\n' +
'(\n' +
'{\n' +
'c:\n' +
'd\n' +
'}\n' +
')',
# -- output --
'a.b({\n' +
' c: d\n' +
'})')
bt(
'a.b({c:"d"})',
# -- output --
'a.b({\n' +
' c: "d"\n' +
'})')
bt(
'a.b\n' +
'(\n' +
'{\n' +
'c:\n' +
'"d"\n' +
'}\n' +
')',
# -- output --
'a.b({\n' +
' c: "d"\n' +
'})')
bt('a=!b', 'a = !b')
bt('a=!!b', 'a = !!b')
bt('a?b:c', 'a ? b : c')
bt('a?1:2', 'a ? 1 : 2')
bt('a?(b):c', 'a ? (b) : c')
bt(
'x={a:1,b:w=="foo"?x:y,c:z}',
# -- output --
'x = {\n' +
' a: 1,\n' +
' b: w == "foo" ? x : y,\n' +
' c: z\n' +
'}')
bt('x=a?b?c?d:e:f:g;', 'x = a ? b ? c ? d : e : f : g;')
bt(
'x=a?b?c?d:{e1:1,e2:2}:f:g;',
# -- output --
'x = a ? b ? c ? d : {\n' +
' e1: 1,\n' +
' e2: 2\n' +
'} : f : g;')
bt('function void(void) {}')
bt('if(!a)foo();', 'if (!a) foo();')
bt('a=~a', 'a = ~a')
bt(
'a;/*comment*/b;',
# -- output --
'a; /*comment*/\n' +
'b;')
bt(
'a;/* comment */b;',
# -- output --
'a; /* comment */\n' +
'b;')
# simple comments don't get touched at all
test_fragment(
'a;/*\n' +
'comment\n' +
'*/b;',
# -- output --
'a;\n' +
'/*\n' +
'comment\n' +
'*/\n' +
'b;')
bt(
'a;/**\n' +
'* javadoc\n' +
'*/b;',
# -- output --
'a;\n' +
'/**\n' +
' * javadoc\n' +
' */\n' +
'b;')
test_fragment(
'a;/**\n' +
'\n' +
'no javadoc\n' +
'*/b;',
# -- output --
'a;\n' +
'/**\n' +
'\n' +
'no javadoc\n' +
'*/\n' +
'b;')
# comment blocks detected and reindented even w/o javadoc starter
bt(
'a;/*\n' +
'* javadoc\n' +
'*/b;',
# -- output --
'a;\n' +
'/*\n' +
' * javadoc\n' +
' */\n' +
'b;')
bt('if(a)break;', 'if (a) break;')
bt(
'if(a){break}',
# -- output --
'if (a) {\n' +
' break\n' +
'}')
bt('if((a))foo();', 'if ((a)) foo();')
bt('for(var i=0;;) a', 'for (var i = 0;;) a')
bt(
'for(var i=0;;)\n' +
'a',
# -- output --
'for (var i = 0;;)\n' +
' a')
bt('a++;')
bt('for(;;i++)a()', 'for (;; i++) a()')
bt(
'for(;;i++)\n' +
'a()',
# -- output --
'for (;; i++)\n' +
' a()')
bt('for(;;++i)a', 'for (;; ++i) a')
bt('return(1)', 'return (1)')
bt(
'try{a();}catch(b){c();}finally{d();}',
# -- output --
'try {\n' +
' a();\n' +
'} catch (b) {\n' +
' c();\n' +
'} finally {\n' +
' d();\n' +
'}')
# magic function call
bt('(xx)()')
# another magic function call
bt('a[1]()')
bt(
'if(a){b();}else if(c) foo();',
# -- output --
'if (a) {\n' +
' b();\n' +
'} else if (c) foo();')
bt(
'switch(x) {case 0: case 1: a(); break; default: break}',
# -- output --
'switch (x) {\n' +
' case 0:\n' +
' case 1:\n' +
' a();\n' +
' break;\n' +
' default:\n' +
' break\n' +
'}')
bt(
'switch(x) {default: case 1: a(); break; case 0: break}',
# -- output --
'switch (x) {\n' +
' default:\n' +
' case 1:\n' +
' a();\n' +
' break;\n' +
' case 0:\n' +
' break\n' +
'}')
bt(
'switch(x){case -1:break;case !y:break;}',
# -- output --
'switch (x) {\n' +
' case -1:\n' +
' break;\n' +
' case !y:\n' +
' break;\n' +
'}')
bt('a !== b')
bt(
'if (a) b(); else c();',
# -- output --
'if (a) b();\n' +
'else c();')
# typical greasemonkey start
bt(
'// comment\n' +
'(function something() {})')
# duplicating newlines
bt(
'{\n' +
'\n' +
' x();\n' +
'\n' +
'}')
bt('if (a in b) foo();')
bt('if (a of b) foo();')
bt('if (a of [1, 2, 3]) foo();')
bt(
'if(X)if(Y)a();else b();else c();',
# -- output --
'if (X)\n' +
' if (Y) a();\n' +
' else b();\n' +
'else c();')
bt(
'if (foo) bar();\n' +
'else break')
bt('var a, b;')
bt('var a = new function();')
test_fragment('new function')
bt('var a, b')
bt(
'{a:1, b:2}',
# -- output --
'{\n' +
' a: 1,\n' +
' b: 2\n' +
'}')
bt(
'a={1:[-1],2:[+1]}',
# -- output --
'a = {\n' +
' 1: [-1],\n' +
' 2: [+1]\n' +
'}')
bt(
'var l = {\'a\':\'1\', \'b\':\'2\'}',
# -- output --
'var l = {\n' +
' \'a\': \'1\',\n' +
' \'b\': \'2\'\n' +
'}')
bt('if (template.user[n] in bk) foo();')
bt('return 45')
bt(
'return this.prevObject ||\n' +
'\n' +
' this.constructor(null);')
bt('If[1]')
bt('Then[1]')
bt('a = 1;// comment', 'a = 1; // comment')
bt('a = 1; // comment')
bt(
'a = 1;\n' +
' // comment',
# -- output --
'a = 1;\n' +
'// comment')
bt('a = [-1, -1, -1]')
bt(
'// a\n' +
'// b\n' +
'\n' +
'\n' +
'\n' +
'// c\n' +
'// d')
bt(
'// func-comment\n' +
'\n' +
'function foo() {}\n' +
'\n' +
'// end-func-comment')
# The exact formatting these should have is open for discussion, but they are at least reasonable
bt(
'a = [ // comment\n' +
' -1, -1, -1\n' +
']')
bt(
'var a = [ // comment\n' +
' -1, -1, -1\n' +
']')
bt(
'a = [ // comment\n' +
' -1, // comment\n' +
' -1, -1\n' +
']')
bt(
'var a = [ // comment\n' +
' -1, // comment\n' +
' -1, -1\n' +
']')
bt(
'o = [{a:b},{c:d}]',
# -- output --
'o = [{\n' +
' a: b\n' +
'}, {\n' +
' c: d\n' +
'}]')
# was: extra space appended
bt(
'if (a) {\n' +
' do();\n' +
'}')
# if/else statement with empty body
bt(
'if (a) {\n' +
'// comment\n' +
'}else{\n' +
'// comment\n' +
'}',
# -- output --
'if (a) {\n' +
' // comment\n' +
'} else {\n' +
' // comment\n' +
'}')
# multiple comments indentation
bt(
'if (a) {\n' +
'// comment\n' +
'// comment\n' +
'}',
# -- output --
'if (a) {\n' +
' // comment\n' +
' // comment\n' +
'}')
bt(
'if (a) b() else c();',
# -- output --
'if (a) b()\n' +
'else c();')
bt(
'if (a) b() else if c() d();',
# -- output --
'if (a) b()\n' +
'else if c() d();')
bt('{}')
bt(
'{\n' +
'\n' +
'}')
bt(
'do { a(); } while ( 1 );',
# -- output --
'do {\n' +
' a();\n' +
'} while (1);')
bt('do {} while (1);')
bt(
'do {\n' +
'} while (1);',
# -- output --
'do {} while (1);')
bt(
'do {\n' +
'\n' +
'} while (1);')
bt('var a = x(a, b, c)')
bt(
'delete x if (a) b();',
# -- output --
'delete x\n' +
'if (a) b();')
bt(
'delete x[x] if (a) b();',
# -- output --
'delete x[x]\n' +
'if (a) b();')
bt('for(var a=1,b=2)d', 'for (var a = 1, b = 2) d')
bt('for(var a=1,b=2,c=3) d', 'for (var a = 1, b = 2, c = 3) d')
bt(
'for(var a=1,b=2,c=3;d<3;d++)\n' +
'e',
# -- output --
'for (var a = 1, b = 2, c = 3; d < 3; d++)\n' +
' e')
bt(
'function x(){(a||b).c()}',
# -- output --
'function x() {\n' +
' (a || b).c()\n' +
'}')
bt(
'function x(){return - 1}',
# -- output --
'function x() {\n' +
' return -1\n' +
'}')
bt(
'function x(){return ! a}',
# -- output --
'function x() {\n' +
' return !a\n' +
'}')
bt('x => x')
bt('(x) => x')
bt(
'x => { x }',
# -- output --
'x => {\n' +
' x\n' +
'}')
bt(
'(x) => { x }',
# -- output --
'(x) => {\n' +
' x\n' +
'}')
# a common snippet in jQuery plugins
bt(
'settings = $.extend({},defaults,settings);',
# -- output --
'settings = $.extend({}, defaults, settings);')
bt('$http().then().finally().default()')
bt(
'$http()\n' +
'.then()\n' +
'.finally()\n' +
'.default()',
# -- output --
'$http()\n' +
' .then()\n' +
' .finally()\n' +
' .default()')
bt('$http().when.in.new.catch().throw()')
bt(
'$http()\n' +
'.when\n' +
'.in\n' +
'.new\n' +
'.catch()\n' +
'.throw()',
# -- output --
'$http()\n' +
' .when\n' +
' .in\n' +
' .new\n' +
' .catch()\n' +
' .throw()')
bt(
'{xxx;}()',
# -- output --
'{\n' +
' xxx;\n' +
'}()')
bt(
'a = \'a\'\n' +
'b = \'b\'')
bt('a = /reg/exp')
bt('a = /reg/')
bt('/abc/.test()')
bt('/abc/i.test()')
bt(
'{/abc/i.test()}',
# -- output --
'{\n' +
' /abc/i.test()\n' +
'}')
bt('var x=(a)/a;', 'var x = (a) / a;')
bt('x != -1')
bt('for (; s-->0;)t', 'for (; s-- > 0;) t')
bt('for (; s++>0;)u', 'for (; s++ > 0;) u')
bt('a = s++>s--;', 'a = s++ > s--;')
bt('a = s++>--s;', 'a = s++ > --s;')
bt(
'{x=#1=[]}',
# -- output --
'{\n' +
' x = #1=[]\n' +
'}')
bt(
'{a:#1={}}',
# -- output --
'{\n' +
' a: #1={}\n' +
'}')
bt(
'{a:#1#}',
# -- output --
'{\n' +
' a: #1#\n' +
'}')
test_fragment('"incomplete-string')
test_fragment('\'incomplete-string')
test_fragment('/incomplete-regex')
test_fragment('`incomplete-template-string')
test_fragment(
'{a:1},{a:2}',
# -- output --
'{\n' +
' a: 1\n' +
'}, {\n' +
' a: 2\n' +
'}')
test_fragment(
'var ary=[{a:1}, {a:2}];',
# -- output --
'var ary = [{\n' +
' a: 1\n' +
'}, {\n' +
' a: 2\n' +
'}];')
# incomplete
test_fragment(
'{a:#1',
# -- output --
'{\n' +
' a: #1')
# incomplete
test_fragment(
'{a:#',
# -- output --
'{\n' +
' a: #')
# incomplete
test_fragment(
'}}}',
# -- output --
'}\n' +
'}\n' +
'}')
test_fragment(
'')
# incomplete regexp
test_fragment('a=/regexp', 'a = /regexp')
bt(
'{a:#1=[],b:#1#,c:#999999#}',
# -- output --
'{\n' +
' a: #1=[],\n' +
' b: #1#,\n' +
' c: #999999#\n' +
'}')
bt(
'do{x()}while(a>1)',
# -- output --
'do {\n' +
' x()\n' +
'} while (a > 1)')
bt(
'x(); /reg/exp.match(something)',
# -- output --
'x();\n' +
'/reg/exp.match(something)')
test_fragment(
'something();(',
# -- output --
'something();\n' +
'(')
test_fragment(
'#!she/bangs, she bangs\n' +
'f=1',
# -- output --
'#!she/bangs, she bangs\n' +
'\n' +
'f = 1')
test_fragment(
'#!she/bangs, she bangs\n' +
'\n' +
'f=1',
# -- output --
'#!she/bangs, she bangs\n' +
'\n' +
'f = 1')
test_fragment(
'#!she/bangs, she bangs\n' +
'\n' +
'/* comment */')
test_fragment(
'#!she/bangs, she bangs\n' +
'\n' +
'\n' +
'/* comment */')
test_fragment('#')
test_fragment('#!')
test_fragment('#include')
test_fragment('#include "settings.jsxinc"')
test_fragment(
'#include "settings.jsxinc"\n' +
'\n' +
'\n' +
'/* comment */')
test_fragment(
'#include "settings.jsxinc"\n' +
'\n' +
'\n' +
'#include "settings.jsxinc"\n' +
'\n' +
'\n' +
'/* comment */')
bt('function namespace::something()')
test_fragment(
'')
test_fragment(
'',
# -- output --
'')
bt(
'{foo();--bar;}',
# -- output --
'{\n' +
' foo();\n' +
' --bar;\n' +
'}')
bt(
'{foo();++bar;}',
# -- output --
'{\n' +
' foo();\n' +
' ++bar;\n' +
'}')
bt(
'{--bar;}',
# -- output --
'{\n' +
' --bar;\n' +
'}')
bt(
'{++bar;}',
# -- output --
'{\n' +
' ++bar;\n' +
'}')
bt('if(true)++a;', 'if (true) ++a;')
bt(
'if(true)\n' +
'++a;',
# -- output --
'if (true)\n' +
' ++a;')
bt('if(true)--a;', 'if (true) --a;')
bt(
'if(true)\n' +
'--a;',
# -- output --
'if (true)\n' +
' --a;')
bt('elem[array]++;')
bt('elem++ * elem[array]++;')
bt('elem-- * -elem[array]++;')
bt('elem-- + elem[array]++;')
bt('elem-- - elem[array]++;')
bt('elem-- - -elem[array]++;')
bt('elem-- - +elem[array]++;')
# Handling of newlines around unary ++ and -- operators
bt(
'{foo\n' +
'++bar;}',
# -- output --
'{\n' +
' foo\n' +
' ++bar;\n' +
'}')
bt(
'{foo++\n' +
'bar;}',
# -- output --
'{\n' +
' foo++\n' +
' bar;\n' +
'}')
# This is invalid, but harder to guard against. Issue #203.
bt(
'{foo\n' +
'++\n' +
'bar;}',
# -- output --
'{\n' +
' foo\n' +
' ++\n' +
' bar;\n' +
'}')
# regexps
bt(
'a(/abc\\/\\/def/);b()',
# -- output --
'a(/abc\\/\\/def/);\n' +
'b()')
bt(
'a(/a[b\\[\\]c]d/);b()',
# -- output --
'a(/a[b\\[\\]c]d/);\n' +
'b()')
# incomplete char class
test_fragment('a(/a[b\\[')
# allow unescaped / in char classes
bt(
'a(/[a/b]/);b()',
# -- output --
'a(/[a/b]/);\n' +
'b()')
bt('typeof /foo\\//;')
bt('throw /foo\\//;')
bt('do /foo\\//;')
bt('return /foo\\//;')
bt(
'switch (a) {\n' +
' case /foo\\//:\n' +
' b\n' +
'}')
bt(
'if (a) /foo\\//\n' +
'else /foo\\//;')
bt('if (foo) /regex/.test();')
bt('for (index in [1, 2, 3]) /^test$/i.test(s)')
bt(
'function foo() {\n' +
' return [\n' +
' "one",\n' +
' "two"\n' +
' ];\n' +
'}')
bt(
'a=[[1,2],[4,5],[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' function() {},\n' +
' [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' function() {},\n' +
' function() {},\n' +
' [7, 8]\n' +
']')
bt(
'a=[[1,2],[4,5],function(){},[7,8]]',
# -- output --
'a = [\n' +
' [1, 2],\n' +
' [4, 5],\n' +
' function() {},\n' +
' [7, 8]\n' +
']')
bt('a=[b,c,function(){},function(){},d]', 'a = [b, c, function() {}, function() {}, d]')
bt(
'a=[b,c,\n' +
'function(){},function(){},d]',
# -- output --
'a = [b, c,\n' +
' function() {},\n' +
' function() {},\n' +
' d\n' +
']')
bt('a=[a[1],b[4],c[d[7]]]', 'a = [a[1], b[4], c[d[7]]]')
bt('[1,2,[3,4,[5,6],7],8]', '[1, 2, [3, 4, [5, 6], 7], 8]')
bt(
'[[["1","2"],["3","4"]],[["5","6","7"],["8","9","0"]],[["1","2","3"],["4","5","6","7"],["8","9","0"]]]',
# -- output --
'[\n' +
' [\n' +
' ["1", "2"],\n' +
' ["3", "4"]\n' +
' ],\n' +
' [\n' +
' ["5", "6", "7"],\n' +
' ["8", "9", "0"]\n' +
' ],\n' +
' [\n' +
' ["1", "2", "3"],\n' +
' ["4", "5", "6", "7"],\n' +
' ["8", "9", "0"]\n' +
' ]\n' +
']')
bt(
'{[x()[0]];indent;}',
# -- output --
'{\n' +
' [x()[0]];\n' +
' indent;\n' +
'}')
bt(
'/*\n' +
' foo trailing space \n' +
' * bar trailing space \n' +
'**/')
bt(
'{\n' +
' /*\n' +
' foo \n' +
' * bar \n' +
' */\n' +
'}')
bt('return ++i')
bt(
'obj.num++\n' +
'foo()\n' +
'bar()\n' +
'\n' +
'obj.num--\n' +
'foo()\n' +
'bar()')
bt('return !!x')
bt('return !x')
bt('return [1,2]', 'return [1, 2]')
bt('return;')
bt(
'return\n' +
'func')
bt('catch(e)', 'catch (e)')
bt(
'var a=1,b={foo:2,bar:3},{baz:4,wham:5},c=4;',
# -- output --
'var a = 1,\n' +
' b = {\n' +
' foo: 2,\n' +
' bar: 3\n' +
' },\n' +
' {\n' +
' baz: 4,\n' +
' wham: 5\n' +
' }, c = 4;')
bt(
'var a=1,b={foo:2,bar:3},{baz:4,wham:5},\n' +
'c=4;',
# -- output --
'var a = 1,\n' +
' b = {\n' +
' foo: 2,\n' +
' bar: 3\n' +
' },\n' +
' {\n' +
' baz: 4,\n' +
' wham: 5\n' +
' },\n' +
' c = 4;')
# inline comment
bt(
'function x(/*int*/ start, /*string*/ foo)',
# -- output --
'function x( /*int*/ start, /*string*/ foo)')
# javadoc comment
bt(
'/**\n' +
'* foo\n' +
'*/',
# -- output --
'/**\n' +
' * foo\n' +
' */')
bt(
'{\n' +
'/**\n' +
'* foo\n' +
'*/\n' +
'}',
# -- output --
'{\n' +
' /**\n' +
' * foo\n' +
' */\n' +
'}')
# starless block comment
bt(
'/**\n' +
'foo\n' +
'*/')
bt(
'/**\n' +
'foo\n' +
'**/')
bt(
'/**\n' +
'foo\n' +
'bar\n' +
'**/')
bt(
'/**\n' +
'foo\n' +
'\n' +
'bar\n' +
'**/')
bt(
'/**\n' +
'foo\n' +
' bar\n' +
'**/')
bt(
'{\n' +
'/**\n' +
'foo\n' +
'*/\n' +
'}',
# -- output --
'{\n' +
' /**\n' +
' foo\n' +
' */\n' +
'}')
bt(
'{\n' +
'/**\n' +
'foo\n' +
'**/\n' +
'}',
# -- output --
'{\n' +
' /**\n' +
' foo\n' +
' **/\n' +
'}')
bt(
'{\n' +
'/**\n' +
'foo\n' +
'bar\n' +
'**/\n' +
'}',
# -- output --
'{\n' +
' /**\n' +
' foo\n' +
' bar\n' +
' **/\n' +
'}')
bt(
'{\n' +
'/**\n' +
'foo\n' +
'\n' +
'bar\n' +
'**/\n' +
'}',
# -- output --
'{\n' +
' /**\n' +
' foo\n' +
'\n' +
' bar\n' +
' **/\n' +
'}')
bt(
'{\n' +
'/**\n' +
'foo\n' +
' bar\n' +
'**/\n' +
'}',
# -- output --
'{\n' +
' /**\n' +
' foo\n' +
' bar\n' +
' **/\n' +
'}')
bt(
'{\n' +
' /**\n' +
' foo\n' +
'bar\n' +
' **/\n' +
'}')
bt(
'var a,b,c=1,d,e,f=2;',
# -- output --
'var a, b, c = 1,\n' +
' d, e, f = 2;')
bt(
'var a,b,c=[],d,e,f=2;',
# -- output --
'var a, b, c = [],\n' +
' d, e, f = 2;')
bt(
'function() {\n' +
' var a, b, c, d, e = [],\n' +
' f;\n' +
'}')
bt(
'do/regexp/;\n' +
'while(1);',
# -- output --
'do /regexp/;\n' +
'while (1);')
bt(
'var a = a,\n' +
'a;\n' +
'b = {\n' +
'b\n' +
'}',
# -- output --
'var a = a,\n' +
' a;\n' +
'b = {\n' +
' b\n' +
'}')
bt(
'var a = a,\n' +
' /* c */\n' +
' b;')
bt(
'var a = a,\n' +
' // c\n' +
' b;')
# weird element referencing
bt('foo.("bar");')
bt(
'if (a) a()\n' +
'else b()\n' +
'newline()')
bt(
'if (a) a()\n' +
'newline()')
bt('a=typeof(x)', 'a = typeof(x)')
bt(
'var a = function() {\n' +
' return null;\n' +
' },\n' +
' b = false;')
bt(
'var a = function() {\n' +
' func1()\n' +
'}')
bt(
'var a = function() {\n' +
' func1()\n' +
'}\n' +
'var b = function() {\n' +
' func2()\n' +
'}')
# code with and without semicolons
bt(
'var whatever = require("whatever");\n' +
'function() {\n' +
' a = 6;\n' +
'}',
# -- output --
'var whatever = require("whatever");\n' +
'\n' +
'function() {\n' +
' a = 6;\n' +
'}')
bt(
'var whatever = require("whatever")\n' +
'function() {\n' +
' a = 6\n' +
'}',
# -- output --
'var whatever = require("whatever")\n' +
'\n' +
'function() {\n' +
' a = 6\n' +
'}')
bt(
'{"x":[{"a":1,"b":3},\n' +
'7,8,8,8,8,{"b":99},{"a":11}]}',
# -- output --
'{\n' +
' "x": [{\n' +
' "a": 1,\n' +
' "b": 3\n' +
' },\n' +
' 7, 8, 8, 8, 8, {\n' +
' "b": 99\n' +
' }, {\n' +
' "a": 11\n' +
' }\n' +
' ]\n' +
'}')
bt(
'{"x":[{"a":1,"b":3},7,8,8,8,8,{"b":99},{"a":11}]}',
# -- output --
'{\n' +
' "x": [{\n' +
' "a": 1,\n' +
' "b": 3\n' +
' }, 7, 8, 8, 8, 8, {\n' +
' "b": 99\n' +
' }, {\n' +
' "a": 11\n' +
' }]\n' +
'}')
bt(
'{"1":{"1a":"1b"},"2"}',
# -- output --
'{\n' +
' "1": {\n' +
' "1a": "1b"\n' +
' },\n' +
' "2"\n' +
'}')
bt(
'{a:{a:b},c}',
# -- output --
'{\n' +
' a: {\n' +
' a: b\n' +
' },\n' +
' c\n' +
'}')
bt(
'{[y[a]];keep_indent;}',
# -- output --
'{\n' +
' [y[a]];\n' +
' keep_indent;\n' +
'}')
bt(
'if (x) {y} else { if (x) {y}}',
# -- output --
'if (x) {\n' +
' y\n' +
'} else {\n' +
' if (x) {\n' +
' y\n' +
' }\n' +
'}')
bt(
'if (foo) one()\n' +
'two()\n' +
'three()')
bt(
'if (1 + foo() && bar(baz()) / 2) one()\n' +
'two()\n' +
'three()')
bt(
'if (1 + foo() && bar(baz()) / 2) one();\n' +
'two();\n' +
'three();')
bt(
'var a=1,b={bang:2},c=3;',
# -- output --
'var a = 1,\n' +
' b = {\n' +
' bang: 2\n' +
' },\n' +
' c = 3;')
bt(
'var a={bing:1},b=2,c=3;',
# -- output --
'var a = {\n' +
' bing: 1\n' +
' },\n' +
' b = 2,\n' +
' c = 3;')
# Issue #1896: Handle newlines with bitwise ~ operator
bt(
'if (foo) {\n' +
'var bar = 1;\n' +
'~bar ? 0 : 1\n' +
' }',
# -- output --
'if (foo) {\n' +
' var bar = 1;\n' +
' ~bar ? 0 : 1\n' +
'}')
def test_beautifier_unconverted(self):
test_fragment = self.decodesto
bt = self.bt
self.reset_options()
#============================================================
bt(None, "")
self.reset_options()
#============================================================
# Test user pebkac protection, converts dash names to underscored names
setattr(self.options, 'end-with-newline', True)
test_fragment(None, '\n')
self.reset_options()
#============================================================
# Test passing dictionary or tuple
self.options = {'end_with_newline': True, 'eol': '\r\n' }
test_fragment(None, '\r\n')
self.options = {'end-with-newline': True}
test_fragment(None, '\n')
self.options = {'end-with-newline': False}
test_fragment(None, '')
self.options = ( ('end-with-newline', True), ('eol', '\r') )
test_fragment(None, '\r')
self.reset_options()
#============================================================
self.options.indent_size = 1
self.options.indent_char = ' '
bt('{ one_char() }', "{\n one_char()\n}")
bt('var a,b=1,c=2', 'var a, b = 1,\n c = 2')
self.options.indent_size = 4
self.options.indent_char = ' '
bt('{ one_char() }', "{\n one_char()\n}")
self.options.indent_size = 1
self.options.indent_char = "\t"
bt('{ one_char() }', "{\n\tone_char()\n}")
bt('x = a ? b : c; x;', 'x = a ? b : c;\nx;')
#set to something else than it should change to, but with tabs on, should override
self.options.indent_size = 5
self.options.indent_char = ' '
self.options.indent_with_tabs = True
bt('{ one_char() }', "{\n\tone_char()\n}")
bt('x = a ? b : c; x;', 'x = a ? b : c;\nx;')
self.reset_options()
#============================================================
self.options.preserve_newlines = False
bt('var\na=dont_preserve_newlines;', 'var a = dont_preserve_newlines;')
# make sure the blank line between function definitions stays
# even when preserve_newlines = False
bt('function foo() {\n return 1;\n}\n\nfunction foo() {\n return 1;\n}')
bt('function foo() {\n return 1;\n}\nfunction foo() {\n return 1;\n}',
'function foo() {\n return 1;\n}\n\nfunction foo() {\n return 1;\n}'
)
bt('function foo() {\n return 1;\n}\n\n\nfunction foo() {\n return 1;\n}',
'function foo() {\n return 1;\n}\n\nfunction foo() {\n return 1;\n}'
)
self.options.preserve_newlines = True
bt('var\na=do_preserve_newlines;', 'var\n a = do_preserve_newlines;')
bt('if (foo) // comment\n{\n bar();\n}')
self.reset_options()
#============================================================
# START tests for brace positioning
# If this is ever supported, update tests for each brace style.
# test_fragment('return\n{', 'return\n{') # can't support this?, but that's an improbable and extreme case anyway.
self.options.brace_style = 'expand'
bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}')
bt('if(1){2}else{3}', "if (1)\n{\n 2\n}\nelse\n{\n 3\n}")
bt('try{a();}catch(b){c();}catch(d){}finally{e();}',
"try\n{\n a();\n}\ncatch (b)\n{\n c();\n}\ncatch (d)\n{}\nfinally\n{\n e();\n}")
bt('if(a){b();}else if(c) foo();',
"if (a)\n{\n b();\n}\nelse if (c) foo();")
bt("if (a) {\n// comment\n}else{\n// comment\n}",
"if (a)\n{\n // comment\n}\nelse\n{\n // comment\n}") # if/else statement with empty body
bt('if (x) {y} else { if (x) {y}}',
'if (x)\n{\n y\n}\nelse\n{\n if (x)\n {\n y\n }\n}')
bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}',
'if (a)\n{\n b;\n}\nelse\n{\n c;\n}')
test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}',
' /*\n * xx\n */\n // xx\n if (foo)\n {\n bar();\n }')
bt('if (foo)\n{}\nelse /regex/.test();')
test_fragment('if (foo) {', 'if (foo)\n{')
test_fragment('foo {', 'foo\n{')
test_fragment('return {', 'return {') # return needs the brace.
test_fragment('return /* inline */ {', 'return /* inline */ {')
test_fragment('return;\n{', 'return;\n{')
bt("throw {}")
bt("throw {\n foo;\n}")
bt('var foo = {}')
bt('function x() {\n foo();\n}zzz', 'function x()\n{\n foo();\n}\nzzz')
test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx')
bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}')
bt('var a = new function() {};')
bt('var a = new function a() {};', 'var a = new function a()\n{};')
bt('var a = new function()\n{};', 'var a = new function() {};')
bt('var a = new function a()\n{};')
bt('var a = new function a()\n {},\n b = new function b()\n {};')
bt("foo({\n 'a': 1\n},\n10);",
"foo(\n {\n 'a': 1\n },\n 10);")
bt('(["foo","bar"]).each(function(i) {return i;});',
'(["foo", "bar"]).each(function(i)\n{\n return i;\n});')
bt('(function(i) {return i;})();',
'(function(i)\n{\n return i;\n})();')
bt( "test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test(\n" +
"/*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"},\n" +
"/*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test(\n" +
" /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test( /*Argument 1*/\n" +
"{\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */\n" +
"{\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
self.options.brace_style = 'collapse'
bt('//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}')
bt('if(1){2}else{3}', "if (1) {\n 2\n} else {\n 3\n}")
bt('try{a();}catch(b){c();}catch(d){}finally{e();}',
"try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}")
bt('if(a){b();}else if(c) foo();',
"if (a) {\n b();\n} else if (c) foo();")
bt("if (a) {\n// comment\n}else{\n// comment\n}",
"if (a) {\n // comment\n} else {\n // comment\n}") # if/else statement with empty body
bt('if (x) {y} else { if (x) {y}}',
'if (x) {\n y\n} else {\n if (x) {\n y\n }\n}')
bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}',
'if (a) {\n b;\n} else {\n c;\n}')
test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}',
' /*\n * xx\n */\n // xx\n if (foo) {\n bar();\n }')
bt('if (foo) {} else /regex/.test();')
test_fragment('if (foo) {', 'if (foo) {')
test_fragment('foo {', 'foo {')
test_fragment('return {', 'return {') # return needs the brace.
test_fragment('return /* inline */ {', 'return /* inline */ {')
test_fragment('return;\n{', 'return;\n{')
bt("throw {}")
bt("throw {\n foo;\n}")
bt('var foo = {}')
bt('function x() {\n foo();\n}zzz', 'function x() {\n foo();\n}\nzzz')
test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx')
bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}')
bt('var a = new function() {};')
bt('var a = new function a() {};')
bt('var a = new function()\n{};', 'var a = new function() {};')
bt('var a = new function a()\n{};', 'var a = new function a() {};')
bt('var a = new function a()\n {},\n b = new function b()\n {};', 'var a = new function a() {},\n b = new function b() {};')
bt("foo({\n 'a': 1\n},\n10);",
"foo({\n 'a': 1\n },\n 10);")
bt('(["foo","bar"]).each(function(i) {return i;});',
'(["foo", "bar"]).each(function(i) {\n return i;\n});')
bt('(function(i) {return i;})();',
'(function(i) {\n return i;\n})();')
bt( "test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test(\n" +
"/*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"},\n" +
"/*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test(\n" +
" /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test( /*Argument 1*/\n" +
"{\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */\n" +
"{\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
self.options.brace_style = "end-expand"
bt('//case 1\nif (a == 1) {}\n//case 2\nelse if (a == 2) {}')
bt('if(1){2}else{3}', "if (1) {\n 2\n}\nelse {\n 3\n}")
bt('try{a();}catch(b){c();}catch(d){}finally{e();}',
"try {\n a();\n}\ncatch (b) {\n c();\n}\ncatch (d) {}\nfinally {\n e();\n}")
bt('if(a){b();}else if(c) foo();',
"if (a) {\n b();\n}\nelse if (c) foo();")
bt("if (a) {\n// comment\n}else{\n// comment\n}",
"if (a) {\n // comment\n}\nelse {\n // comment\n}") # if/else statement with empty body
bt('if (x) {y} else { if (x) {y}}',
'if (x) {\n y\n}\nelse {\n if (x) {\n y\n }\n}')
bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}',
'if (a) {\n b;\n}\nelse {\n c;\n}')
test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}',
' /*\n * xx\n */\n // xx\n if (foo) {\n bar();\n }')
bt('if (foo) {}\nelse /regex/.test();')
test_fragment('if (foo) {', 'if (foo) {')
test_fragment('foo {', 'foo {')
test_fragment('return {', 'return {') # return needs the brace.
test_fragment('return /* inline */ {', 'return /* inline */ {')
test_fragment('return;\n{', 'return;\n{')
bt("throw {}")
bt("throw {\n foo;\n}")
bt('var foo = {}')
bt('function x() {\n foo();\n}zzz', 'function x() {\n foo();\n}\nzzz')
test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx')
bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}')
bt('var a = new function() {};')
bt('var a = new function a() {};')
bt('var a = new function()\n{};', 'var a = new function() {};')
bt('var a = new function a()\n{};', 'var a = new function a() {};')
bt('var a = new function a()\n {},\n b = new function b()\n {};', 'var a = new function a() {},\n b = new function b() {};')
bt("foo({\n 'a': 1\n},\n10);",
"foo({\n 'a': 1\n },\n 10);")
bt('(["foo","bar"]).each(function(i) {return i;});',
'(["foo", "bar"]).each(function(i) {\n return i;\n});')
bt('(function(i) {return i;})();',
'(function(i) {\n return i;\n})();')
bt( "test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test(\n" +
"/*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"},\n" +
"/*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test(\n" +
" /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test( /*Argument 1*/\n" +
"{\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */\n" +
"{\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
self.options.brace_style = 'none'
bt('//case 1\nif (a == 1)\n{}\n//case 2\nelse if (a == 2)\n{}')
bt('if(1){2}else{3}', "if (1) {\n 2\n} else {\n 3\n}")
bt('try{a();}catch(b){c();}catch(d){}finally{e();}',
"try {\n a();\n} catch (b) {\n c();\n} catch (d) {} finally {\n e();\n}")
bt('if(a){b();}else if(c) foo();',
"if (a) {\n b();\n} else if (c) foo();")
bt("if (a) {\n// comment\n}else{\n// comment\n}",
"if (a) {\n // comment\n} else {\n // comment\n}") # if/else statement with empty body
bt('if (x) {y} else { if (x) {y}}',
'if (x) {\n y\n} else {\n if (x) {\n y\n }\n}')
bt('if (a)\n{\nb;\n}\nelse\n{\nc;\n}',
'if (a)\n{\n b;\n}\nelse\n{\n c;\n}')
test_fragment(' /*\n* xx\n*/\n// xx\nif (foo) {\n bar();\n}',
' /*\n * xx\n */\n // xx\n if (foo) {\n bar();\n }')
bt('if (foo)\n{}\nelse /regex/.test();')
test_fragment('if (foo) {')
test_fragment('foo {')
test_fragment('return {') # return needs the brace.
test_fragment('return /* inline */ {')
test_fragment('return;\n{')
bt("throw {}")
bt("throw {\n foo;\n}")
bt('var foo = {}')
bt('function x() {\n foo();\n}zzz', 'function x() {\n foo();\n}\nzzz')
test_fragment('a: do {} while (); xxx', 'a: do {} while ();\nxxx')
bt('{a: do {} while (); xxx}', '{\n a: do {} while ();xxx\n}')
bt('var a = new function() {};')
bt('var a = new function a() {};')
bt('var a = new function()\n{};', 'var a = new function() {};')
bt('var a = new function a()\n{};')
bt('var a = new function a()\n {},\n b = new function b()\n {};')
bt("foo({\n 'a': 1\n},\n10);",
"foo({\n 'a': 1\n },\n 10);")
bt('(["foo","bar"]).each(function(i) {return i;});',
'(["foo", "bar"]).each(function(i) {\n return i;\n});')
bt('(function(i) {return i;})();',
'(function(i) {\n return i;\n})();')
bt( "test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test(\n" +
"/*Argument 1*/ {\n" +
" 'Value1': '1'\n" +
"},\n" +
"/*Argument 2\n" +
" */ {\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test(\n" +
" /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
bt( "test( /*Argument 1*/\n" +
"{\n" +
" 'Value1': '1'\n" +
"}, /*Argument 2\n" +
" */\n" +
"{\n" +
" 'Value2': '2'\n" +
"});",
# expected
"test( /*Argument 1*/\n" +
" {\n" +
" 'Value1': '1'\n" +
" },\n" +
" /*Argument 2\n" +
" */\n" +
" {\n" +
" 'Value2': '2'\n" +
" });")
# END tests for brace position
self.reset_options()
#============================================================
self.options.preserve_newlines = True
bt("var a = 'foo' +\n 'bar';")
bt('"foo""bar""baz"', '"foo"\n"bar"\n"baz"')
bt("'foo''bar''baz'", "'foo'\n'bar'\n'baz'")
bt("{\n get foo() {}\n}")
bt("{\n var a = get\n foo();\n}")
bt("{\n set foo() {}\n}")
bt("{\n var a = set\n foo();\n}")
bt("var x = {\n get function()\n}")
bt("var x = {\n set function()\n}")
# According to my current research get/set have no special meaning outside of an object literal
bt("var x = set\n\na() {}", "var x = set\n\na() {}")
bt("var x = set\n\nfunction() {}", "var x = set\n\nfunction() {}")
bt('for () /abc/.test()')
bt('if (k) /aaa/m.test(v) && l();')
bt('switch (true) {\n case /swf/i.test(foo):\n bar();\n}')
bt('createdAt = {\n type: Date,\n default: Date.now\n}')
bt('switch (createdAt) {\n case a:\n Date,\n default:\n Date.now\n}')
self.reset_options()
#============================================================
def decodesto(self, input, expectation=None):
if expectation is None:
expectation = input
self.assertMultiLineEqual(
jsbeautifier.beautify(input, self.options), expectation)
# if the expected is different from input, run it again
# expected output should be unchanged when run twice.
if not expectation is None:
self.assertMultiLineEqual(
jsbeautifier.beautify(expectation, self.options), expectation)
if self.options is None or not isinstance(self.options, (dict, tuple)):
# Everywhere we do newlines, they should be replaced with opts.eol
self.options.eol = '\r\\n'
expectation = expectation.replace('\n', '\r\n')
self.options.disabled = True
self.assertMultiLineEqual(
jsbeautifier.beautify(input, self.options), input or '')
self.assertMultiLineEqual(
jsbeautifier.beautify('\n\n' + expectation, self.options), '\n\n' + expectation)
self.options.disabled = False;
self.assertMultiLineEqual(
jsbeautifier.beautify(input, self.options), expectation)
if input and input.find('\n') != -1:
input = input.replace('\n', '\r\n')
self.assertMultiLineEqual(
jsbeautifier.beautify(input, self.options), expectation)
# Ensure support for auto eol detection
self.options.eol = 'auto'
self.assertMultiLineEqual(
jsbeautifier.beautify(input, self.options), expectation)
self.options.eol = '\n'
def wrap(self, text):
return self.wrapregex.sub(' \\1', text)
def bt(self, input, expectation=None):
if expectation is None:
expectation = input
self.decodesto(input, expectation)
# If we set raw, input should be unchanged
self.options.test_output_raw = True
if self.options.end_with_newline:
self.decodesto(input, input)
self.options.test_output_raw = False
current_indent_size = None
if self.options.js and self.options.js['indent_size']:
current_indent_size = self.options.js['indent_size']
if not current_indent_size:
current_indent_size = self.options.indent_size
if current_indent_size == 4 and input:
wrapped_input = '{\n%s\n foo = bar;\n}' % self.wrap(input)
wrapped_expect = '{\n%s\n foo = bar;\n}' % self.wrap(expectation)
self.decodesto(wrapped_input, wrapped_expect)
# If we set raw, input should be unchanged
self.options.test_output_raw = True
if self.options.end_with_newline:
self.decodesto(wrapped_input, wrapped_input)
self.options.test_output_raw = False
if __name__ == '__main__':
unittest.main()
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/tests/testindentation.py 0000644 0001751 0000177 00000002607 14522301436 023351 0 ustar 00runner docker import re
import unittest
import jsbeautifier
class TestJSBeautifierIndentation(unittest.TestCase):
def test_tabs(self):
test_fragment = self.decodesto
self.options.indent_with_tabs = 1
test_fragment("{tabs()}", "{\n\ttabs()\n}")
def test_function_indent(self):
test_fragment = self.decodesto
self.options.indent_with_tabs = 1
self.options.keep_function_indentation = 1
test_fragment(
"var foo = function(){ bar() }();", "var foo = function() {\n\tbar()\n}();"
)
self.options.tabs = 1
self.options.keep_function_indentation = 0
test_fragment(
"var foo = function(){ baz() }();", "var foo = function() {\n\tbaz()\n}();"
)
def decodesto(self, input, expectation=None):
self.assertEqual(
jsbeautifier.beautify(input, self.options), expectation or input
)
@classmethod
def setUpClass(cls):
options = jsbeautifier.default_options()
options.indent_size = 4
options.indent_char = " "
options.preserve_newlines = True
options.jslint_happy = False
options.keep_array_indentation = False
options.brace_style = "collapse"
options.indent_level = 0
cls.options = options
cls.wrapregex = re.compile("^(.+)$", re.MULTILINE)
if __name__ == "__main__":
unittest.main()
././@PaxHeader 0000000 0000000 0000000 00000000033 00000000000 010211 x ustar 00 27 mtime=1699316581.318391
jsbeautifier-1.14.11/jsbeautifier/unpackers/ 0000755 0001751 0000177 00000000000 14522301545 020410 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/unpackers/__init__.py 0000644 0001751 0000177 00000004421 14522301436 022521 0 ustar 00runner docker #
# General code for JSBeautifier unpackers infrastructure. See README.specs
# written by Stefano Sanfilippo
#
"""General code for JSBeautifier unpackers infrastructure."""
import pkgutil
import re
from jsbeautifier.unpackers import evalbased
# NOTE: AT THE MOMENT, IT IS DEACTIVATED FOR YOUR SECURITY: it runs js!
BLACKLIST = ["jsbeautifier.unpackers.evalbased"]
class UnpackingError(Exception):
"""Badly packed source or general error. Argument is a
meaningful description."""
pass
def getunpackers():
"""Scans the unpackers dir, finds unpackers and add them to UNPACKERS list.
An unpacker will be loaded only if it is a valid python module (name must
adhere to naming conventions) and it is not blacklisted (i.e. inserted
into BLACKLIST."""
path = __path__
prefix = __name__ + "."
unpackers = []
interface = ["unpack", "detect", "PRIORITY"]
for _importer, modname, _ispkg in pkgutil.iter_modules(path, prefix):
if "tests" not in modname and modname not in BLACKLIST:
try:
module = __import__(modname, fromlist=interface)
except ImportError:
raise UnpackingError("Bad unpacker: %s" % modname)
else:
unpackers.append(module)
return sorted(unpackers, key=lambda mod: mod.PRIORITY)
UNPACKERS = getunpackers()
def run(source, evalcode=False):
"""Runs the applicable unpackers and return unpacked source as a string."""
for unpacker in [mod for mod in UNPACKERS if mod.detect(source)]:
source = unpacker.unpack(source)
if evalcode and evalbased.detect(source):
source = evalbased.unpack(source)
return source
def filtercomments(source):
"""NOT USED: strips trailing comments and put them at the top."""
trailing_comments = []
comment = True
while comment:
if re.search(r"^\s*\/\*", source):
comment = source[0, source.index("*/") + 2]
elif re.search(r"^\s*\/\/", source):
comment = re.search(r"^\s*\/\/", source).group(0)
else:
comment = None
if comment:
source = re.sub(r"^\s+", "", source[len(comment) :])
trailing_comments.append(comment)
return "\n".join(trailing_comments) + source
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/unpackers/evalbased.py 0000644 0001751 0000177 00000002225 14522301436 022710 0 ustar 00runner docker #
# Unpacker for eval() based packers, a part of javascript beautifier
# by Einar Lielmanis
#
# written by Stefano Sanfilippo
#
# usage:
#
# if detect(some_string):
# unpacked = unpack(some_string)
#
"""Unpacker for eval() based packers: runs JS code and returns result.
Works only if a JS interpreter (e.g. Mozilla's Rhino) is installed and
properly set up on host."""
from subprocess import PIPE, Popen
PRIORITY = 3
def detect(source):
"""Detects if source is likely to be eval() packed."""
return source.strip().lower().startswith("eval(function(")
def unpack(source):
"""Runs source and return resulting code."""
return jseval("print %s;" % source[4:]) if detect(source) else source
# In case of failure, we'll just return the original, without crashing on user.
def jseval(script):
"""Run code in the JS interpreter and return output."""
try:
interpreter = Popen(["js"], stdin=PIPE, stdout=PIPE)
except OSError:
return script
result, errors = interpreter.communicate(script)
if interpreter.poll() or errors:
return script
return result
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/unpackers/javascriptobfuscator.py 0000644 0001751 0000177 00000003376 14522301436 025230 0 ustar 00runner docker #
# simple unpacker/deobfuscator for scripts messed up with
# javascriptobfuscator.com
#
# written by Einar Lielmanis
# rewritten in Python by Stefano Sanfilippo
#
# Will always return valid javascript: if `detect()` is false, `code` is
# returned, unmodified.
#
# usage:
#
# if javascriptobfuscator.detect(some_string):
# some_string = javascriptobfuscator.unpack(some_string)
#
"""deobfuscator for scripts messed up with JavascriptObfuscator.com"""
import re
PRIORITY = 1
def smartsplit(code):
"""Split `code` at " symbol, only if it is not escaped."""
strings = []
pos = 0
while pos < len(code):
if code[pos] == '"':
word = "" # new word
pos += 1
while pos < len(code):
if code[pos] == '"':
break
if code[pos] == "\\":
word += "\\"
pos += 1
word += code[pos]
pos += 1
strings.append('"%s"' % word)
pos += 1
return strings
def detect(code):
"""Detects if `code` is JavascriptObfuscator.com packed."""
# prefer `is not` idiom, so that a true boolean is returned
return re.search(r"^var _0x[a-f0-9]+ ?\= ?\[", code) is not None
def unpack(code):
"""Unpacks JavascriptObfuscator.com packed code."""
if detect(code):
matches = re.search(r"var (_0x[a-f\d]+) ?\= ?\[(.*?)\];", code)
if matches:
variable = matches.group(1)
dictionary = smartsplit(matches.group(2))
code = code[len(matches.group(0)) :]
for key, value in enumerate(dictionary):
code = code.replace(r"%s[%s]" % (variable, key), value)
return code
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1699316510.0
jsbeautifier-1.14.11/jsbeautifier/unpackers/myobfuscate.py 0000644 0001751 0000177 00000005312 14522301436 023303 0 ustar 00runner docker #
# deobfuscator for scripts messed up with myobfuscate.com
# by Einar Lielmanis
#
# written by Stefano Sanfilippo
#
# usage:
#
# if detect(some_string):
# unpacked = unpack(some_string)
#
# CAVEAT by Einar Lielmanis
#
# You really don't want to obfuscate your scripts there: they're tracking
# your unpackings, your script gets turned into something like this,
# as of 2011-08-26:
#
# var _escape = 'your_script_escaped';
# var _111 = document.createElement('script');
# _111.src = 'http://api.www.myobfuscate.com/?getsrc=ok' +
# '&ref=' + encodeURIComponent(document.referrer) +
# '&url=' + encodeURIComponent(document.URL);
# var 000 = document.getElementsByTagName('head')[0];
# 000.appendChild(_111);
# document.write(unescape(_escape));
#
"""Deobfuscator for scripts messed up with MyObfuscate.com"""
import re
import base64
# Python 2 retrocompatibility
# pylint: disable=F0401
# pylint: disable=E0611
try:
from urllib import unquote
except ImportError:
from urllib.parse import unquote
from jsbeautifier.unpackers import UnpackingError
PRIORITY = 1
CAVEAT = """//
// Unpacker warning: be careful when using myobfuscate.com for your projects:
// scripts obfuscated by the free online version call back home.
//
"""
SIGNATURE = (
r'["\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F'
r"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x61\x62\x63\x64\x65"
r"\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75"
r"\x76\x77\x78\x79\x7A\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2B"
r'\x2F\x3D","","\x63\x68\x61\x72\x41\x74","\x69\x6E\x64\x65\x78'
r'\x4F\x66","\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","'
r'\x6C\x65\x6E\x67\x74\x68"]'
)
def detect(source):
"""Detects MyObfuscate.com packer."""
return SIGNATURE in source
def unpack(source):
"""Unpacks js code packed with MyObfuscate.com"""
if not detect(source):
return source
payload = unquote(_filter(source))
match = re.search(r"^var _escape\='