Add JSBeautify scripts
authorMiguel de Juana <miguel.dejuana@openbravo.com>
Mon, 09 May 2016 14:03:00 +0200
changeset 29450 098506f49242
parent 29449 58bacde3f953
child 29451 25cda173d4d8
Add JSBeautify scripts

- Add script to execute JSBeautifier
* Scripts to be executed in root project or for each module
* Scripts to be execute manually or when doing a commit
- Create one file to define js files to be taken into account for jslint and jsbeautify
- Define scripts as bash and add set -e for errors
modules/org.openbravo.client.kernel/jsbeautify/jsbeautifier.py
modules/org.openbravo.client.kernel/jsbeautify/jsbeautify
modules/org.openbravo.client.kernel/jsbeautify/jsbeautify-module
modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy
modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy-hg
modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy-module
modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy-module-hg
modules/org.openbravo.client.kernel/jscheck/jsfiles
modules/org.openbravo.client.kernel/jslint/jscheck
modules/org.openbravo.client.kernel/jslint/jscheck-hg
modules/org.openbravo.client.kernel/jslint/jscheck-module-hg
modules/org.openbravo.client.kernel/jslint/jslint
modules/org.openbravo.client.kernel/jslint/jslint-module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jsbeautifier.py	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,1089 @@
+#!/usr/bin/env python
+
+import sys
+import getopt
+import re
+
+#
+# Originally written by Einar Lielmanis et al.,
+# Conversion to python by Einar Lielmanis, einar@jsbeautifier.org,
+# MIT licence, enjoy.
+#
+# 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)
+
+
+class BeautifierOptions:
+    def __init__(self):
+        self.indent_size = 4
+        self.indent_char = ' '
+        self.preserve_newlines = True
+        self.max_preserve_newlines = 10.
+        self.jslint_happy = False
+        self.brace_style = 'collapse'
+        self.keep_array_indentation = False
+        self.indent_level = 0
+
+
+
+    def __repr__(self):
+        return \
+"""indent_size = %d
+indent_char = [%s]
+preserve_newlines = %s
+max_preserve_newlines = %d
+jslint_happy = %s
+brace_style = %s
+keep_array_indentation = %s
+indent_level = %d
+""" % ( self.indent_size,
+        self.indent_char,
+        self.preserve_newlines,
+        self.max_preserve_newlines,
+        self.jslint_happy,
+        self.brace_style,
+        self.keep_array_indentation,
+        self.indent_level)
+
+
+class BeautifierFlags:
+    def __init__(self, mode):
+        self.previous_mode = 'BLOCK'
+        self.mode = mode
+        self.var_line = False
+        self.var_line_tainted = False
+        self.var_line_reindented = False
+        self.in_html_comment = False
+        self.if_line = False
+        self.in_case = False
+        self.eat_next_space = False
+        self.indentation_baseline = -1
+        self.indentation_level = 0
+        self.ternary_depth = 0
+
+
+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() ):
+
+    if file_name == '-': # stdin
+        f = sys.stdin
+    else:
+        f = open(file_name)
+
+    b = Beautifier()
+    return b.beautify(''.join(f.readlines()), opts)
+
+
+def usage():
+
+    print("""Javascript beautifier (http://jsbeautifier.org/)
+
+Usage: jsbeautifier.py [options] <infile>
+
+    <infile> 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).
+ -d,  --disable-preserve-newlines  do not preserve existing line breaks.
+ -j,  --jslint-happy               more jslint-compatible output
+ -b,  --brace-style=collapse       brace style (collapse, expand, end-expand)
+ -k,  --keep-array-indentation     keep array indentation.
+
+Rarely needed options:
+
+ -l,  --indent-level=NUMBER        initial indentation level. (default 0).
+
+ -h,  --help, --usage              prints this help statement.
+
+""");
+
+
+
+
+
+
+class Beautifier:
+
+    def __init__(self, opts = default_options() ):
+
+        self.opts = opts
+        self.blank_state()
+
+    def blank_state(self):
+
+        # internal flags
+        self.flags = BeautifierFlags('BLOCK')
+        self.flag_store = []
+        self.wanted_newline = False
+        self.just_added_newline = False
+        self.do_block_just_closed = False
+
+
+        self.indent_string = self.opts.indent_char * self.opts.indent_size
+        self.last_word = ''              # last TK_WORD seen
+        self.last_type = 'TK_START_EXPR' # last token type
+        self.last_text = ''              # last token text
+        self.last_last_text = ''         # pre-last token text
+
+        self.input = None
+        self.output = []                 # formatted javascript gets built here
+
+        self.whitespace = ["\n", "\r", "\t", " "]
+        self.wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'
+        self.digits = '0123456789'
+        self.punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::'.split(' ');
+
+
+        # Words which always should start on a new line
+        self.line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',')
+        self.set_mode('BLOCK')
+
+        global parser_pos
+        parser_pos = 0
+
+
+    def beautify(self, s, opts = None ):
+
+        if opts != None:
+            self.opts = opts
+
+
+        if self.opts.brace_style not in ['expand', 'collapse', 'end-expand']:
+            raise(Exception('opts.brace_style must be "expand", "collapse" or "end-expand".'))
+
+        self.blank_state()
+
+        self.input = s
+
+        parser_pos = 0
+        while True:
+            token_text, token_type = self.get_next_token()
+            #print (token_text, token_type, self.flags.mode)
+            if token_type == 'TK_EOF':
+                break
+
+            handlers = {
+                'TK_START_EXPR': self.handle_start_expr,
+                'TK_END_EXPR': self.handle_end_expr,
+                'TK_START_BLOCK': self.handle_start_block,
+                'TK_END_BLOCK': self.handle_end_block,
+                'TK_WORD': self.handle_word,
+                'TK_SEMICOLON': self.handle_semicolon,
+                'TK_STRING': self.handle_string,
+                'TK_EQUALS': self.handle_equals,
+                'TK_OPERATOR': self.handle_operator,
+                'TK_BLOCK_COMMENT': self.handle_block_comment,
+                'TK_INLINE_COMMENT': self.handle_inline_comment,
+                'TK_COMMENT': self.handle_comment,
+                'TK_UNKNOWN': self.handle_unknown,
+            }
+
+            handlers[token_type](token_text)
+
+            self.last_last_text = self.last_text
+            self.last_type = token_type
+            self.last_text = token_text
+
+        sweet_code = re.sub('[\n ]+$', '', ''.join(self.output))
+        if self.opts.indent_level:
+            sweet_code = self.opts.indent_level * self.indent_string + sweet_code
+        return sweet_code
+
+
+
+    def trim_output(self, eat_newlines = False):
+        while len(self.output) \
+              and (
+                  self.output[-1] == ' '\
+                  or self.output[-1] == self.indent_string \
+                  or (eat_newlines and self.output[-1] in ['\n', '\r'])):
+            self.output.pop()
+
+
+    def is_array(self, mode):
+        return mode in ['[EXPRESSION]', '[INDENDED-EXPRESSION]']
+
+
+    def is_expression(self, mode):
+        return mode in ['[EXPRESSION]', '[INDENDED-EXPRESSION]', '(EXPRESSION)']
+
+
+    def append_newline_forced(self):
+        old_array_indentation = self.opts.keep_array_indentation
+        self.opts.keep_array_indentation = False
+        self.append_newline()
+        self.opts.keep_array_indentation = old_array_indentation
+
+    def append_newline(self, ignore_repeated = True):
+
+        self.flags.eat_next_space = False;
+
+        if self.opts.keep_array_indentation and self.is_array(self.flags.mode):
+            return
+
+        self.flags.if_line = False;
+        self.trim_output();
+
+        if len(self.output) == 0:
+            # no newline on start of file
+            return
+
+        if self.output[-1] != '\n' or not ignore_repeated:
+            self.just_added_newline = True
+            self.output.append('\n')
+
+        for i in range(self.flags.indentation_level + self.opts.indent_level):
+            self.output.append(self.indent_string)
+
+        if self.flags.var_line and self.flags.var_line_reindented:
+            if self.opts.indent_char == ' ':
+                # var_line always pushes 4 spaces, so that the variables would be one under another
+                self.output.append('    ')
+            else:
+                self.output.append(self.indent_string)
+
+
+    def append(self, s):
+        if s == ' ':
+            # make sure only single space gets drawn
+            if self.flags.eat_next_space:
+                self.flags.eat_next_space = False
+            elif len(self.output) and self.output[-1] not in [' ', '\n', self.indent_string]:
+                self.output.append(' ')
+        else:
+            self.just_added_newline = False
+            self.flags.eat_next_space = False
+            self.output.append(s)
+
+
+    def indent(self):
+        self.flags.indentation_level = self.flags.indentation_level + 1
+
+
+    def remove_indent(self):
+        if len(self.output) and self.output[-1] == self.indent_string:
+            self.output.pop()
+
+
+    def set_mode(self, mode):
+
+        prev = BeautifierFlags('BLOCK')
+
+        if self.flags:
+            self.flag_store.append(self.flags)
+            prev = self.flags
+
+        self.flags = BeautifierFlags(mode)
+
+        if len(self.flag_store) == 1:
+            self.flags.indentation_level = 0
+        else:
+            self.flags.indentation_level = prev.indentation_level
+            if prev.var_line and prev.var_line_reindented:
+                self.flags.indentation_level = self.flags.indentation_level + 1
+        self.flags.previous_mode = prev.mode
+
+
+    def restore_mode(self):
+        self.do_block_just_closed = self.flags.mode == 'DO_BLOCK'
+        if len(self.flag_store) > 0:
+            self.flags = self.flag_store.pop()
+
+
+    def get_next_token(self):
+
+        global parser_pos
+
+        self.n_newlines = 0
+
+        if parser_pos >= len(self.input):
+            return '', 'TK_EOF'
+
+        self.wanted_newline = False;
+        c = self.input[parser_pos]
+        parser_pos += 1
+
+        keep_whitespace = self.opts.keep_array_indentation and self.is_array(self.flags.mode)
+
+        if keep_whitespace:
+            # slight mess to allow nice preservation of array indentation and reindent that correctly
+            # first time when we get to the arrays:
+            # var a = [
+            # ....'something'
+            # we make note of whitespace_count = 4 into flags.indentation_baseline
+            # so we know that 4 whitespaces in original source match indent_level of reindented source
+            #
+            # and afterwards, when we get to
+            #    'something,
+            # .......'something else'
+            # we know that this should be indented to indent_level + (7 - indentation_baseline) spaces
+
+            whitespace_count = 0
+            while c in self.whitespace:
+                if c == '\n':
+                    self.trim_output()
+                    self.output.append('\n')
+                    self.just_added_newline = True
+                    whitespace_count = 0
+                elif c == '\t':
+                    whitespace_count += 4
+                elif c == '\r':
+                    pass
+                else:
+                    whitespace_count += 1
+
+                if parser_pos >= len(self.input):
+                    return '', 'TK_EOF'
+
+                c = self.input[parser_pos]
+                parser_pos += 1
+
+            if self.flags.indentation_baseline == -1:
+
+                self.flags.indentation_baseline = whitespace_count
+
+            if self.just_added_newline:
+                for i in range(self.flags.indentation_level + 1):
+                    self.output.append(self.indent_string)
+
+                if self.flags.indentation_baseline != -1:
+                    for i in range(whitespace_count - self.flags.indentation_baseline):
+                        self.output.append(' ')
+
+        else: # not keep_whitespace
+            while c in self.whitespace:
+                if c == '\n':
+                    if self.opts.max_preserve_newlines == 0 or self.opts.max_preserve_newlines > self.n_newlines:
+                        self.n_newlines += 1
+
+                if parser_pos >= len(self.input):
+                    return '', 'TK_EOF'
+
+                c = self.input[parser_pos]
+                parser_pos += 1
+
+            if self.opts.preserve_newlines and self.n_newlines > 1:
+                for i in range(self.n_newlines):
+                    self.append_newline(i == 0)
+                    self.just_added_newline = True
+
+            self.wanted_newline = self.n_newlines > 0
+
+
+        if c in self.wordchar:
+            if parser_pos < len(self.input):
+                while self.input[parser_pos] in self.wordchar:
+                    c = c + self.input[parser_pos]
+                    parser_pos += 1
+                    if parser_pos == len(self.input):
+                        break
+
+            # small and surprisingly unugly hack for 1E-10 representation
+            if parser_pos != len(self.input) and self.input[parser_pos] in '+-' \
+               and re.match('^[0-9]+[Ee]$', c):
+
+                sign = self.input[parser_pos]
+                parser_pos += 1
+                t = self.get_next_token()
+                c += sign + t[0]
+                return c, 'TK_WORD'
+
+            if c == 'in': # in is an operator, need to hack
+                return c, 'TK_OPERATOR'
+
+            if self.wanted_newline and \
+               self.last_type != 'TK_OPERATOR' and\
+               self.last_type != 'TK_EQUALS' and\
+               not self.flags.if_line and \
+               (self.opts.preserve_newlines or self.last_text != 'var'):
+                self.append_newline()
+
+            return c, 'TK_WORD'
+
+        if c in '([':
+            return c, 'TK_START_EXPR'
+
+        if c in ')]':
+            return c, 'TK_END_EXPR'
+
+        if c == '{':
+            return c, 'TK_START_BLOCK'
+
+        if c == '}':
+            return c, 'TK_END_BLOCK'
+
+        if c == ';':
+            return c, 'TK_SEMICOLON'
+
+        if c == '/':
+            comment = ''
+            inline_comment = True
+            comment_mode = 'TK_INLINE_COMMENT'
+            if self.input[parser_pos] == '*': # peek /* .. */ comment
+                parser_pos += 1
+                if parser_pos < len(self.input):
+                    while not (self.input[parser_pos] == '*' and \
+                               parser_pos + 1 < len(self.input) and \
+                               self.input[parser_pos + 1] == '/')\
+                          and parser_pos < len(self.input):
+                        c = self.input[parser_pos]
+                        comment += c
+                        if c in '\r\n':
+                            comment_mode = 'TK_BLOCK_COMMENT'
+                        parser_pos += 1
+                        if parser_pos >= len(self.input):
+                            break
+                parser_pos += 2
+                return '/*' + comment + '*/', comment_mode
+            if self.input[parser_pos] == '/': # peek // comment
+                comment = c
+                while self.input[parser_pos] not in '\r\n':
+                    comment += self.input[parser_pos]
+                    parser_pos += 1
+                    if parser_pos >= len(self.input):
+                        break
+                parser_pos += 1
+                if self.wanted_newline:
+                    self.append_newline()
+                return comment, 'TK_COMMENT'
+
+
+
+        if c == "'" or c == '"' or \
+           (c == '/' and ((self.last_type == 'TK_WORD' and self.last_text in ['return', 'do']) or \
+                          (self.last_type in ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK', 'TK_END_BLOCK', 'TK_OPERATOR',
+                                              'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON']))):
+             sep = c
+             esc = False
+             resulting_string = c
+             in_char_class = False
+
+             if parser_pos < len(self.input):
+                if sep == '/':
+                    # handle regexp
+                    in_char_class = False
+                    while esc or in_char_class or self.input[parser_pos] != sep:
+                        resulting_string += self.input[parser_pos]
+                        if not esc:
+                            esc = self.input[parser_pos] == '\\'
+                            if self.input[parser_pos] == '[':
+                                in_char_class = True
+                            elif self.input[parser_pos] == ']':
+                                in_char_class = False
+                        else:
+                            esc = False
+                        parser_pos += 1
+                        if parser_pos >= len(self.input):
+                            # incomplete regex when end-of-file reached
+                            # bail out with what has received so far
+                            return resulting_string, 'TK_STRING'
+                else:
+                    # handle string
+                    while esc or self.input[parser_pos] != sep:
+                        resulting_string += self.input[parser_pos]
+                        if not esc:
+                            esc = self.input[parser_pos] == '\\'
+                        else:
+                            esc = False
+                        parser_pos += 1
+                        if parser_pos >= len(self.input):
+                            # incomplete string when end-of-file reached
+                            # bail out with what has received so far
+                            return resulting_string, 'TK_STRING'
+
+
+             parser_pos += 1
+             resulting_string += sep
+             if sep == '/':
+                 # regexps may have modifiers /regexp/MOD, so fetch those too
+                 while parser_pos < len(self.input) and self.input[parser_pos] in self.wordchar:
+                     resulting_string += self.input[parser_pos]
+                     parser_pos += 1
+             return resulting_string, 'TK_STRING'
+
+        if c == '#':
+
+            # she-bang
+            if len(self.output) == 0 and len(self.input) > 1 and self.input[parser_pos] == '!':
+                resulting_string = c
+                while parser_pos < len(self.input) and c != '\n':
+                    c = self.input[parser_pos]
+                    resulting_string += c
+                    parser_pos += 1
+                self.output.append(resulting_string.strip() + "\n")
+                self.append_newline()
+                return self.get_next_token()
+
+
+            # 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 parser_pos < len(self.input) and self.input[parser_pos] in self.digits:
+                while True:
+                    c = self.input[parser_pos]
+                    sharp += c
+                    parser_pos += 1
+                    if parser_pos >= len(self.input)  or c == '#' or c == '=':
+                        break
+            if c == '#' or parser_pos >= len(self.input):
+                pass
+            elif self.input[parser_pos] == '[' and self.input[parser_pos + 1] == ']':
+                sharp += '[]'
+                parser_pos += 2
+            elif self.input[parser_pos] == '{' and self.input[parser_pos + 1] == '}':
+                sharp += '{}'
+                parser_pos += 2
+            return sharp, 'TK_WORD'
+
+        if c == '<' and self.input[parser_pos - 1 : parser_pos + 3] == '<!--':
+            parser_pos += 3
+            self.flags.in_html_comment = True
+            return '<!--', 'TK_COMMENT'
+
+        if c == '-' and self.flags.in_html_comment and self.input[parser_pos - 1 : parser_pos + 2] == '-->':
+            self.flags.in_html_comment = False
+            parser_pos += 2
+            if self.wanted_newline:
+                self.append_newline()
+            return '-->', 'TK_COMMENT'
+
+        if c in self.punct:
+            while parser_pos < len(self.input) and c + self.input[parser_pos] in self.punct:
+                c += self.input[parser_pos]
+                parser_pos += 1
+                if parser_pos >= len(self.input):
+                    break
+            if c == '=':
+                return c, 'TK_EQUALS'
+            else:
+                return c, 'TK_OPERATOR'
+        return c, 'TK_UNKNOWN'
+
+
+
+    def handle_start_expr(self, token_text):
+        if token_text == '[':
+            if self.last_type == 'TK_WORD' or self.last_text == ')':
+                if self.last_text in self.line_starters:
+                    self.append(' ')
+                self.set_mode('(EXPRESSION)')
+                self.append(token_text)
+                return
+
+            if self.flags.mode in ['[EXPRESSION]', '[INDENTED-EXPRESSION]']:
+                if self.last_last_text == ']' and self.last_text == ',':
+                    # ], [ goes to a new line
+                    if self.flags.mode == '[EXPRESSION]':
+                        self.flags.mode = '[INDENTED-EXPRESSION]'
+                        if not self.opts.keep_array_indentation:
+                            self.indent()
+                    self.set_mode('[EXPRESSION]')
+                    if not self.opts.keep_array_indentation:
+                        self.append_newline()
+                elif self.last_text == '[':
+                    if self.flags.mode == '[EXPRESSION]':
+                        self.flags.mode = '[INDENTED-EXPRESSION]'
+                        if not self.opts.keep_array_indentation:
+                            self.indent()
+                    self.set_mode('[EXPRESSION]')
+
+                    if not self.opts.keep_array_indentation:
+                        self.append_newline()
+                else:
+                    self.set_mode('[EXPRESSION]')
+            else:
+                self.set_mode('[EXPRESSION]')
+        else:
+            self.set_mode('(EXPRESSION)')
+
+
+        if self.last_text == ';' or self.last_type == 'TK_START_BLOCK':
+            self.append_newline()
+        elif self.last_type in ['TK_END_EXPR', 'TK_START_EXPR', 'TK_END_BLOCK'] or self.last_text == '.':
+            # do nothing on (( and )( and ][ and ]( and .(
+            pass
+        elif self.last_type not in ['TK_WORD', 'TK_OPERATOR']:
+            self.append(' ')
+        elif self.last_word == 'function' or self.last_word == 'typeof':
+            # function() vs function (), typeof() vs typeof ()
+            if self.opts.jslint_happy:
+                self.append(' ')
+        elif self.last_text in self.line_starters or self.last_text == 'catch':
+            self.append(' ')
+
+        self.append(token_text)
+
+
+    def handle_end_expr(self, token_text):
+        if token_text == ']':
+            if self.opts.keep_array_indentation:
+                if self.last_text == '}':
+                    self.remove_indent()
+                    self.append(token_text)
+                    self.restore_mode()
+                    return
+            else:
+                if self.flags.mode == '[INDENTED-EXPRESSION]':
+                    if self.last_text == ']':
+                        self.restore_mode()
+                        self.append_newline()
+                        self.append(token_text)
+                        return
+        self.restore_mode()
+        self.append(token_text)
+
+
+    def handle_start_block(self, token_text):
+        if self.last_word == 'do':
+            self.set_mode('DO_BLOCK')
+        else:
+            self.set_mode('BLOCK')
+
+        if self.opts.brace_style == 'expand':
+            if self.last_type != 'TK_OPERATOR':
+                if self.last_text in ['return', '=']:
+                    self.append(' ')
+                else:
+                    self.append_newline(True)
+
+            self.append(token_text)
+            self.indent()
+        else:
+            if self.last_type not in ['TK_OPERATOR', 'TK_START_EXPR']:
+                if self.last_type == 'TK_START_BLOCK':
+                    self.append_newline()
+                else:
+                    self.append(' ')
+            else:
+                # if TK_OPERATOR or TK_START_EXPR
+                if self.is_array(self.flags.previous_mode) and self.last_text == ',':
+                    if self.last_last_text == '}':
+                        self.append(' ')
+                    else:
+                        self.append_newline()
+            self.indent()
+            self.append(token_text)
+
+
+
+
+
+    def handle_end_block(self, token_text):
+        self.restore_mode()
+        if self.opts.brace_style == 'expand':
+            if self.last_text != '{':
+                self.append_newline()
+        else:
+            if self.last_type == 'TK_START_BLOCK':
+                if self.just_added_newline:
+                    self.remove_indent()
+                else:
+                    # {}
+                    self.trim_output()
+            else:
+                if self.is_array(self.flags.mode) and self.opts.keep_array_indentation:
+                    self.opts.keep_array_indentation = False
+                    self.append_newline()
+                    self.opts.keep_array_indentation = True
+                else:
+                    self.append_newline()
+
+        self.append(token_text)
+
+
+    def handle_word(self, token_text):
+        if self.do_block_just_closed:
+            self.append(' ')
+            self.append(token_text)
+            self.append(' ')
+            self.do_block_just_closed = False
+            return
+
+        if token_text == 'function':
+
+            if self.flags.var_line:
+                self.flags.var_line_reindented = True
+            if (self.just_added_newline or self.last_text == ';') and self.last_text != '{':
+                # make sure there is a nice clean space of at least one blank line
+                # before a new function definition
+                have_newlines = self.n_newlines
+                if not self.just_added_newline:
+                    have_newlines = 0
+                if not self.opts.preserve_newlines:
+                    have_newlines = 1
+                for i in range(2 - have_newlines):
+                    self.append_newline(False)
+
+        if token_text in ['case', 'default']:
+            if self.last_text == ':':
+                self.remove_indent()
+            else:
+                self.flags.indentation_level -= 1
+                self.append_newline()
+                self.flags.indentation_level += 1
+            self.append(token_text)
+            self.flags.in_case = True
+            return
+
+        prefix = 'NONE'
+
+        if self.last_type == 'TK_END_BLOCK':
+            if token_text not in ['else', 'catch', 'finally']:
+                prefix = 'NEWLINE'
+            else:
+                if self.opts.brace_style in ['expand', 'end-expand']:
+                    prefix = 'NEWLINE'
+                else:
+                    prefix = 'SPACE'
+                    self.append(' ')
+        elif self.last_type == 'TK_SEMICOLON' and self.flags.mode in ['BLOCK', 'DO_BLOCK']:
+            prefix = 'NEWLINE'
+        elif self.last_type == 'TK_SEMICOLON' and self.is_expression(self.flags.mode):
+            prefix = 'SPACE'
+        elif self.last_type == 'TK_STRING':
+            prefix = 'NEWLINE'
+        elif self.last_type == 'TK_WORD':
+            if self.last_text == 'else':
+                # eat newlines between ...else *** some_op...
+                # won't preserve extra newlines in this place (if any), but don't care that much
+                self.trim_output(True);
+            prefix = 'SPACE'
+        elif self.last_type == 'TK_START_BLOCK':
+            prefix = 'NEWLINE'
+        elif self.last_type == 'TK_END_EXPR':
+            self.append(' ')
+            prefix = 'NEWLINE'
+
+        if self.flags.if_line and self.last_type == 'TK_END_EXPR':
+            self.flags.if_line = False
+
+        if token_text in self.line_starters:
+            if self.last_text == 'else':
+                prefix = 'SPACE'
+            else:
+                prefix = 'NEWLINE'
+
+        if token_text in ['else', 'catch', 'finally']:
+            if self.last_type != 'TK_END_BLOCK' \
+               or self.opts.brace_style == 'expand' \
+               or self.opts.brace_style == 'end-expand':
+                self.append_newline()
+            else:
+                self.trim_output(True)
+                self.append(' ')
+        elif prefix == 'NEWLINE':
+            if token_text == 'function' and (self.last_type == 'TK_START_EXPR' or self.last_text in '=,'):
+                # no need to force newline on "function" -
+                #   (function...
+                pass
+            elif token_text == 'function' and self.last_text == 'new':
+                self.append(' ')
+            elif self.last_text in ['return', 'throw']:
+                # no newline between return nnn
+                self.append(' ')
+            elif self.last_type != 'TK_END_EXPR':
+                if (self.last_type != 'TK_START_EXPR' or token_text != 'var') and self.last_text != ':':
+                    # no need to force newline on VAR -
+                    # for (var x = 0...
+                    if token_text == 'if' and self.last_word == 'else' and self.last_text != '{':
+                        self.append(' ')
+                    else:
+                        self.flags.var_line = False
+                        self.flags.var_line_reindented = False
+                        self.append_newline()
+            elif token_text in self.line_starters and self.last_text != ')':
+                self.flags.var_line = False
+                self.flags.var_line_reindented = False
+                self.append_newline()
+        elif self.is_array(self.flags.mode) and self.last_text == ',' and self.last_last_text == '}':
+                self.append_newline() # }, in lists get a newline
+        elif prefix == 'SPACE':
+            self.append(' ')
+
+
+        self.append(token_text)
+        self.last_word = token_text
+
+        if token_text == 'var':
+            self.flags.var_line = True
+            self.flags.var_line_reindented = False
+            self.flags.var_line_tainted = False
+
+
+        if token_text == 'if':
+            self.flags.if_line = True
+
+        if token_text == 'else':
+            self.flags.if_line = False
+
+
+    def handle_semicolon(self, token_text):
+        self.append(token_text)
+        self.flags.var_line = False
+        self.flags.var_line_reindented = False
+        if self.flags.mode == 'OBJECT':
+            # OBJECT mode is weird and doesn't get reset too well.
+            self.flags.mode = 'BLOCK'
+
+
+    def handle_string(self, token_text):
+        if self.last_type in ['TK_START_BLOCK', 'TK_END_BLOCK', 'TK_SEMICOLON']:
+            self.append_newline()
+        elif self.last_type == 'TK_WORD':
+            self.append(' ')
+
+        self.append(token_text)
+
+
+    def handle_equals(self, token_text):
+        if self.flags.var_line:
+            # just got an '=' in a var-line, different line breaking rules will apply
+            self.flags.var_line_tainted = True
+
+        self.append(' ')
+        self.append(token_text)
+        self.append(' ')
+
+
+    def handle_operator(self, token_text):
+        space_before = True
+        space_after = True
+
+        if self.flags.var_line and token_text == ',' and self.is_expression(self.flags.mode):
+            # do not break on comma, for ( var a = 1, b = 2
+            self.flags.var_line_tainted = False
+
+        if self.flags.var_line and token_text == ',':
+            if self.flags.var_line_tainted:
+                self.append(token_text)
+                self.flags.var_line_reindented = True
+                self.flags.var_line_tainted = False
+                self.append_newline()
+                return
+            else:
+                self.flags.var_line_tainted = False
+
+        if self.last_text in ['return', 'throw']:
+            # return had a special handling in TK_WORD
+            self.append(' ')
+            self.append(token_text)
+            return
+
+        if token_text == ':' and self.flags.in_case:
+            self.append(token_text)
+            self.append_newline()
+            self.flags.in_case = False
+            return
+
+        if token_text == '::':
+            # no spaces around the exotic namespacing syntax operator
+            self.append(token_text)
+            return
+
+        if token_text == ',':
+            if self.flags.var_line:
+                if self.flags.var_line_tainted:
+                    # This never happens, as it's handled previously, right?
+                    self.append(token_text)
+                    self.append_newline()
+                    self.flags.var_line_tainted = False
+                else:
+                    self.append(token_text)
+                    self.append(' ')
+            elif self.last_type == 'TK_END_BLOCK' and self.flags.mode != '(EXPRESSION)':
+                self.append(token_text)
+                if self.flags.mode == 'OBJECT' and self.last_text == '}':
+                    self.append_newline()
+                else:
+                    self.append(' ')
+            else:
+                if self.flags.mode == 'OBJECT':
+                    self.append(token_text)
+                    self.append_newline()
+                else:
+                    # EXPR or DO_BLOCK
+                    self.append(token_text)
+                    self.append(' ')
+            # comma handled
+            return
+        elif token_text in ['--', '++', '!'] \
+                or (token_text in ['+', '-'] \
+                    and self.last_type in ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) \
+                or self.last_text in self.line_starters:
+
+            space_before = False
+            space_after = False
+
+            if self.last_text == ';' and self.is_expression(self.flags.mode):
+                # for (;; ++i)
+                #         ^^
+                space_before = True
+
+            if self.last_type == 'TK_WORD' and self.last_text in self.line_starters:
+                space_before = True
+
+            if self.flags.mode == 'BLOCK' and self.last_text in ['{', ';']:
+                # { foo: --i }
+                # foo(): --bar
+                self.append_newline()
+
+        elif token_text == '.':
+            # decimal digits or object.property
+            space_before = False
+
+        elif token_text == ':':
+            if self.flags.ternary_depth == 0:
+                self.flags.mode = 'OBJECT'
+                space_before = False
+            else:
+                self.flags.ternary_depth -= 1
+        elif token_text == '?':
+            self.flags.ternary_depth += 1
+
+        if space_before:
+            self.append(' ')
+
+        self.append(token_text)
+
+        if space_after:
+            self.append(' ')
+
+
+
+    def handle_block_comment(self, token_text):
+
+        lines = token_text.replace('\x0d', '').split('\x0a')
+        # all lines start with an asterisk? that's a proper box comment
+        if not any(l for l in lines[1:] if (l.lstrip())[0] != '*'):
+            self.append_newline()
+            self.append(lines[0])
+            for line in lines[1:]:
+                self.append_newline()
+                self.append(' ' + line.strip())
+        else:
+            # simple block comment: leave intact
+            if len(lines) > 1:
+                # multiline comment starts on a new line
+                self.append_newline()
+                self.trim_output()
+            else:
+                # single line /* ... */ comment stays on the same line
+                self.append(' ')
+            for line in lines:
+                self.append(line)
+                self.append('\n')
+        self.append_newline()
+
+
+    def handle_inline_comment(self, token_text):
+        self.append(' ')
+        self.append(token_text)
+        if self.is_expression(self.flags.mode):
+            self.append(' ')
+        else:
+            self.append_newline_forced()
+
+
+    def handle_comment(self, token_text):
+        if self.wanted_newline:
+            self.append_newline()
+        else:
+            self.append(' ')
+
+        self.append(token_text)
+        self.append_newline_forced()
+
+
+    def handle_unknown(self, token_text):
+        if self.last_text in ['return', 'throw']:
+            self.append(' ')
+
+        self.append(token_text)
+
+
+
+
+
+def main():
+
+    argv = sys.argv[1:]
+
+    try:
+        opts, args = getopt.getopt(argv, "s:c:djbkil:h", ['indent-size=','indent-char=', 'disable-preserve-newlines',
+                                                          'jslint-happy', 'brace-style=',
+                                                          'keep-array-indentation', 'indent-level=', 'help',
+                                                          'usage', 'stdin'])
+    except getopt.GetoptError:
+        usage()
+        sys.exit(2)
+
+    js_options = default_options()
+
+    file = None
+    if len(args) == 1:
+        file = args[0]
+
+    for opt, arg in opts:
+        if opt in ('--keep-array-indentation', '-k'):
+            js_options.keep_array_indentation = True
+        if 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 ('--disable-preserve_newlines', '-d'):
+            js_options.preserve_newlines = False
+        elif opt in ('--jslint-happy', '-j'):
+            js_options.jslint_happy = True
+        elif opt in ('--brace-style', '-b'):
+            js_options.brace_style = arg
+        elif opt in ('--indent-level', '-l'):
+            js_options.indent_level = int(arg)
+        elif opt in ('--stdin', '-i'):
+            file = '-'
+        elif opt in ('--help', '--usage', '--h'):
+            return usage()
+
+    if file == None:
+        return usage()
+    else:
+        print(beautify_file(file, js_options))
+
+
+
+if __name__ == "__main__":
+    main()
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jsbeautify	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+# Mercurial pre-commit hook for jsbeautify
+
+changedfile=$1
+replaceparam=$2
+./modules/org.openbravo.client.kernel/jsbeautify/jsbeautifier.py --indent-size=2 --jslint-happy "$changedfile" > "$changedfile.beautified"
+if ! diff -Z "$changedfile" "$changedfile.beautified" >/dev/null ; then
+  if [ "$replaceparam" != "replace" ] ; then
+    echo "Beautify Error --> Please, beautify $changedfile";
+    rm -rf "$changedfile.beautified"
+    export ERROR="1"
+  else
+    perl -pe 'chop if eof' "$changedfile.beautified" > "$changedfile"
+    echo "Beautify --> File beautified: $changedfile";
+  fi
+fi
+rm -rf "$changedfile.beautified"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jsbeautify-module	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+# Mercurial pre-commit hook for jsbeautify
+
+changedfile=$1
+replaceparam=$2
+../org.openbravo.client.kernel/jsbeautify/jsbeautifier.py --indent-size=2 --jslint-happy "$changedfile" > "$changedfile.beautified"
+if ! diff -Z "$changedfile" "$changedfile.beautified" >/dev/null ; then
+  if [ "$replaceparam" != "replace" ] ; then
+    echo "Beautify Error --> Please, beautify $changedfile";
+    rm -rf "$changedfile.beautified"
+    export ERROR="1"
+  else
+    perl -pe 'chop if eof' "$changedfile.beautified" > "$changedfile"
+    echo "Beautify --> File beautified: $changedfile";
+  fi
+fi
+rm -rf "$changedfile.beautified"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+replaceparam=$1
+if [ "$replaceparam" != "replace" ] ; then
+ echo "Performing jsbeautify check on all js resources"
+else
+ echo "Performing jsbeautify replacement on all js resources"
+fi
+
+files=$(./modules/org.openbravo.client.kernel/jscheck/jsfiles ./modules)
+
+for changedfile in echo $files; do
+  if [ -f "$changedfile" -a -n "$(echo $changedfile | awk '/.js$/')" ]; then
+    source ./modules/org.openbravo.client.kernel/jsbeautify/jsbeautify $changedfile $replaceparam
+  fi
+done
+exit $ERROR
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy-hg	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+# Mercurial pre-commit hook for jsbeautify
+
+replaceparam=$1
+if [ "$replaceparam" != "replace" ] ; then
+ echo "Performing jsbeautify check on all js resources"
+else
+ echo "Performing jsbeautify replacement on all js resources"
+fi
+
+for changedfile in $(hg st -ma)
+do
+  if [ -f "$changedfile" -a -n "$(echo $changedfile | awk '/.js$/ && ! /^web/')" ]; then
+    source ./modules/org.openbravo.client.kernel/jsbeautify/jsbeautify $changedfile $replaceparam
+  fi
+done
+exit $ERROR
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy-module	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+replaceparam=$1
+if [ "$replaceparam" != "replace" ] ; then
+ echo "Performing jsbeautify check on all js resources"
+else
+ echo "Performing jsbeautify replacement on all js resources"
+fi
+
+files=$(../org.openbravo.client.kernel/jscheck/jsfiles ./)
+
+for changedfile in echo $(hg st -ma)
+do
+  if [ -f "$changedfile" -a -n "$(echo $changedfile | awk '/.js$/')" ]; then
+  source ../org.openbravo.client.kernel/jsbeautify/jsbeautify-module $changedfile $replaceparam
+  fi
+done
+exit $ERROR
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jsbeautify/jscheck-btfy-module-hg	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+# Mercurial pre-commit hook for jsbeautify
+replaceparam=$1
+if [ "$replaceparam" != "replace" ] ; then
+ echo "Performing jsbeautify check on all js resources"
+else
+ echo "Performing jsbeautify replacement on all js resources"
+fi
+
+for changedfile in $(hg st -ma)
+do
+  if [ -f "$changedfile" -a -n "$(echo $changedfile | awk '/.js$/')" ]; then
+    source ../org.openbravo.client.kernel/jsbeautify/jsbeautify-module $changedfile $replaceparam
+  fi
+done
+exit $ERROR
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.client.kernel/jscheck/jsfiles	Mon May 09 14:03:00 2016 +0200
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Find js files
+
+find $1 -name '*.js' -and ! -path '*isomorphic*' \
+-and ! -path '*qunit*' -and ! -path '*docs*' \
+-and ! -path '*LAB*' -and ! -path '*benchmark*' \
+-and ! -path '*unittest*' \
+-and ! -path '*postest*' \
+-and ! -path '*xmla4js*' \
+-and ! -path '*VAADIN*' \
+-and ! -path '*saiku*' \
+-and ! -path '*libs*' \
+-and ! -path '*lib*' \
+-and ! -path '*enyo*' \
+-and ! -path '*smartclient*' \
+-and ! -path '*scopeleaks*' \
+-and ! -path '*BigDecimal*'
\ No newline at end of file
--- a/modules/org.openbravo.client.kernel/jslint/jscheck	Fri May 06 10:09:56 2016 +0200
+++ b/modules/org.openbravo.client.kernel/jslint/jscheck	Mon May 09 14:03:00 2016 +0200
@@ -1,16 +1,4 @@
-#!/bin/sh
-echo "Performing jslint check on all js resources"
-find ./modules -name '*.js' -and ! -path '*isomorphic*' \
--and ! -path '*qunit*' -and ! -path '*docs*' \
--and ! -path '*LAB*' -and ! -path '*benchmark*' \
--and ! -path '*unittest*' \
--and ! -path '*postest*' \
--and ! -path '*xmla4js*' \
--and ! -path '*VAADIN*' \
--and ! -path '*saiku*' \
--and ! -path '*libs*' \
--and ! -path '*lib*' \
--and ! -path '*enyo*' \
--and ! -path '*smartclient*' \
--and ! -path '*scopeleaks*' \
--and ! -path '*BigDecimal*' | xargs ./modules/org.openbravo.client.kernel/jslint/jslint || exit 1
+#!/bin/bash
+
+files=$(./modules/org.openbravo.client.kernel/jscheck/jsfiles ./modules)
+echo $files | xargs ./modules/org.openbravo.client.kernel/jslint/jslint || exit 1
--- a/modules/org.openbravo.client.kernel/jslint/jscheck-hg	Fri May 06 10:09:56 2016 +0200
+++ b/modules/org.openbravo.client.kernel/jslint/jscheck-hg	Mon May 09 14:03:00 2016 +0200
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # Mercurial pretxncommit hook
 echo "Performing jslint check on modified js resources"
--- a/modules/org.openbravo.client.kernel/jslint/jscheck-module-hg	Fri May 06 10:09:56 2016 +0200
+++ b/modules/org.openbravo.client.kernel/jslint/jscheck-module-hg	Mon May 09 14:03:00 2016 +0200
@@ -1,17 +1,17 @@
-#!/bin/sh
+#!/bin/bash
 
 # Mercurial pretxncommit hook
 echo "Performing jslint check on modified js resources"
 for i in $(hg log -r $HG_NODE --template '{files}')
 do
-	if [[ $i == *vendor* ]]
-	then
-	  echo "Skipping " $i;
-	else
-	  if [ -f "$i" -a -n "$(echo $i | awk '/.js$/')" ]
-	  then
-	    ../org.openbravo.client.kernel/jslint/jslint-module $i || exit 1
-		fi
+  if [[ $i == *vendor* ]]
+  then
+    echo "Skipping " $i;
+  else
+    if [ -f "$i" -a -n "$(echo $i | awk '/.js$/')" ]
+    then
+      ../org.openbravo.client.kernel/jslint/jslint-module $i || exit 1
+	fi
   fi
 done
 
--- a/modules/org.openbravo.client.kernel/jslint/jslint	Fri May 06 10:09:56 2016 +0200
+++ b/modules/org.openbravo.client.kernel/jslint/jslint	Mon May 09 14:03:00 2016 +0200
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # --browser doesn't work properly in jslint4java 1.4.7
 # adding the global available functions manually: window, unscape, top, alert, escape
--- a/modules/org.openbravo.client.kernel/jslint/jslint-module	Fri May 06 10:09:56 2016 +0200
+++ b/modules/org.openbravo.client.kernel/jslint/jslint-module	Mon May 09 14:03:00 2016 +0200
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # --browser doesn't work properly in jslint4java 1.4.7
 # adding the global available functions manually: window, unscape, top, alert, escape
@@ -7,4 +7,4 @@
 echo "Checking --> $@"
 java -jar ../org.openbravo.client.kernel/lib/runtime/jslint4java-1.4.7.jar \
  --browser --evil --continue --undef \
- --predef window,unescape,escape,top,alert,isc,OB,ok,test,module,expect,same,stop,start,asyncTest,equals,BigDecimal "$@"
+ --predef window,unescape,escape,top,alert,isc,OB,ok,test,module,expect,same,stop,start,asyncTest,equals,BigDecimal "$@"
\ No newline at end of file