Browse Source

代码美化工具用web worker实现

zxlie 7 years ago
parent
commit
3882922b70
5 changed files with 1315 additions and 1268 deletions
  1. 29 24
      apps/code-beautify/automatic.js
  2. 178 151
      apps/code-beautify/beautify-css.js
  3. 1090 1075
      apps/code-beautify/beautify.js
  4. 17 17
      apps/code-beautify/index.js
  5. 1 1
      apps/manifest.json

+ 29 - 24
apps/code-beautify/automatic.js

@@ -3,9 +3,31 @@ module.exports = (() => {
     /**
     /**
      * 代码美化
      * 代码美化
      */
      */
-    let format = (fileType, source) => {
+    let format = (fileType, source, callback) => {
+
+        let beauty = txtResult => {
+
+            txtResult = txtResult.replace(/>/g, '&gt;').replace(/</g, '&lt;');
+            txtResult = '<pre class="brush: ' + fileType.toLowerCase() + ';toolbar:false;">' + txtResult + '</pre>';
+            document.body.innerHTML = txtResult;
+
+            // 代码高亮
+            let map = {
+                core: '../static/vendor/syntaxhighlighter/shCore.js',
+                Javascript: '../static/vendor/syntaxhighlighter/shBrushJScript.js',
+                CSS: '../static/vendor/syntaxhighlighter/shBrushCss.js'
+            };
+
+            Tarp.require(map.core, true).then(SH => {
+                Tarp.require(map[fileType], true).then(SH => {
+                    SH.defaults['toolbar'] = false;
+                    SH.highlight();
+                });
+            });
+
+            callback && callback();
+        };
 
 
-        let txtResult = '';
         switch (fileType) {
         switch (fileType) {
             case 'Javascript':
             case 'Javascript':
                 let opts = {
                 let opts = {
@@ -22,32 +44,14 @@ module.exports = (() => {
                     wrap_line_length: "120"
                     wrap_line_length: "120"
                 };
                 };
                 Tarp.require('../code-beautify/beautify.js');
                 Tarp.require('../code-beautify/beautify.js');
-                txtResult = js_beautify(source, opts);
+                js_beautify(source, opts, resp => beauty(resp));
                 break;
                 break;
             case 'CSS':
             case 'CSS':
                 Tarp.require('../code-beautify/beautify-css.js');
                 Tarp.require('../code-beautify/beautify-css.js');
-                txtResult = css_beautify(source);
+                css_beautify(source, {}, resp => beauty(resp));
                 break;
                 break;
         }
         }
 
 
-        txtResult = txtResult.replace(/>/g, '&gt;').replace(/</g, '&lt;');
-        txtResult = '<pre class="brush: ' + fileType.toLowerCase() + ';toolbar:false;">' + txtResult + '</pre>';
-        document.body.innerHTML = txtResult;
-
-        // 代码高亮
-        let map = {
-            core: '../static/vendor/syntaxhighlighter/shCore.js',
-            Javascript: '../static/vendor/syntaxhighlighter/shBrushJScript.js',
-            CSS: '../static/vendor/syntaxhighlighter/shBrushCss.js'
-        };
-
-        Tarp.require(map.core, true).then(SH => {
-            Tarp.require(map[fileType], true).then(SH => {
-                SH.defaults['toolbar'] = false;
-                SH.highlight();
-            });
-        });
-
     };
     };
 
 
     /**
     /**
@@ -78,8 +82,9 @@ module.exports = (() => {
         tipsBar.find('button.yes').click((evt) => {
         tipsBar.find('button.yes').click((evt) => {
             tipsBar.find('button.yes,button.no').hide();
             tipsBar.find('button.yes,button.no').hide();
             $('<span class="doing">正在努力,请稍后...</span>').insertBefore(tipsBar.find('button.yes'));
             $('<span class="doing">正在努力,请稍后...</span>').insertBefore(tipsBar.find('button.yes'));
-            format(fileType, source);
-            $(document.body).removeClass('show-tipsbar').addClass('show-beautified');
+            format(fileType, source,()=>{
+                $(document.body).removeClass('show-tipsbar').addClass('show-beautified');
+            });
         });
         });
 
 
         tipsBar.find('a.forbid').click((evt) => {
         tipsBar.find('a.forbid').click((evt) => {

+ 178 - 151
apps/code-beautify/beautify-css.js

@@ -53,190 +53,217 @@
 // http://www.w3.org/TR/CSS21/syndata.html#tokenization
 // http://www.w3.org/TR/CSS21/syndata.html#tokenization
 // http://www.w3.org/TR/css3-syntax/
 // http://www.w3.org/TR/css3-syntax/
 
 
-(function() {
-    function css_beautify(source_text, options) {
-        options = options || {};
-        var indentSize = options.indent_size || 4;
-        var indentCharacter = options.indent_char || ' ';
-
-        // compatibility
-        if (typeof indentSize === "string") {
-            indentSize = parseInt(indentSize, 10);
-        }
+(function () {
 
 
+    function css_beautify(source_text, options, callback) {
+        "use strict";
 
 
-        // tokenizer
-        var whiteRe = /^\s+$/;
-        var wordRe = /[\w$\-_]/;
+        // 用webwork的方式来进行格式化,效率更高
+        let worker = new Worker(URL.createObjectURL(new Blob(["(" + beautifyWebWorker.toString() + ")()"], {type: 'text/javascript'})));
+        worker.onmessage = function (evt) {
+            callback && callback(evt.data);
+        };
+        worker.postMessage({
+            source_text: source_text,
+            options: options
+        });
+    }
 
 
-        var pos = -1, ch;
-        function next() {
-            ch = source_text.charAt(++pos);
-            return ch;
-        }
-        function peek() {
-            return source_text.charAt(pos+1);
-        }
-        function eatString(comma) {
-            var start = pos;
-            while(next()){
-                if (ch === "\\"){
-                    next();
-                    next();
-                } else if (ch === comma) {
-                    break;
-                } else if (ch === "\n") {
-                    break;
-                }
+    function beautifyWebWorker() {
+        function Beautifier(source_text, options) {
+            options = options || {};
+            var indentSize = options.indent_size || 4;
+            var indentCharacter = options.indent_char || ' ';
+
+            // compatibility
+            if (typeof indentSize === "string") {
+                indentSize = parseInt(indentSize, 10);
             }
             }
-            return source_text.substring(start, pos + 1);
-        }
 
 
-        function eatWhitespace() {
-            var start = pos;
-            while (whiteRe.test(peek())) {
-                pos++;
+
+            // tokenizer
+            var whiteRe = /^\s+$/;
+            var wordRe = /[\w$\-_]/;
+
+            var pos = -1, ch;
+
+            function next() {
+                ch = source_text.charAt(++pos);
+                return ch;
             }
             }
-            return pos !== start;
-        }
 
 
-        function skipWhitespace() {
-            var start = pos;
-            do{
-            }while (whiteRe.test(next()));
-            return pos !== start + 1;
-        }
+            function peek() {
+                return source_text.charAt(pos + 1);
+            }
 
 
-        function eatComment() {
-            var start = pos;
-            next();
-            while (next()) {
-                if (ch === "*" && peek() === "/") {
-                    pos ++;
-                    break;
+            function eatString(comma) {
+                var start = pos;
+                while (next()) {
+                    if (ch === "\\") {
+                        next();
+                        next();
+                    } else if (ch === comma) {
+                        break;
+                    } else if (ch === "\n") {
+                        break;
+                    }
                 }
                 }
+                return source_text.substring(start, pos + 1);
             }
             }
 
 
-            return source_text.substring(start, pos + 1);
-        }
+            function eatWhitespace() {
+                var start = pos;
+                while (whiteRe.test(peek())) {
+                    pos++;
+                }
+                return pos !== start;
+            }
 
 
+            function skipWhitespace() {
+                var start = pos;
+                do {
+                } while (whiteRe.test(next()));
+                return pos !== start + 1;
+            }
 
 
-        function lookBack(str) {
-            return source_text.substring(pos-str.length, pos).toLowerCase() === str;
-        }
+            function eatComment() {
+                var start = pos;
+                next();
+                while (next()) {
+                    if (ch === "*" && peek() === "/") {
+                        pos++;
+                        break;
+                    }
+                }
 
 
-        // printer
-        var indentString = source_text.match(/^[\r\n]*[\t ]*/)[0];
-        var singleIndent = Array(indentSize + 1).join(indentCharacter);
-        var indentLevel = 0;
-        function indent() {
-            indentLevel++;
-            indentString += singleIndent;
-        }
-        function outdent() {
-            indentLevel--;
-            indentString = indentString.slice(0, -indentSize);
-        }
+                return source_text.substring(start, pos + 1);
+            }
 
 
-        var print = {};
-        print["{"] = function(ch) {
-            print.singleSpace();
-            output.push(ch);
-            print.newLine();
-        };
-        print["}"] = function(ch) {
-            print.newLine();
-            output.push(ch);
-            print.newLine();
-        };
 
 
-        print.newLine = function(keepWhitespace) {
-            if (!keepWhitespace) {
-                while (whiteRe.test(output[output.length - 1])) {
-                    output.pop();
-                }
+            function lookBack(str) {
+                return source_text.substring(pos - str.length, pos).toLowerCase() === str;
             }
             }
 
 
-            if (output.length) {
-                output.push('\n');
+            // printer
+            var indentString = source_text.match(/^[\r\n]*[\t ]*/)[0];
+            var singleIndent = Array(indentSize + 1).join(indentCharacter);
+            var indentLevel = 0;
+
+            function indent() {
+                indentLevel++;
+                indentString += singleIndent;
             }
             }
+
+            function outdent() {
+                indentLevel--;
+                indentString = indentString.slice(0, -indentSize);
+            }
+
+            var print = {};
+            print["{"] = function (ch) {
+                print.singleSpace();
+                output.push(ch);
+                print.newLine();
+            };
+            print["}"] = function (ch) {
+                print.newLine();
+                output.push(ch);
+                print.newLine();
+            };
+
+            print.newLine = function (keepWhitespace) {
+                if (!keepWhitespace) {
+                    while (whiteRe.test(output[output.length - 1])) {
+                        output.pop();
+                    }
+                }
+
+                if (output.length) {
+                    output.push('\n');
+                }
+                if (indentString) {
+                    output.push(indentString);
+                }
+            };
+            print.singleSpace = function () {
+                if (output.length && !whiteRe.test(output[output.length - 1])) {
+                    output.push(' ');
+                }
+            };
+            var output = [];
             if (indentString) {
             if (indentString) {
                 output.push(indentString);
                 output.push(indentString);
             }
             }
-        };
-        print.singleSpace = function() {
-            if (output.length && !whiteRe.test(output[output.length - 1])) {
-                output.push(' ');
-            }
-        };
-        var output = [];
-        if (indentString) {
-            output.push(indentString);
-        }
-        /*_____________________--------------------_____________________*/
+            /*_____________________--------------------_____________________*/
 
 
-        while(true) {
-            var isAfterSpace = skipWhitespace();
+            while (true) {
+                var isAfterSpace = skipWhitespace();
 
 
-            if (!ch) {
-                break;
-            }
+                if (!ch) {
+                    break;
+                }
 
 
 
 
-            if (ch === '{') {
-                indent();
-                print["{"](ch);
-            } else if (ch === '}') {
-                outdent();
-                print["}"](ch);
-            } else if (ch === '"' || ch === '\'') {
-                output.push(eatString(ch));
-            } else if (ch === ';') {
-                output.push(ch, '\n', indentString);
-            } else if (ch === '/' && peek() === '*') { // comment
-                print.newLine();
-                output.push(eatComment(), "\n", indentString);
-            } else if (ch === '(') { // may be a url
-                if (lookBack("url")) {
-                  output.push(ch);
-                  eatWhitespace();
-                  if (next()) {
-                    if (ch !== ')' && ch !== '"' && ch !== '\'') {
-                        output.push(eatString(')'));
+                if (ch === '{') {
+                    indent();
+                    print["{"](ch);
+                } else if (ch === '}') {
+                    outdent();
+                    print["}"](ch);
+                } else if (ch === '"' || ch === '\'') {
+                    output.push(eatString(ch));
+                } else if (ch === ';') {
+                    output.push(ch, '\n', indentString);
+                } else if (ch === '/' && peek() === '*') { // comment
+                    print.newLine();
+                    output.push(eatComment(), "\n", indentString);
+                } else if (ch === '(') { // may be a url
+                    if (lookBack("url")) {
+                        output.push(ch);
+                        eatWhitespace();
+                        if (next()) {
+                            if (ch !== ')' && ch !== '"' && ch !== '\'') {
+                                output.push(eatString(')'));
+                            } else {
+                                pos--;
+                            }
+                        }
                     } else {
                     } else {
-                        pos--;
+                        if (isAfterSpace) {
+                            print.singleSpace();
+                        }
+                        output.push(ch);
+                        eatWhitespace();
                     }
                     }
-                  }
-                } else {
-                  if (isAfterSpace) {
-                      print.singleSpace();
-                  }
-                  output.push(ch);
-                  eatWhitespace();
-                }
-            } else if (ch === ')') {
-                output.push(ch);
-            } else if (ch === ',') {
-                eatWhitespace();
-                output.push(ch);
-                print.singleSpace();
-            } else if (ch === ']') {
-                output.push(ch);
-            }  else if (ch === '[' || ch === '=') { // no whitespace before or after
-                eatWhitespace();
-                output.push(ch);
-            } else {
-                if (isAfterSpace) {
+                } else if (ch === ')') {
+                    output.push(ch);
+                } else if (ch === ',') {
+                    eatWhitespace();
+                    output.push(ch);
                     print.singleSpace();
                     print.singleSpace();
-                }
+                } else if (ch === ']') {
+                    output.push(ch);
+                } else if (ch === '[' || ch === '=') { // no whitespace before or after
+                    eatWhitespace();
+                    output.push(ch);
+                } else {
+                    if (isAfterSpace) {
+                        print.singleSpace();
+                    }
 
 
-                output.push(ch);
+                    output.push(ch);
+                }
             }
             }
-        }
 
 
 
 
-        var sweetCode = output.join('').replace(/[\n ]+$/, '');
-        return sweetCode;
+            var sweetCode = output.join('').replace(/[\n ]+$/, '');
+            return sweetCode;
+        }
+
+        self.onmessage = function (evt) {
+            var result = Beautifier(evt.data.source_text, evt.data.options);
+            self.postMessage(result);
+        };
     }
     }
 
 
     module.exports.css_beautify = window.css_beautify = css_beautify;
     module.exports.css_beautify = window.css_beautify = css_beautify;

+ 1090 - 1075
apps/code-beautify/beautify.js

@@ -83,1368 +83,1383 @@
 */
 */
 
 
 
 
-(function() {
-    function js_beautify(js_source_text, options) {
+(function () {
+    function js_beautify(js_source_text, options, callback) {
         "use strict";
         "use strict";
-        var beautifier = new Beautifier(js_source_text, options);
-        return beautifier.beautify();
-    }
 
 
-    function Beautifier(js_source_text, options) {
-        "use strict";
-        var input, output, token_text, token_type, last_type, last_last_text, indent_string;
-        var flags, previous_flags, flag_store;
-        var whitespace, wordchar, punct, parser_pos, line_starters, digits;
-        var prefix;
-        var wanted_newline, n_newlines, output_wrapped, output_space_before_token, whitespace_before_token;
-        var input_length;
-        var handlers, MODE, opt;
-        var preindent_string = '';
-
-        whitespace = "\n\r\t ".split('');
-        wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
-        digits = '0123456789'.split('');
-
-        punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::';
-        punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers
-        punct = punct.split(' ');
-
-        // words which should always start on new line.
-        line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
-
-        MODE = {
-            BlockStatement: 'BlockStatement', // 'BLOCK'
-            Statement: 'Statement', // 'STATEMENT'
-            ObjectLiteral: 'ObjectLiteral', // 'OBJECT',
-            ArrayLiteral: 'ArrayLiteral', //'[EXPRESSION]',
-            ForInitializer: 'ForInitializer', //'(FOR-EXPRESSION)',
-            Conditional: 'Conditional', //'(COND-EXPRESSION)',
-            Expression: 'Expression' //'(EXPRESSION)'
+        // 用webwork的方式来进行格式化,效率更高
+        let worker = new Worker(URL.createObjectURL(new Blob(["(" + beautifyWebWorker.toString() + ")()"], {type: 'text/javascript'})));
+        worker.onmessage = function (evt) {
+            callback && callback(evt.data);
         };
         };
+        worker.postMessage({
+            js_source_text: js_source_text,
+            options: options
+        });
+    }
 
 
-        handlers = {
-            'TK_START_EXPR': handle_start_expr,
-            'TK_END_EXPR': handle_end_expr,
-            'TK_START_BLOCK': handle_start_block,
-            'TK_END_BLOCK': handle_end_block,
-            'TK_WORD': handle_word,
-            'TK_SEMICOLON': handle_semicolon,
-            'TK_STRING': handle_string,
-            'TK_EQUALS': handle_equals,
-            'TK_OPERATOR': handle_operator,
-            'TK_COMMA': handle_comma,
-            'TK_BLOCK_COMMENT': handle_block_comment,
-            'TK_INLINE_COMMENT': handle_inline_comment,
-            'TK_COMMENT': handle_comment,
-            'TK_DOT': handle_dot,
-            'TK_UNKNOWN': handle_unknown
-        };
+    var beautifyWebWorker = function () {
+        function Beautifier(js_source_text, options) {
+            "use strict";
+            var input, output, token_text, token_type, last_type, last_last_text, indent_string;
+            var flags, previous_flags, flag_store;
+            var whitespace, wordchar, punct, parser_pos, line_starters, digits;
+            var prefix;
+            var wanted_newline, n_newlines, output_wrapped, output_space_before_token, whitespace_before_token;
+            var input_length;
+            var handlers, MODE, opt;
+            var preindent_string = '';
+
+            whitespace = "\n\r\t ".split('');
+            wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
+            digits = '0123456789'.split('');
+
+            punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::';
+            punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers
+            punct = punct.split(' ');
+
+            // words which should always start on new line.
+            line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
+
+            MODE = {
+                BlockStatement: 'BlockStatement', // 'BLOCK'
+                Statement: 'Statement', // 'STATEMENT'
+                ObjectLiteral: 'ObjectLiteral', // 'OBJECT',
+                ArrayLiteral: 'ArrayLiteral', //'[EXPRESSION]',
+                ForInitializer: 'ForInitializer', //'(FOR-EXPRESSION)',
+                Conditional: 'Conditional', //'(COND-EXPRESSION)',
+                Expression: 'Expression' //'(EXPRESSION)'
+            };
 
 
-        function create_flags(flags_base, mode) {
-            return {
-                mode: mode,
-                last_text: flags_base ? flags_base.last_text : '', // last token text
-                last_word: flags_base ? flags_base.last_word : '', // last 'TK_WORD' passed
-                var_line: false,
-                var_line_tainted: false,
-                var_line_reindented: false,
-                in_html_comment: false,
-                multiline_array: false,
-                if_block: false,
-                do_block: false,
-                do_while: false,
-                in_case_statement: false, // switch(..){ INSIDE HERE }
-                in_case: false, // we're on the exact line with "case 0:"
-                case_body: false, // the indented case-action block
-                indentation_level: (flags_base ? flags_base.indentation_level + ((flags_base.var_line && flags_base.var_line_reindented) ? 1 : 0) : 0),
-                ternary_depth: 0
+            handlers = {
+                'TK_START_EXPR': handle_start_expr,
+                'TK_END_EXPR': handle_end_expr,
+                'TK_START_BLOCK': handle_start_block,
+                'TK_END_BLOCK': handle_end_block,
+                'TK_WORD': handle_word,
+                'TK_SEMICOLON': handle_semicolon,
+                'TK_STRING': handle_string,
+                'TK_EQUALS': handle_equals,
+                'TK_OPERATOR': handle_operator,
+                'TK_COMMA': handle_comma,
+                'TK_BLOCK_COMMENT': handle_block_comment,
+                'TK_INLINE_COMMENT': handle_inline_comment,
+                'TK_COMMENT': handle_comment,
+                'TK_DOT': handle_dot,
+                'TK_UNKNOWN': handle_unknown
             };
             };
-        }
 
 
-        // Some interpreters have unexpected results with foo = baz || bar;
-        options = options ? options : {};
-        opt = {};
+            function create_flags(flags_base, mode) {
+                return {
+                    mode: mode,
+                    last_text: flags_base ? flags_base.last_text : '', // last token text
+                    last_word: flags_base ? flags_base.last_word : '', // last 'TK_WORD' passed
+                    var_line: false,
+                    var_line_tainted: false,
+                    var_line_reindented: false,
+                    in_html_comment: false,
+                    multiline_array: false,
+                    if_block: false,
+                    do_block: false,
+                    do_while: false,
+                    in_case_statement: false, // switch(..){ INSIDE HERE }
+                    in_case: false, // we're on the exact line with "case 0:"
+                    case_body: false, // the indented case-action block
+                    indentation_level: (flags_base ? flags_base.indentation_level + ((flags_base.var_line && flags_base.var_line_reindented) ? 1 : 0) : 0),
+                    ternary_depth: 0
+                };
+            }
+
+            // Some interpreters have unexpected results with foo = baz || bar;
+            options = options ? options : {};
+            opt = {};
+
+            // compatibility
+            if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) {
+                options.jslint_happy = options.space_after_anon_function;
+            }
+            if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
+                opt.brace_style = options.braces_on_own_line ? "expand" : "collapse";
+            }
+            opt.brace_style = options.brace_style ? options.brace_style : (opt.brace_style ? opt.brace_style : "collapse");
+
+            opt.indent_size = options.indent_size ? parseInt(options.indent_size, 10) : 4;
+            opt.indent_char = options.indent_char ? options.indent_char : ' ';
+            opt.preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
+            opt.break_chained_methods = (options.break_chained_methods === undefined) ? false : options.break_chained_methods;
+            opt.max_preserve_newlines = (options.max_preserve_newlines === undefined) ? 0 : parseInt(options.max_preserve_newlines, 10);
+            opt.jslint_happy = (options.jslint_happy === undefined) ? false : options.jslint_happy;
+            opt.keep_array_indentation = (options.keep_array_indentation === undefined) ? false : options.keep_array_indentation;
+            opt.space_before_conditional = (options.space_before_conditional === undefined) ? true : options.space_before_conditional;
+            opt.unescape_strings = (options.unescape_strings === undefined) ? false : options.unescape_strings;
+            opt.wrap_line_length = (options.wrap_line_length === undefined) ? 0 : parseInt(options.wrap_line_length, 10);
+
+            //----------------------------------
+            indent_string = '';
+            while (opt.indent_size > 0) {
+                indent_string += opt.indent_char;
+                opt.indent_size -= 1;
+            }
+
+            while (js_source_text && (js_source_text.charAt(0) === ' ' || js_source_text.charAt(0) === '\t')) {
+                preindent_string += js_source_text.charAt(0);
+                js_source_text = js_source_text.substring(1);
+            }
+            input = js_source_text;
+            // cache the source's length.
+            input_length = js_source_text.length;
+
+            last_type = 'TK_START_BLOCK'; // last token type
+            last_last_text = ''; // pre-last token text
+            output = [];
+            output_wrapped = false;
+            output_space_before_token = false;
+            whitespace_before_token = [];
 
 
-        // compatibility
-        if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) {
-            options.jslint_happy = options.space_after_anon_function;
-        }
-        if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
-            opt.brace_style = options.braces_on_own_line ? "expand" : "collapse";
-        }
-        opt.brace_style = options.brace_style ? options.brace_style : (opt.brace_style ? opt.brace_style : "collapse");
-
-        opt.indent_size = options.indent_size ? parseInt(options.indent_size, 10) : 4;
-        opt.indent_char = options.indent_char ? options.indent_char : ' ';
-        opt.preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
-        opt.break_chained_methods = (options.break_chained_methods === undefined) ? false : options.break_chained_methods;
-        opt.max_preserve_newlines = (options.max_preserve_newlines === undefined) ? 0 : parseInt(options.max_preserve_newlines, 10);
-        opt.jslint_happy = (options.jslint_happy === undefined) ? false : options.jslint_happy;
-        opt.keep_array_indentation = (options.keep_array_indentation === undefined) ? false : options.keep_array_indentation;
-        opt.space_before_conditional= (options.space_before_conditional === undefined) ? true : options.space_before_conditional;
-        opt.unescape_strings = (options.unescape_strings === undefined) ? false : options.unescape_strings;
-        opt.wrap_line_length = (options.wrap_line_length === undefined) ? 0 : parseInt(options.wrap_line_length, 10);
-
-        //----------------------------------
-        indent_string = '';
-        while (opt.indent_size > 0) {
-            indent_string += opt.indent_char;
-            opt.indent_size -= 1;
-        }
+            // Stack of parsing/formatting states, including MODE.
+            // We tokenize, parse, and output in an almost purely a forward-only stream of token input
+            // and formatted output.  This makes the beautifier less accurate than full parsers
+            // but also far more tolerant of syntax errors.
+            //
+            // For example, the default mode is MODE.BlockStatement. If we see a '{' we push a new frame of type
+            // MODE.BlockStatement on the the stack, even though it could be object literal.  If we later
+            // encounter a ":", we'll switch to to MODE.ObjectLiteral.  If we then see a ";",
+            // most full parsers would die, but the beautifier gracefully falls back to
+            // MODE.BlockStatement and continues on.
+            flag_store = [];
+            set_mode(MODE.BlockStatement);
 
 
-        while (js_source_text && (js_source_text.charAt(0) === ' ' || js_source_text.charAt(0) === '\t')) {
-            preindent_string += js_source_text.charAt(0);
-            js_source_text = js_source_text.substring(1);
-        }
-        input = js_source_text;
-        // cache the source's length.
-        input_length = js_source_text.length;
-
-        last_type = 'TK_START_BLOCK'; // last token type
-        last_last_text = ''; // pre-last token text
-        output = [];
-        output_wrapped = false;
-        output_space_before_token = false;
-        whitespace_before_token = [];
-
-        // Stack of parsing/formatting states, including MODE.
-        // We tokenize, parse, and output in an almost purely a forward-only stream of token input
-        // and formatted output.  This makes the beautifier less accurate than full parsers
-        // but also far more tolerant of syntax errors.
-        //
-        // For example, the default mode is MODE.BlockStatement. If we see a '{' we push a new frame of type
-        // MODE.BlockStatement on the the stack, even though it could be object literal.  If we later
-        // encounter a ":", we'll switch to to MODE.ObjectLiteral.  If we then see a ";",
-        // most full parsers would die, but the beautifier gracefully falls back to
-        // MODE.BlockStatement and continues on.
-        flag_store = [];
-        set_mode(MODE.BlockStatement);
-
-        parser_pos = 0;
-
-        this.beautify = function () {
-            /*jshint onevar:true */
-            var t, i, keep_whitespace, sweet_code;
-
-            while (true) {
-                t = get_next_token();
-                token_text = t[0];
-                token_type = t[1];
-
-                if (token_type === 'TK_EOF') {
-                    break;
-                }
-
-                keep_whitespace = opt.keep_array_indentation && is_array(flags.mode);
-
-                if (keep_whitespace) {
-                    for (i = 0; i < n_newlines; i += 1) {
-                        print_newline(true);
-                    }
-                } else {
-                    wanted_newline = n_newlines > 0;
-                    if (opt.max_preserve_newlines && n_newlines > opt.max_preserve_newlines) {
-                        n_newlines = opt.max_preserve_newlines;
+            parser_pos = 0;
+
+            this.beautify = function () {
+                /*jshint onevar:true */
+                var t, i, keep_whitespace, sweet_code;
+
+                while (true) {
+                    t = get_next_token();
+                    token_text = t[0];
+                    token_type = t[1];
+
+                    if (token_type === 'TK_EOF') {
+                        break;
                     }
                     }
 
 
-                    if (opt.preserve_newlines) {
-                        if (n_newlines > 1) {
-                            print_newline();
-                            for (i = 1; i < n_newlines; i += 1) {
-                                print_newline(true);
+                    keep_whitespace = opt.keep_array_indentation && is_array(flags.mode);
+
+                    if (keep_whitespace) {
+                        for (i = 0; i < n_newlines; i += 1) {
+                            print_newline(true);
+                        }
+                    } else {
+                        wanted_newline = n_newlines > 0;
+                        if (opt.max_preserve_newlines && n_newlines > opt.max_preserve_newlines) {
+                            n_newlines = opt.max_preserve_newlines;
+                        }
+
+                        if (opt.preserve_newlines) {
+                            if (n_newlines > 1) {
+                                print_newline();
+                                for (i = 1; i < n_newlines; i += 1) {
+                                    print_newline(true);
+                                }
                             }
                             }
                         }
                         }
                     }
                     }
-                }
 
 
-                handlers[token_type]();
+                    handlers[token_type]();
 
 
-                // 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.
-                if (token_type !== 'TK_INLINE_COMMENT' && token_type !== 'TK_COMMENT' &&
-                    token_type !== 'TK_UNKNOWN') {
-                    last_last_text = flags.last_text;
-                    last_type = token_type;
-                    flags.last_text = token_text;
+                    // 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.
+                    if (token_type !== 'TK_INLINE_COMMENT' && token_type !== 'TK_COMMENT' &&
+                        token_type !== 'TK_UNKNOWN') {
+                        last_last_text = flags.last_text;
+                        last_type = token_type;
+                        flags.last_text = token_text;
+                    }
                 }
                 }
-            }
 
 
-            sweet_code = preindent_string + output.join('').replace(/[\r\n ]+$/, '');
-            return sweet_code;
-        };
+                sweet_code = preindent_string + output.join('').replace(/[\r\n ]+$/, '');
+                return sweet_code;
+            };
 
 
-        function trim_output(eat_newlines) {
-            eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;
-            while (output.length && (output[output.length - 1] === ' ' || output[output.length - 1] === indent_string || output[output.length - 1] === preindent_string || (eat_newlines && (output[output.length - 1] === '\n' || output[output.length - 1] === '\r')))) {
-                output.pop();
+            function trim_output(eat_newlines) {
+                eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;
+                while (output.length && (output[output.length - 1] === ' ' || output[output.length - 1] === indent_string || output[output.length - 1] === preindent_string || (eat_newlines && (output[output.length - 1] === '\n' || output[output.length - 1] === '\r')))) {
+                    output.pop();
+                }
             }
             }
-        }
 
 
-        function trim(s) {
-            return s.replace(/^\s\s*|\s\s*$/, '');
-        }
+            function trim(s) {
+                return s.replace(/^\s\s*|\s\s*$/, '');
+            }
 
 
-        // we could use just string.split, but
-        // IE doesn't like returning empty strings
+            // we could use just string.split, but
+            // IE doesn't like returning empty strings
 
 
-        function split_newlines(s) {
-            //return s.split(/\x0d\x0a|\x0a/);
+            function split_newlines(s) {
+                //return s.split(/\x0d\x0a|\x0a/);
 
 
-            s = s.replace(/\x0d/g, '');
-            var out = [],
-                idx = s.indexOf("\n");
-            while (idx !== -1) {
-                out.push(s.substring(0, idx));
-                s = s.substring(idx + 1);
-                idx = s.indexOf("\n");
-            }
-            if (s.length) {
-                out.push(s);
+                s = s.replace(/\x0d/g, '');
+                var out = [],
+                    idx = s.indexOf("\n");
+                while (idx !== -1) {
+                    out.push(s.substring(0, idx));
+                    s = s.substring(idx + 1);
+                    idx = s.indexOf("\n");
+                }
+                if (s.length) {
+                    out.push(s);
+                }
+                return out;
             }
             }
-            return out;
-        }
 
 
-        function just_added_newline() {
-            return output.length && output[output.length - 1] === "\n";
-        }
-
-        function _last_index_of(arr, find) {
-            var i = arr.length - 1;
-            if (i < 0) {
-                i += arr.length;
-            }
-            if (i > arr.length - 1) {
-                i = arr.length - 1;
-            }
-            for (i++; i-- > 0;) {
-                if (i in arr && arr[i] === find) {
-                    return i;
-                }
+            function just_added_newline() {
+                return output.length && output[output.length - 1] === "\n";
             }
             }
-            return -1;
-        }
 
 
-        function allow_wrap_or_preserved_newline(force_linewrap) {
-            force_linewrap = (force_linewrap === undefined) ? false : force_linewrap;
-            if (opt.wrap_line_length && !force_linewrap) {
-                var current_line = '';
-                var proposed_line_length = 0;
-                var start_line = _last_index_of(output, '\n') + 1;
-                // never wrap the first token of a line.
-                if (start_line < output.length) {
-                    current_line = output.slice(start_line).join('');
-                    proposed_line_length = current_line.length + token_text.length +
-                        (output_space_before_token ? 1 : 0);
-                    if (proposed_line_length >= opt.wrap_line_length) {
-                        force_linewrap = true;
+            function _last_index_of(arr, find) {
+                var i = arr.length - 1;
+                if (i < 0) {
+                    i += arr.length;
+                }
+                if (i > arr.length - 1) {
+                    i = arr.length - 1;
+                }
+                for (i++; i-- > 0;) {
+                    if (i in arr && arr[i] === find) {
+                        return i;
                     }
                     }
                 }
                 }
+                return -1;
+            }
+
+            function allow_wrap_or_preserved_newline(force_linewrap) {
+                force_linewrap = (force_linewrap === undefined) ? false : force_linewrap;
+                if (opt.wrap_line_length && !force_linewrap) {
+                    var current_line = '';
+                    var proposed_line_length = 0;
+                    var start_line = _last_index_of(output, '\n') + 1;
+                    // never wrap the first token of a line.
+                    if (start_line < output.length) {
+                        current_line = output.slice(start_line).join('');
+                        proposed_line_length = current_line.length + token_text.length +
+                            (output_space_before_token ? 1 : 0);
+                        if (proposed_line_length >= opt.wrap_line_length) {
+                            force_linewrap = true;
+                        }
+                    }
+                }
+                if (((opt.preserve_newlines && wanted_newline) || force_linewrap) && !just_added_newline()) {
+                    print_newline(false, true);
+                    output_wrapped = true;
+                    wanted_newline = false;
+                }
             }
             }
-            if (((opt.preserve_newlines && wanted_newline) || force_linewrap) && !just_added_newline()) {
-                print_newline(false, true);
-                output_wrapped = true;
-                wanted_newline = false;
-            }
-        }
 
 
-        function print_newline(force_newline, preserve_statement_flags) {
-            output_wrapped = false;
-            output_space_before_token = false;
+            function print_newline(force_newline, preserve_statement_flags) {
+                output_wrapped = false;
+                output_space_before_token = false;
 
 
-            if (!preserve_statement_flags) {
-                if  (flags.last_text !== ';') {
-                    while (flags.mode === MODE.Statement && !flags.if_block) {
-                        restore_mode();
+                if (!preserve_statement_flags) {
+                    if (flags.last_text !== ';') {
+                        while (flags.mode === MODE.Statement && !flags.if_block) {
+                            restore_mode();
+                        }
                     }
                     }
                 }
                 }
-            }
 
 
-            if (flags.mode === MODE.ArrayLiteral) {
-                flags.multiline_array = true;
-            }
+                if (flags.mode === MODE.ArrayLiteral) {
+                    flags.multiline_array = true;
+                }
 
 
 
 
-            if (!output.length) {
-                return; // no newline on start of file
-            }
+                if (!output.length) {
+                    return; // no newline on start of file
+                }
 
 
-            if (force_newline || !just_added_newline()) {
-                output.push("\n");
+                if (force_newline || !just_added_newline()) {
+                    output.push("\n");
+                }
             }
             }
-        }
 
 
-        function print_token_line_indentation() {
-            if (just_added_newline()) {
-                if (opt.keep_array_indentation && is_array(flags.mode) && whitespace_before_token.length) {
-                    output.push(whitespace_before_token.join('') + '');
-                } else {
-                    if (preindent_string) {
-                        output.push(preindent_string);
-                    }
+            function print_token_line_indentation() {
+                if (just_added_newline()) {
+                    if (opt.keep_array_indentation && is_array(flags.mode) && whitespace_before_token.length) {
+                        output.push(whitespace_before_token.join('') + '');
+                    } else {
+                        if (preindent_string) {
+                            output.push(preindent_string);
+                        }
 
 
-                    print_indent_string(flags.indentation_level);
-                    print_indent_string(flags.var_line && flags.var_line_reindented);
-                    print_indent_string(output_wrapped);
+                        print_indent_string(flags.indentation_level);
+                        print_indent_string(flags.var_line && flags.var_line_reindented);
+                        print_indent_string(output_wrapped);
+                    }
                 }
                 }
             }
             }
-        }
 
 
-        function print_indent_string(level) {
-            if (level === undefined) {
-                level = 1;
-            } else if (typeof level !== 'number') {
-                level = level ? 1 : 0;
-            }
+            function print_indent_string(level) {
+                if (level === undefined) {
+                    level = 1;
+                } else if (typeof level !== 'number') {
+                    level = level ? 1 : 0;
+                }
 
 
-            // Never indent your first output indent at the start of the file
-            if (flags.last_text !== '') {
-                for (var i = 0; i < level; i += 1) {
-                    output.push(indent_string);
+                // Never indent your first output indent at the start of the file
+                if (flags.last_text !== '') {
+                    for (var i = 0; i < level; i += 1) {
+                        output.push(indent_string);
+                    }
                 }
                 }
             }
             }
-        }
 
 
-        function print_token_space_before() {
-            if (output_space_before_token && output.length) {
-                var last_output = output[output.length - 1];
-                if (!just_added_newline() && last_output !== ' ' && last_output !== indent_string) { // prevent occassional duplicate space
-                    output.push(' ');
+            function print_token_space_before() {
+                if (output_space_before_token && output.length) {
+                    var last_output = output[output.length - 1];
+                    if (!just_added_newline() && last_output !== ' ' && last_output !== indent_string) { // prevent occassional duplicate space
+                        output.push(' ');
+                    }
                 }
                 }
             }
             }
-        }
-
-        function print_token(printable_token) {
-            printable_token = printable_token || token_text;
-            print_token_line_indentation();
-            output_wrapped = false;
-            print_token_space_before();
-            output_space_before_token = false;
-            output.push(printable_token);
-        }
-
-        function indent() {
-            flags.indentation_level += 1;
-        }
 
 
-        function set_mode(mode) {
-            if (flags) {
-                flag_store.push(flags);
-                previous_flags = flags;
-            } else {
-                previous_flags = create_flags(null, mode);
+            function print_token(printable_token) {
+                printable_token = printable_token || token_text;
+                print_token_line_indentation();
+                output_wrapped = false;
+                print_token_space_before();
+                output_space_before_token = false;
+                output.push(printable_token);
             }
             }
 
 
-            flags = create_flags(previous_flags, mode);
-        }
+            function indent() {
+                flags.indentation_level += 1;
+            }
 
 
-        function is_array(mode) {
-            return mode === MODE.ArrayLiteral;
-        }
+            function set_mode(mode) {
+                if (flags) {
+                    flag_store.push(flags);
+                    previous_flags = flags;
+                } else {
+                    previous_flags = create_flags(null, mode);
+                }
 
 
-        function is_expression(mode) {
-            return in_array(mode, [MODE.ArrayLiteral, MODE.Expression, MODE.ForInitializer, MODE.Conditional]);
-        }
+                flags = create_flags(previous_flags, mode);
+            }
 
 
-        function restore_mode() {
-            if (flag_store.length > 0) {
-                previous_flags = flags;
-                flags = flag_store.pop();
+            function is_array(mode) {
+                return mode === MODE.ArrayLiteral;
             }
             }
-        }
 
 
-        function start_of_statement() {
-            if (
-             (flags.last_text === 'do' ||
-                 (flags.last_text === 'else' && token_text !== 'if') ||
-                (last_type === 'TK_END_EXPR' && (previous_flags.mode === MODE.ForInitializer || previous_flags.mode === MODE.Conditional)))) {
-                allow_wrap_or_preserved_newline();
-                set_mode(MODE.Statement);
-                indent();
-                output_wrapped = false;
-                return true;
+            function is_expression(mode) {
+                return in_array(mode, [MODE.ArrayLiteral, MODE.Expression, MODE.ForInitializer, MODE.Conditional]);
             }
             }
-            return false;
-        }
 
 
-        function all_lines_start_with(lines, c) {
-            for (var i = 0; i < lines.length; i++) {
-                var line = trim(lines[i]);
-                if (line.charAt(0) !== c) {
-                    return false;
+            function restore_mode() {
+                if (flag_store.length > 0) {
+                    previous_flags = flags;
+                    flags = flag_store.pop();
                 }
                 }
             }
             }
-            return true;
-        }
-
-        function is_special_word(word) {
-            return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);
-        }
 
 
-        function in_array(what, arr) {
-            for (var i = 0; i < arr.length; i += 1) {
-                if (arr[i] === what) {
+            function start_of_statement() {
+                if (
+                    (flags.last_text === 'do' ||
+                        (flags.last_text === 'else' && token_text !== 'if') ||
+                        (last_type === 'TK_END_EXPR' && (previous_flags.mode === MODE.ForInitializer || previous_flags.mode === MODE.Conditional)))) {
+                    allow_wrap_or_preserved_newline();
+                    set_mode(MODE.Statement);
+                    indent();
+                    output_wrapped = false;
                     return true;
                     return true;
                 }
                 }
+                return false;
             }
             }
-            return false;
-        }
 
 
-        function unescape_string(s) {
-            var esc = false,
-                out = '',
-                pos = 0,
-                s_hex = '',
-                escaped = 0,
-                c;
-
-            while (esc || pos < s.length) {
-
-                c = s.charAt(pos);
-                pos++;
-
-                if (esc) {
-                    esc = false;
-                    if (c === 'x') {
-                        // simple hex-escape \x24
-                        s_hex = s.substr(pos, 2);
-                        pos += 2;
-                    } else if (c === 'u') {
-                        // unicode-escape, \u2134
-                        s_hex = s.substr(pos, 4);
-                        pos += 4;
-                    } else {
-                        // some common escape, e.g \n
-                        out += '\\' + c;
-                        continue;
+            function all_lines_start_with(lines, c) {
+                for (var i = 0; i < lines.length; i++) {
+                    var line = trim(lines[i]);
+                    if (line.charAt(0) !== c) {
+                        return false;
                     }
                     }
-                    if (!s_hex.match(/^[0123456789abcdefABCDEF]+$/)) {
-                        // some weird escaping, bail out,
-                        // leaving whole string intact
-                        return s;
+                }
+                return true;
+            }
+
+            function is_special_word(word) {
+                return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);
+            }
+
+            function in_array(what, arr) {
+                for (var i = 0; i < arr.length; i += 1) {
+                    if (arr[i] === what) {
+                        return true;
                     }
                     }
+                }
+                return false;
+            }
+
+            function unescape_string(s) {
+                var esc = false,
+                    out = '',
+                    pos = 0,
+                    s_hex = '',
+                    escaped = 0,
+                    c;
+
+                while (esc || pos < s.length) {
 
 
-                    escaped = parseInt(s_hex, 16);
+                    c = s.charAt(pos);
+                    pos++;
 
 
-                    if (escaped >= 0x00 && escaped < 0x20) {
-                        // leave 0x00...0x1f escaped
+                    if (esc) {
+                        esc = false;
                         if (c === 'x') {
                         if (c === 'x') {
-                            out += '\\x' + s_hex;
+                            // simple hex-escape \x24
+                            s_hex = s.substr(pos, 2);
+                            pos += 2;
+                        } else if (c === 'u') {
+                            // unicode-escape, \u2134
+                            s_hex = s.substr(pos, 4);
+                            pos += 4;
+                        } else {
+                            // some common escape, e.g \n
+                            out += '\\' + c;
+                            continue;
+                        }
+                        if (!s_hex.match(/^[0123456789abcdefABCDEF]+$/)) {
+                            // some weird escaping, bail out,
+                            // leaving whole string intact
+                            return s;
+                        }
+
+                        escaped = parseInt(s_hex, 16);
+
+                        if (escaped >= 0x00 && escaped < 0x20) {
+                            // leave 0x00...0x1f escaped
+                            if (c === 'x') {
+                                out += '\\x' + s_hex;
+                            } else {
+                                out += '\\u' + s_hex;
+                            }
+                            continue;
+                        } else if (escaped === 0x22 || escaped === 0x27 || escaped === 0x5c) {
+                            // single-quote, apostrophe, backslash - escape these
+                            out += '\\' + String.fromCharCode(escaped);
+                        } else if (c === 'x' && escaped > 0x7e && escaped <= 0xff) {
+                            // we bail out on \x7f..\xff,
+                            // leaving whole string escaped,
+                            // as it's probably completely binary
+                            return s;
                         } else {
                         } else {
-                            out += '\\u' + s_hex;
+                            out += String.fromCharCode(escaped);
                         }
                         }
-                        continue;
-                    } else if (escaped === 0x22 || escaped === 0x27 || escaped === 0x5c) {
-                        // single-quote, apostrophe, backslash - escape these
-                        out += '\\' + String.fromCharCode(escaped);
-                    } else if (c === 'x' && escaped > 0x7e && escaped <= 0xff) {
-                        // we bail out on \x7f..\xff,
-                        // leaving whole string escaped,
-                        // as it's probably completely binary
-                        return s;
+                    } else if (c === '\\') {
+                        esc = true;
                     } else {
                     } else {
-                        out += String.fromCharCode(escaped);
+                        out += c;
                     }
                     }
-                } else if (c === '\\') {
-                    esc = true;
-                } else {
-                    out += c;
                 }
                 }
+                return out;
             }
             }
-            return out;
-        }
 
 
-        function is_next(find) {
-            var local_pos = parser_pos;
-            var c = input.charAt(local_pos);
-            while (in_array(c, whitespace) && c !== find) {
-                local_pos++;
-                if (local_pos >= input_length) {
-                    return false;
+            function is_next(find) {
+                var local_pos = parser_pos;
+                var c = input.charAt(local_pos);
+                while (in_array(c, whitespace) && c !== find) {
+                    local_pos++;
+                    if (local_pos >= input_length) {
+                        return false;
+                    }
+                    c = input.charAt(local_pos);
                 }
                 }
-                c = input.charAt(local_pos);
+                return c === find;
             }
             }
-            return c === find;
-        }
 
 
-        function get_next_token() {
-            var i, resulting_string;
+            function get_next_token() {
+                var i, resulting_string;
 
 
-            n_newlines = 0;
+                n_newlines = 0;
 
 
-            if (parser_pos >= input_length) {
-                return ['', 'TK_EOF'];
-            }
+                if (parser_pos >= input_length) {
+                    return ['', 'TK_EOF'];
+                }
 
 
-            wanted_newline = false;
-            whitespace_before_token = [];
+                wanted_newline = false;
+                whitespace_before_token = [];
 
 
-            var c = input.charAt(parser_pos);
-            parser_pos += 1;
+                var c = input.charAt(parser_pos);
+                parser_pos += 1;
 
 
-            while (in_array(c, whitespace)) {
+                while (in_array(c, whitespace)) {
 
 
-                if (c === '\n') {
-                    n_newlines += 1;
-                    whitespace_before_token = [];
-                } else if (n_newlines) {
-                    if (c === indent_string) {
-                        whitespace_before_token.push(indent_string);
-                    } else if (c !== '\r') {
-                        whitespace_before_token.push(' ');
+                    if (c === '\n') {
+                        n_newlines += 1;
+                        whitespace_before_token = [];
+                    } else if (n_newlines) {
+                        if (c === indent_string) {
+                            whitespace_before_token.push(indent_string);
+                        } else if (c !== '\r') {
+                            whitespace_before_token.push(' ');
+                        }
                     }
                     }
-                }
 
 
-                if (parser_pos >= input_length) {
-                    return ['', 'TK_EOF'];
-                }
+                    if (parser_pos >= input_length) {
+                        return ['', 'TK_EOF'];
+                    }
 
 
-                c = input.charAt(parser_pos);
-                parser_pos += 1;
-            }
+                    c = input.charAt(parser_pos);
+                    parser_pos += 1;
+                }
 
 
-            if (in_array(c, wordchar)) {
-                if (parser_pos < input_length) {
-                    while (in_array(input.charAt(parser_pos), wordchar)) {
-                        c += input.charAt(parser_pos);
-                        parser_pos += 1;
-                        if (parser_pos === input_length) {
-                            break;
+                if (in_array(c, wordchar)) {
+                    if (parser_pos < input_length) {
+                        while (in_array(input.charAt(parser_pos), wordchar)) {
+                            c += input.charAt(parser_pos);
+                            parser_pos += 1;
+                            if (parser_pos === input_length) {
+                                break;
+                            }
                         }
                         }
                     }
                     }
-                }
 
 
-                // small and surprisingly unugly hack for 1E-10 representation
-                if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) {
+                    // small and surprisingly unugly hack for 1E-10 representation
+                    if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) {
 
 
-                    var sign = input.charAt(parser_pos);
-                    parser_pos += 1;
+                        var sign = input.charAt(parser_pos);
+                        parser_pos += 1;
+
+                        var t = get_next_token();
+                        c += sign + t[0];
+                        return [c, 'TK_WORD'];
+                    }
 
 
-                    var t = get_next_token();
-                    c += sign + t[0];
+                    if (c === 'in') { // hack for 'in' operator
+                        return [c, 'TK_OPERATOR'];
+                    }
                     return [c, 'TK_WORD'];
                     return [c, 'TK_WORD'];
                 }
                 }
 
 
-                if (c === 'in') { // hack for 'in' operator
-                    return [c, 'TK_OPERATOR'];
+                if (c === '(' || c === '[') {
+                    return [c, 'TK_START_EXPR'];
                 }
                 }
-                return [c, 'TK_WORD'];
-            }
-
-            if (c === '(' || c === '[') {
-                return [c, 'TK_START_EXPR'];
-            }
 
 
-            if (c === ')' || c === ']') {
-                return [c, 'TK_END_EXPR'];
-            }
+                if (c === ')' || c === ']') {
+                    return [c, 'TK_END_EXPR'];
+                }
 
 
-            if (c === '{') {
-                return [c, 'TK_START_BLOCK'];
-            }
+                if (c === '{') {
+                    return [c, 'TK_START_BLOCK'];
+                }
 
 
-            if (c === '}') {
-                return [c, 'TK_END_BLOCK'];
-            }
+                if (c === '}') {
+                    return [c, 'TK_END_BLOCK'];
+                }
 
 
-            if (c === ';') {
-                return [c, 'TK_SEMICOLON'];
-            }
+                if (c === ';') {
+                    return [c, 'TK_SEMICOLON'];
+                }
 
 
-            if (c === '/') {
-                var comment = '';
-                // peek for comment /* ... */
-                var inline_comment = true;
-                if (input.charAt(parser_pos) === '*') {
-                    parser_pos += 1;
-                    if (parser_pos < input_length) {
-                        while (parser_pos < input_length && !(input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) {
-                            c = input.charAt(parser_pos);
-                            comment += c;
-                            if (c === "\n" || c === "\r") {
-                                inline_comment = false;
+                if (c === '/') {
+                    var comment = '';
+                    // peek for comment /* ... */
+                    var inline_comment = true;
+                    if (input.charAt(parser_pos) === '*') {
+                        parser_pos += 1;
+                        if (parser_pos < input_length) {
+                            while (parser_pos < input_length && !(input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) {
+                                c = input.charAt(parser_pos);
+                                comment += c;
+                                if (c === "\n" || c === "\r") {
+                                    inline_comment = false;
+                                }
+                                parser_pos += 1;
+                                if (parser_pos >= input_length) {
+                                    break;
+                                }
                             }
                             }
+                        }
+                        parser_pos += 2;
+                        if (inline_comment && n_newlines === 0) {
+                            return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];
+                        } else {
+                            return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
+                        }
+                    }
+                    // peek for comment // ...
+                    if (input.charAt(parser_pos) === '/') {
+                        comment = c;
+                        while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {
+                            comment += input.charAt(parser_pos);
                             parser_pos += 1;
                             parser_pos += 1;
                             if (parser_pos >= input_length) {
                             if (parser_pos >= input_length) {
                                 break;
                                 break;
                             }
                             }
                         }
                         }
+                        return [comment, 'TK_COMMENT'];
                     }
                     }
-                    parser_pos += 2;
-                    if (inline_comment && n_newlines === 0) {
-                        return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];
-                    } else {
-                        return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
-                    }
-                }
-                // peek for comment // ...
-                if (input.charAt(parser_pos) === '/') {
-                    comment = c;
-                    while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {
-                        comment += input.charAt(parser_pos);
-                        parser_pos += 1;
-                        if (parser_pos >= input_length) {
-                            break;
-                        }
-                    }
-                    return [comment, 'TK_COMMENT'];
-                }
 
 
-            }
+                }
 
 
-            if (c === "'" || c === '"' || // string
-            (c === '/' &&
-                ((last_type === 'TK_WORD' && is_special_word (flags.last_text)) ||
-                (last_type === 'TK_END_EXPR' && in_array(previous_flags.mode, [MODE.Conditional, MODE.ForInitializer])) ||
-                (in_array(last_type, ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK',
-                    'TK_END_BLOCK', 'TK_OPERATOR', 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA'
-            ]))))) { // regexp
-                var sep = c,
-                    esc = false,
-                    has_char_escapes = false;
+                if (c === "'" || c === '"' || // string
+                    (c === '/' &&
+                        ((last_type === 'TK_WORD' && is_special_word(flags.last_text)) ||
+                            (last_type === 'TK_END_EXPR' && in_array(previous_flags.mode, [MODE.Conditional, MODE.ForInitializer])) ||
+                            (in_array(last_type, ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK',
+                                'TK_END_BLOCK', 'TK_OPERATOR', 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA'
+                            ]))))) { // regexp
+                    var sep = c,
+                        esc = false,
+                        has_char_escapes = false;
 
 
-                resulting_string = c;
+                    resulting_string = c;
 
 
-                if (parser_pos < input_length) {
-                    if (sep === '/') {
-                        //
-                        // handle regexp separately...
-                        //
-                        var in_char_class = false;
-                        while (esc || in_char_class || input.charAt(parser_pos) !== sep) {
-                            resulting_string += input.charAt(parser_pos);
-                            if (!esc) {
-                                esc = input.charAt(parser_pos) === '\\';
-                                if (input.charAt(parser_pos) === '[') {
-                                    in_char_class = true;
-                                } else if (input.charAt(parser_pos) === ']') {
-                                    in_char_class = false;
+                    if (parser_pos < input_length) {
+                        if (sep === '/') {
+                            //
+                            // handle regexp separately...
+                            //
+                            var in_char_class = false;
+                            while (esc || in_char_class || input.charAt(parser_pos) !== sep) {
+                                resulting_string += input.charAt(parser_pos);
+                                if (!esc) {
+                                    esc = input.charAt(parser_pos) === '\\';
+                                    if (input.charAt(parser_pos) === '[') {
+                                        in_char_class = true;
+                                    } else if (input.charAt(parser_pos) === ']') {
+                                        in_char_class = false;
+                                    }
+                                } else {
+                                    esc = false;
+                                }
+                                parser_pos += 1;
+                                if (parser_pos >= input_length) {
+                                    // incomplete string/rexp when end-of-file reached.
+                                    // bail out with what had been received so far.
+                                    return [resulting_string, 'TK_STRING'];
                                 }
                                 }
-                            } else {
-                                esc = false;
-                            }
-                            parser_pos += 1;
-                            if (parser_pos >= input_length) {
-                                // incomplete string/rexp when end-of-file reached.
-                                // bail out with what had been received so far.
-                                return [resulting_string, 'TK_STRING'];
                             }
                             }
-                        }
 
 
-                    } else {
-                        //
-                        // and handle string also separately
-                        //
-                        while (esc || input.charAt(parser_pos) !== sep) {
-                            resulting_string += input.charAt(parser_pos);
-                            if (esc) {
-                                if (input.charAt(parser_pos) === 'x' || input.charAt(parser_pos) === 'u') {
-                                    has_char_escapes = true;
+                        } else {
+                            //
+                            // and handle string also separately
+                            //
+                            while (esc || input.charAt(parser_pos) !== sep) {
+                                resulting_string += input.charAt(parser_pos);
+                                if (esc) {
+                                    if (input.charAt(parser_pos) === 'x' || input.charAt(parser_pos) === 'u') {
+                                        has_char_escapes = true;
+                                    }
+                                    esc = false;
+                                } else {
+                                    esc = input.charAt(parser_pos) === '\\';
+                                }
+                                parser_pos += 1;
+                                if (parser_pos >= input_length) {
+                                    // incomplete string/rexp when end-of-file reached.
+                                    // bail out with what had been received so far.
+                                    return [resulting_string, 'TK_STRING'];
                                 }
                                 }
-                                esc = false;
-                            } else {
-                                esc = input.charAt(parser_pos) === '\\';
-                            }
-                            parser_pos += 1;
-                            if (parser_pos >= input_length) {
-                                // incomplete string/rexp when end-of-file reached.
-                                // bail out with what had been received so far.
-                                return [resulting_string, 'TK_STRING'];
                             }
                             }
-                        }
 
 
+                        }
                     }
                     }
-                }
 
 
-                parser_pos += 1;
-                resulting_string += sep;
+                    parser_pos += 1;
+                    resulting_string += sep;
 
 
-                if (has_char_escapes && opt.unescape_strings) {
-                    resulting_string = unescape_string(resulting_string);
-                }
+                    if (has_char_escapes && opt.unescape_strings) {
+                        resulting_string = unescape_string(resulting_string);
+                    }
 
 
-                if (sep === '/') {
-                    // regexps may have modifiers /regexp/MOD , so fetch those, too
-                    while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) {
-                        resulting_string += input.charAt(parser_pos);
-                        parser_pos += 1;
+                    if (sep === '/') {
+                        // regexps may have modifiers /regexp/MOD , so fetch those, too
+                        while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) {
+                            resulting_string += input.charAt(parser_pos);
+                            parser_pos += 1;
+                        }
                     }
                     }
+                    return [resulting_string, 'TK_STRING'];
                 }
                 }
-                return [resulting_string, 'TK_STRING'];
-            }
 
 
-            if (c === '#') {
+                if (c === '#') {
 
 
 
 
-                if (output.length === 0 && input.charAt(parser_pos) === '!') {
-                    // shebang
-                    resulting_string = c;
-                    while (parser_pos < input_length && c !== '\n') {
-                        c = input.charAt(parser_pos);
-                        resulting_string += c;
-                        parser_pos += 1;
+                    if (output.length === 0 && input.charAt(parser_pos) === '!') {
+                        // shebang
+                        resulting_string = c;
+                        while (parser_pos < input_length && c !== '\n') {
+                            c = input.charAt(parser_pos);
+                            resulting_string += c;
+                            parser_pos += 1;
+                        }
+                        return [trim(resulting_string) + '\n', 'TK_UNKNOWN'];
                     }
                     }
-                    return [trim(resulting_string) + '\n', 'TK_UNKNOWN'];
-                }
 
 
 
 
+                    // 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
+                    var sharp = '#';
+                    if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) {
+                        do {
+                            c = input.charAt(parser_pos);
+                            sharp += c;
+                            parser_pos += 1;
+                        } while (parser_pos < input_length && c !== '#' && c !== '=');
+                        if (c === '#') {
+                            //
+                        } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {
+                            sharp += '[]';
+                            parser_pos += 2;
+                        } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {
+                            sharp += '{}';
+                            parser_pos += 2;
+                        }
+                        return [sharp, 'TK_WORD'];
+                    }
+                }
 
 
-                // 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
-                var sharp = '#';
-                if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) {
-                    do {
-                        c = input.charAt(parser_pos);
-                        sharp += c;
-                        parser_pos += 1;
-                    } while (parser_pos < input_length && c !== '#' && c !== '=');
-                    if (c === '#') {
-                        //
-                    } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {
-                        sharp += '[]';
-                        parser_pos += 2;
-                    } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {
-                        sharp += '{}';
-                        parser_pos += 2;
+                if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
+                    parser_pos += 3;
+                    c = '<!--';
+                    while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {
+                        c += input.charAt(parser_pos);
+                        parser_pos++;
                     }
                     }
-                    return [sharp, 'TK_WORD'];
+                    flags.in_html_comment = true;
+                    return [c, 'TK_COMMENT'];
                 }
                 }
-            }
 
 
-            if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
-                parser_pos += 3;
-                c = '<!--';
-                while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {
-                    c += input.charAt(parser_pos);
-                    parser_pos++;
+                if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {
+                    flags.in_html_comment = false;
+                    parser_pos += 2;
+                    return ['-->', 'TK_COMMENT'];
                 }
                 }
-                flags.in_html_comment = true;
-                return [c, 'TK_COMMENT'];
-            }
 
 
-            if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {
-                flags.in_html_comment = false;
-                parser_pos += 2;
-                return ['-->', 'TK_COMMENT'];
-            }
+                if (c === '.') {
+                    return [c, 'TK_DOT'];
+                }
 
 
-            if (c === '.') {
-                return [c, 'TK_DOT'];
-            }
+                if (in_array(c, punct)) {
+                    while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {
+                        c += input.charAt(parser_pos);
+                        parser_pos += 1;
+                        if (parser_pos >= input_length) {
+                            break;
+                        }
+                    }
 
 
-            if (in_array(c, punct)) {
-                while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {
-                    c += input.charAt(parser_pos);
-                    parser_pos += 1;
-                    if (parser_pos >= input_length) {
-                        break;
+                    if (c === ',') {
+                        return [c, 'TK_COMMA'];
+                    } else if (c === '=') {
+                        return [c, 'TK_EQUALS'];
+                    } else {
+                        return [c, 'TK_OPERATOR'];
                     }
                     }
                 }
                 }
 
 
-                if (c === ',') {
-                    return [c, 'TK_COMMA'];
-                } else if (c === '=') {
-                    return [c, 'TK_EQUALS'];
-                } else {
-                    return [c, 'TK_OPERATOR'];
-                }
+                return [c, 'TK_UNKNOWN'];
             }
             }
 
 
-            return [c, 'TK_UNKNOWN'];
-        }
-
-        function handle_start_expr() {
-            if (start_of_statement()) {
-                // The conditional starts the statement if appropriate.
-            }
+            function handle_start_expr() {
+                if (start_of_statement()) {
+                    // The conditional starts the statement if appropriate.
+                }
 
 
-            if (token_text === '[') {
+                if (token_text === '[') {
 
 
-                if (last_type === 'TK_WORD' || flags.last_text === ')') {
-                    // this is array index specifier, break immediately
-                    // a[x], fn()[x]
-                    if (in_array (flags.last_text, line_starters)) {
-                        output_space_before_token = true;
+                    if (last_type === 'TK_WORD' || flags.last_text === ')') {
+                        // this is array index specifier, break immediately
+                        // a[x], fn()[x]
+                        if (in_array(flags.last_text, line_starters)) {
+                            output_space_before_token = true;
+                        }
+                        set_mode(MODE.Expression);
+                        print_token();
+                        return;
                     }
                     }
-                    set_mode(MODE.Expression);
-                    print_token();
-                    return;
-                }
 
 
-                if (is_array(flags.mode)) {
-                    if ( (flags.last_text === '[') ||
-                        (last_last_text === ']' && flags.last_text === ',')) {
-                        // ], [ goes to new line
-                        if (!opt.keep_array_indentation) {
-                            print_newline();
+                    if (is_array(flags.mode)) {
+                        if ((flags.last_text === '[') ||
+                            (last_last_text === ']' && flags.last_text === ',')) {
+                            // ], [ goes to new line
+                            if (!opt.keep_array_indentation) {
+                                print_newline();
+                            }
                         }
                         }
                     }
                     }
-                }
 
 
-            } else {
-                if  (flags.last_text === 'for') {
-                    set_mode(MODE.ForInitializer);
-                } else if (in_array (flags.last_text, ['if', 'while'])) {
-                    set_mode(MODE.Conditional);
                 } else {
                 } else {
-                    set_mode(MODE.Expression);
+                    if (flags.last_text === 'for') {
+                        set_mode(MODE.ForInitializer);
+                    } else if (in_array(flags.last_text, ['if', 'while'])) {
+                        set_mode(MODE.Conditional);
+                    } else {
+                        set_mode(MODE.Expression);
+                    }
                 }
                 }
-            }
 
 
-            if  (flags.last_text === ';' || last_type === 'TK_START_BLOCK') {
-                print_newline();
-            } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || flags.last_text === '.') {
-                if (wanted_newline) {
+                if (flags.last_text === ';' || last_type === 'TK_START_BLOCK') {
                     print_newline();
                     print_newline();
-                }
-                // do nothing on (( and )( and ][ and ]( and .(
-            } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
-                output_space_before_token = true;
-            } else if (flags.last_word === 'function' || flags.last_word === 'typeof') {
-                // function() vs function ()
-                if (opt.jslint_happy) {
-                    output_space_before_token = true;
-                }
-            } else if (in_array (flags.last_text, line_starters) || flags.last_text === 'catch') {
-                if (opt.space_before_conditional) {
+                } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || flags.last_text === '.') {
+                    if (wanted_newline) {
+                        print_newline();
+                    }
+                    // do nothing on (( and )( and ][ and ]( and .(
+                } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
                     output_space_before_token = true;
                     output_space_before_token = true;
+                } else if (flags.last_word === 'function' || flags.last_word === 'typeof') {
+                    // function() vs function ()
+                    if (opt.jslint_happy) {
+                        output_space_before_token = true;
+                    }
+                } else if (in_array(flags.last_text, line_starters) || flags.last_text === 'catch') {
+                    if (opt.space_before_conditional) {
+                        output_space_before_token = true;
+                    }
                 }
                 }
-            }
 
 
-            // Support of this kind of newline preservation.
-            // a = (b &&
-            //     (c || d));
-            if (token_text === '(') {
-                if (last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
-                    if (flags.mode !== MODE.ObjectLiteral) {
-                        allow_wrap_or_preserved_newline();
+                // Support of this kind of newline preservation.
+                // a = (b &&
+                //     (c || d));
+                if (token_text === '(') {
+                    if (last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
+                        if (flags.mode !== MODE.ObjectLiteral) {
+                            allow_wrap_or_preserved_newline();
+                        }
                     }
                     }
                 }
                 }
+                print_token();
+                if (token_text === '[') {
+                    set_mode(MODE.ArrayLiteral);
+                    indent();
+                }
             }
             }
-            print_token();
-            if (token_text === '[') {
-                set_mode(MODE.ArrayLiteral);
-                indent();
-            }
-        }
 
 
-        function handle_end_expr() {
-            // statements inside expressions are not valid syntax, but...
-            // statements must all be closed when their container closes
-            while (flags.mode === MODE.Statement) {
-                restore_mode();
-            }
+            function handle_end_expr() {
+                // statements inside expressions are not valid syntax, but...
+                // statements must all be closed when their container closes
+                while (flags.mode === MODE.Statement) {
+                    restore_mode();
+                }
 
 
-            if (token_text === ']' && is_array(flags.mode) && flags.multiline_array && !opt.keep_array_indentation) {
-                print_newline();
-            }
-            restore_mode();
-            print_token();
+                if (token_text === ']' && is_array(flags.mode) && flags.multiline_array && !opt.keep_array_indentation) {
+                    print_newline();
+                }
+                restore_mode();
+                print_token();
 
 
-            // do {} while () // no statement required after
-            if (flags.do_while && previous_flags.mode === MODE.Conditional) {
-                previous_flags.mode = MODE.Expression;
-                flags.do_block = false;
-                flags.do_while = false;
+                // do {} while () // no statement required after
+                if (flags.do_while && previous_flags.mode === MODE.Conditional) {
+                    previous_flags.mode = MODE.Expression;
+                    flags.do_block = false;
+                    flags.do_while = false;
 
 
+                }
             }
             }
-        }
 
 
-        function handle_start_block() {
-            set_mode(MODE.BlockStatement);
+            function handle_start_block() {
+                set_mode(MODE.BlockStatement);
 
 
-            var empty_braces = is_next('}');
+                var empty_braces = is_next('}');
 
 
-            if (opt.brace_style === "expand-strict") {
-                if (!empty_braces) {
-                    print_newline();
-                }
-            } else if (opt.brace_style === "expand") {
-                if (last_type !== 'TK_OPERATOR') {
-                    if (last_type === 'TK_EQUALS' ||
-                        (is_special_word (flags.last_text) && flags.last_text !== 'else')) {
-                        output_space_before_token = true;
-                    } else {
+                if (opt.brace_style === "expand-strict") {
+                    if (!empty_braces) {
                         print_newline();
                         print_newline();
                     }
                     }
-                }
-            } else { // collapse
-                if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
-                    if (last_type === 'TK_START_BLOCK') {
-                        print_newline();
-                    } else {
-                        output_space_before_token = true;
-                    }
-                } else {
-                    // if TK_OPERATOR or TK_START_EXPR
-                    if (is_array(previous_flags.mode) && flags.last_text === ',') {
-                        if (last_last_text === '}') {
-                            // }, { in array context
+                } else if (opt.brace_style === "expand") {
+                    if (last_type !== 'TK_OPERATOR') {
+                        if (last_type === 'TK_EQUALS' ||
+                            (is_special_word(flags.last_text) && flags.last_text !== 'else')) {
                             output_space_before_token = true;
                             output_space_before_token = true;
                         } else {
                         } else {
-                            print_newline(); // [a, b, c, {
+                            print_newline();
+                        }
+                    }
+                } else { // collapse
+                    if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
+                        if (last_type === 'TK_START_BLOCK') {
+                            print_newline();
+                        } else {
+                            output_space_before_token = true;
+                        }
+                    } else {
+                        // if TK_OPERATOR or TK_START_EXPR
+                        if (is_array(previous_flags.mode) && flags.last_text === ',') {
+                            if (last_last_text === '}') {
+                                // }, { in array context
+                                output_space_before_token = true;
+                            } else {
+                                print_newline(); // [a, b, c, {
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
+                print_token();
+                indent();
             }
             }
-            print_token();
-            indent();
-        }
 
 
-        function handle_end_block() {
-            // statements must all be closed when their container closes
-            while (flags.mode === MODE.Statement) {
-                restore_mode();
-            }
-            restore_mode();
-            if (opt.brace_style === "expand" || opt.brace_style === "expand-strict") {
-                if  (last_type !== 'TK_START_BLOCK') {
-                    print_newline();
+            function handle_end_block() {
+                // statements must all be closed when their container closes
+                while (flags.mode === MODE.Statement) {
+                    restore_mode();
                 }
                 }
-            } else {
-                // skip {}
-                if (last_type !== 'TK_START_BLOCK') {
-                    if (is_array(flags.mode) && opt.keep_array_indentation) {
-                        // we REALLY need a newline here, but newliner would skip that
-                        opt.keep_array_indentation = false;
+                restore_mode();
+                if (opt.brace_style === "expand" || opt.brace_style === "expand-strict") {
+                    if (last_type !== 'TK_START_BLOCK') {
                         print_newline();
                         print_newline();
-                        opt.keep_array_indentation = true;
+                    }
+                } else {
+                    // skip {}
+                    if (last_type !== 'TK_START_BLOCK') {
+                        if (is_array(flags.mode) && opt.keep_array_indentation) {
+                            // we REALLY need a newline here, but newliner would skip that
+                            opt.keep_array_indentation = false;
+                            print_newline();
+                            opt.keep_array_indentation = true;
 
 
-                    } else {
-                        print_newline();
+                        } else {
+                            print_newline();
+                        }
                     }
                     }
                 }
                 }
+                print_token();
             }
             }
-            print_token();
-        }
-
-        function handle_word() {
-            if (start_of_statement()) {
-                // The conditional starts the statement if appropriate.
-            } else if (wanted_newline && !is_expression(flags.mode) &&
-                (last_type !== 'TK_OPERATOR' || (flags.last_text === '--' || flags.last_text === '++')) &&
-                last_type !== 'TK_EQUALS' &&
-                (opt.preserve_newlines || flags.last_text !== 'var')) {
 
 
-                print_newline();
-            }
+            function handle_word() {
+                if (start_of_statement()) {
+                    // The conditional starts the statement if appropriate.
+                } else if (wanted_newline && !is_expression(flags.mode) &&
+                    (last_type !== 'TK_OPERATOR' || (flags.last_text === '--' || flags.last_text === '++')) &&
+                    last_type !== 'TK_EQUALS' &&
+                    (opt.preserve_newlines || flags.last_text !== 'var')) {
 
 
-            if (flags.do_block && !flags.do_while) {
-                if (token_text === 'while') {
-                    // do {} ## while ()
-                    output_space_before_token = true;
-                    print_token();
-                    output_space_before_token = true;
-                    flags.do_while = true;
-                    return;
-                } else {
-                    // do {} should always have while as the next word.
-                    // if we don't see the expected while, recover
                     print_newline();
                     print_newline();
-                    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 (flags.if_block) {
-                if (token_text !== 'else') {
-                    while (flags.mode === MODE.Statement) {
-                        restore_mode();
+                if (flags.do_block && !flags.do_while) {
+                    if (token_text === 'while') {
+                        // do {} ## while ()
+                        output_space_before_token = true;
+                        print_token();
+                        output_space_before_token = true;
+                        flags.do_while = true;
+                        return;
+                    } else {
+                        // do {} should always have while as the next word.
+                        // if we don't see the expected while, recover
+                        print_newline();
+                        flags.do_block = false;
                     }
                     }
-                    flags.if_block = false;
                 }
                 }
-            }
 
 
-            if (token_text === 'function') {
-                if (flags.var_line && last_type !== 'TK_EQUALS') {
-                    flags.var_line_reindented = true;
+                // 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 (flags.if_block) {
+                    if (token_text !== 'else') {
+                        while (flags.mode === MODE.Statement) {
+                            restore_mode();
+                        }
+                        flags.if_block = false;
+                    }
                 }
                 }
-                if ((just_added_newline() || flags.last_text === ';') && flags.last_text !== '{' && last_type !== 'TK_BLOCK_COMMENT' && last_type !== 'TK_COMMENT') {
-                    // make sure there is a nice clean space of at least one blank line
-                    // before a new function definition
-                    n_newlines = just_added_newline() ? n_newlines : 0;
-                    if (!opt.preserve_newlines) {
-                        n_newlines = 1;
+
+                if (token_text === 'function') {
+                    if (flags.var_line && last_type !== 'TK_EQUALS') {
+                        flags.var_line_reindented = true;
                     }
                     }
+                    if ((just_added_newline() || flags.last_text === ';') && flags.last_text !== '{' && last_type !== 'TK_BLOCK_COMMENT' && last_type !== 'TK_COMMENT') {
+                        // make sure there is a nice clean space of at least one blank line
+                        // before a new function definition
+                        n_newlines = just_added_newline() ? n_newlines : 0;
+                        if (!opt.preserve_newlines) {
+                            n_newlines = 1;
+                        }
 
 
-                    for (var i = 0; i < 2 - n_newlines; i++) {
-                        print_newline(true);
+                        for (var i = 0; i < 2 - n_newlines; i++) {
+                            print_newline(true);
+                        }
                     }
                     }
-                }
-                if (last_type === 'TK_WORD') {
-                    if  (flags.last_text === 'get' || flags.last_text === 'set' || flags.last_text === 'new' || flags.last_text === 'return') {
+                    if (last_type === 'TK_WORD') {
+                        if (flags.last_text === 'get' || flags.last_text === 'set' || flags.last_text === 'new' || flags.last_text === 'return') {
+                            output_space_before_token = true;
+                        } else {
+                            print_newline();
+                        }
+                    } else if (last_type === 'TK_OPERATOR' || flags.last_text === '=') {
+                        // foo = function
                         output_space_before_token = true;
                         output_space_before_token = true;
+                    } else if (is_expression(flags.mode)) {
+                        // (function
                     } else {
                     } else {
                         print_newline();
                         print_newline();
                     }
                     }
-                } else if (last_type === 'TK_OPERATOR' || flags.last_text === '=') {
-                    // foo = function
-                    output_space_before_token = true;
-                } else if (is_expression(flags.mode)) {
-                    // (function
-                } else {
-                    print_newline();
-                }
 
 
-                print_token();
-                flags.last_word = token_text;
-                return;
-            }
+                    print_token();
+                    flags.last_word = token_text;
+                    return;
+                }
 
 
-            if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) {
-                print_newline();
-                if (flags.case_body || opt.jslint_happy) {
-                    // switch cases following one another
-                    flags.indentation_level--;
-                    flags.case_body = false;
+                if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) {
+                    print_newline();
+                    if (flags.case_body || opt.jslint_happy) {
+                        // switch cases following one another
+                        flags.indentation_level--;
+                        flags.case_body = false;
+                    }
+                    print_token();
+                    flags.in_case = true;
+                    flags.in_case_statement = true;
+                    return;
                 }
                 }
-                print_token();
-                flags.in_case = true;
-                flags.in_case_statement = true;
-                return;
-            }
 
 
-            prefix = 'NONE';
+                prefix = 'NONE';
 
 
-            if (last_type === 'TK_END_BLOCK') {
-                if (!in_array(token_text, ['else', 'catch', 'finally'])) {
-                    prefix = 'NEWLINE';
-                } else {
-                    if (opt.brace_style === "expand" || opt.brace_style === "end-expand" || opt.brace_style === "expand-strict") {
+                if (last_type === 'TK_END_BLOCK') {
+                    if (!in_array(token_text, ['else', 'catch', 'finally'])) {
                         prefix = 'NEWLINE';
                         prefix = 'NEWLINE';
                     } else {
                     } else {
-                        prefix = 'SPACE';
-                        output_space_before_token = true;
+                        if (opt.brace_style === "expand" || opt.brace_style === "end-expand" || opt.brace_style === "expand-strict") {
+                            prefix = 'NEWLINE';
+                        } else {
+                            prefix = 'SPACE';
+                            output_space_before_token = true;
+                        }
                     }
                     }
-                }
-            } else if (last_type === 'TK_SEMICOLON' && flags.mode === MODE.BlockStatement) {
-                // TODO: Should this be for STATEMENT as well?
-                prefix = 'NEWLINE';
-            } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {
-                prefix = 'SPACE';
-            } else if (last_type === 'TK_STRING') {
-                prefix = 'NEWLINE';
-            } else if (last_type === 'TK_WORD') {
-                prefix = 'SPACE';
-            } else if (last_type === 'TK_START_BLOCK') {
-                prefix = 'NEWLINE';
-            } else if (last_type === 'TK_END_EXPR') {
-                output_space_before_token = true;
-                prefix = 'NEWLINE';
-            }
-
-            if (in_array(token_text, line_starters) && flags.last_text !== ')') {
-                if  (flags.last_text === 'else') {
+                } else if (last_type === 'TK_SEMICOLON' && flags.mode === MODE.BlockStatement) {
+                    // TODO: Should this be for STATEMENT as well?
+                    prefix = 'NEWLINE';
+                } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {
                     prefix = 'SPACE';
                     prefix = 'SPACE';
-                } else {
+                } else if (last_type === 'TK_STRING') {
+                    prefix = 'NEWLINE';
+                } else if (last_type === 'TK_WORD') {
+                    prefix = 'SPACE';
+                } else if (last_type === 'TK_START_BLOCK') {
+                    prefix = 'NEWLINE';
+                } else if (last_type === 'TK_END_EXPR') {
+                    output_space_before_token = true;
                     prefix = 'NEWLINE';
                     prefix = 'NEWLINE';
                 }
                 }
 
 
-            }
+                if (in_array(token_text, line_starters) && flags.last_text !== ')') {
+                    if (flags.last_text === 'else') {
+                        prefix = 'SPACE';
+                    } else {
+                        prefix = 'NEWLINE';
+                    }
 
 
-            if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
-                if (flags.mode !== MODE.ObjectLiteral) {
-                    allow_wrap_or_preserved_newline();
                 }
                 }
-            }
 
 
-            if (in_array(token_text, ['else', 'catch', 'finally'])) {
-                if (last_type !== 'TK_END_BLOCK' || opt.brace_style === "expand" || opt.brace_style === "end-expand" || opt.brace_style === "expand-strict") {
-                    print_newline();
-                } else {
-                    trim_output(true);
-                    // If we trimmed and there's something other than a close block before us
-                    // put a newline back in.  Handles '} // comment' scenario.
-                    if (output[output.length - 1] !== '}') {
-                        print_newline();
+                if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
+                    if (flags.mode !== MODE.ObjectLiteral) {
+                        allow_wrap_or_preserved_newline();
                     }
                     }
-                    output_space_before_token = true;
                 }
                 }
-            } else if (prefix === 'NEWLINE') {
-                if (is_special_word (flags.last_text)) {
-                    // no newline between 'return nnn'
-                    output_space_before_token = true;
-                } else if (last_type !== 'TK_END_EXPR') {
-                    if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && flags.last_text !== ':') {
-                        // no need to force newline on 'var': for (var x = 0...)
-                        if (token_text === 'if' && flags.last_word === 'else' && flags.last_text !== '{') {
-                            // no newline for } else if {
-                            output_space_before_token = true;
-                        } else {
-                            flags.var_line = false;
-                            flags.var_line_reindented = false;
+
+                if (in_array(token_text, ['else', 'catch', 'finally'])) {
+                    if (last_type !== 'TK_END_BLOCK' || opt.brace_style === "expand" || opt.brace_style === "end-expand" || opt.brace_style === "expand-strict") {
+                        print_newline();
+                    } else {
+                        trim_output(true);
+                        // If we trimmed and there's something other than a close block before us
+                        // put a newline back in.  Handles '} // comment' scenario.
+                        if (output[output.length - 1] !== '}') {
                             print_newline();
                             print_newline();
                         }
                         }
+                        output_space_before_token = true;
                     }
                     }
-                } else if (in_array(token_text, line_starters) && flags.last_text !== ')') {
-                    flags.var_line = false;
-                    flags.var_line_reindented = false;
-                    print_newline();
+                } else if (prefix === 'NEWLINE') {
+                    if (is_special_word(flags.last_text)) {
+                        // no newline between 'return nnn'
+                        output_space_before_token = true;
+                    } else if (last_type !== 'TK_END_EXPR') {
+                        if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && flags.last_text !== ':') {
+                            // no need to force newline on 'var': for (var x = 0...)
+                            if (token_text === 'if' && flags.last_word === 'else' && flags.last_text !== '{') {
+                                // no newline for } else if {
+                                output_space_before_token = true;
+                            } else {
+                                flags.var_line = false;
+                                flags.var_line_reindented = false;
+                                print_newline();
+                            }
+                        }
+                    } else if (in_array(token_text, line_starters) && flags.last_text !== ')') {
+                        flags.var_line = false;
+                        flags.var_line_reindented = false;
+                        print_newline();
+                    }
+                } else if (is_array(flags.mode) && flags.last_text === ',' && last_last_text === '}') {
+                    print_newline(); // }, in lists get a newline treatment
+                } else if (prefix === 'SPACE') {
+                    output_space_before_token = true;
                 }
                 }
-            } else if (is_array(flags.mode) && flags.last_text === ',' && last_last_text === '}') {
-                print_newline(); // }, in lists get a newline treatment
-            } else if (prefix === 'SPACE') {
-                output_space_before_token = true;
-            }
-            print_token();
-            flags.last_word = token_text;
-
-            if (token_text === 'var') {
-                flags.var_line = true;
-                flags.var_line_reindented = false;
-                flags.var_line_tainted = false;
-            }
-
-            if (token_text === 'do') {
-                flags.do_block = true;
-            }
-
-            if (token_text === 'if') {
-                flags.if_block = true;
-            }
-        }
-
-        function handle_semicolon() {
-            while (flags.mode === MODE.Statement && !flags.if_block) {
-                restore_mode();
-            }
-            print_token();
-            flags.var_line = false;
-            flags.var_line_reindented = false;
-            if (flags.mode === MODE.ObjectLiteral) {
-                // if we're in OBJECT mode and see a semicolon, its invalid syntax
-                // recover back to treating this as a BLOCK
-                flags.mode = MODE.BlockStatement;
-            }
-        }
+                print_token();
+                flags.last_word = token_text;
 
 
-        function handle_string() {
-            if (start_of_statement()) {
-                // The conditional starts the statement if appropriate.
-                // One difference - strings want at least a space before
-                output_space_before_token = true;
-            } else if (last_type === 'TK_WORD') {
-                output_space_before_token = true;
-            } else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
-                if (flags.mode !== MODE.ObjectLiteral) {
-                    allow_wrap_or_preserved_newline();
+                if (token_text === 'var') {
+                    flags.var_line = true;
+                    flags.var_line_reindented = false;
+                    flags.var_line_tainted = false;
                 }
                 }
-            } else {
-                print_newline();
-            }
-            print_token();
-        }
 
 
-        function handle_equals() {
-            if (flags.var_line) {
-                // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
-                flags.var_line_tainted = true;
-            }
-            output_space_before_token = true;
-            print_token();
-            output_space_before_token = true;
-        }
-
-        function handle_comma() {
-            if (flags.var_line) {
-                if (is_expression(flags.mode) || last_type === 'TK_END_BLOCK') {
-                    // do not break on comma, for(var a = 1, b = 2)
-                    flags.var_line_tainted = false;
+                if (token_text === 'do') {
+                    flags.do_block = true;
                 }
                 }
 
 
-                if (flags.var_line) {
-                    flags.var_line_reindented = true;
+                if (token_text === 'if') {
+                    flags.if_block = true;
                 }
                 }
+            }
 
 
+            function handle_semicolon() {
+                while (flags.mode === MODE.Statement && !flags.if_block) {
+                    restore_mode();
+                }
                 print_token();
                 print_token();
-
-                if (flags.var_line_tainted) {
-                    flags.var_line_tainted = false;
-                    print_newline();
-                } else {
-                    output_space_before_token = true;
+                flags.var_line = false;
+                flags.var_line_reindented = false;
+                if (flags.mode === MODE.ObjectLiteral) {
+                    // if we're in OBJECT mode and see a semicolon, its invalid syntax
+                    // recover back to treating this as a BLOCK
+                    flags.mode = MODE.BlockStatement;
                 }
                 }
-                return;
             }
             }
 
 
-            if (last_type === 'TK_END_BLOCK' && flags.mode !== MODE.Expression) {
-                print_token();
-                if (flags.mode === MODE.ObjectLiteral && flags.last_text === '}') {
-                    print_newline();
-                } else {
+            function handle_string() {
+                if (start_of_statement()) {
+                    // The conditional starts the statement if appropriate.
+                    // One difference - strings want at least a space before
                     output_space_before_token = true;
                     output_space_before_token = true;
-                }
-            } else {
-                if (flags.mode === MODE.ObjectLiteral) {
-                    print_token();
-                    print_newline();
-                } else {
-                    // EXPR or DO_BLOCK
-                    print_token();
+                } else if (last_type === 'TK_WORD') {
                     output_space_before_token = true;
                     output_space_before_token = true;
+                } else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
+                    if (flags.mode !== MODE.ObjectLiteral) {
+                        allow_wrap_or_preserved_newline();
+                    }
+                } else {
+                    print_newline();
                 }
                 }
+                print_token();
             }
             }
-        }
 
 
-        function handle_operator() {
-            var space_before = true;
-            var space_after = true;
-            if (is_special_word (flags.last_text)) {
-                // "return" had a special handling in TK_WORD. Now we need to return the favor
+            function handle_equals() {
+                if (flags.var_line) {
+                    // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
+                    flags.var_line_tainted = true;
+                }
                 output_space_before_token = true;
                 output_space_before_token = true;
                 print_token();
                 print_token();
-                return;
+                output_space_before_token = true;
             }
             }
 
 
-            // hack for actionscript's import .*;
-            if (token_text === '*' && last_type === 'TK_DOT' && !last_last_text.match(/^\d+$/)) {
-                print_token();
-                return;
-            }
+            function handle_comma() {
+                if (flags.var_line) {
+                    if (is_expression(flags.mode) || last_type === 'TK_END_BLOCK') {
+                        // do not break on comma, for(var a = 1, b = 2)
+                        flags.var_line_tainted = false;
+                    }
 
 
-            if (token_text === ':' && flags.in_case) {
-                flags.case_body = true;
-                indent();
-                print_token();
-                print_newline();
-                flags.in_case = false;
-                return;
-            }
+                    if (flags.var_line) {
+                        flags.var_line_reindented = true;
+                    }
 
 
-            if (token_text === '::') {
-                // no spaces around exotic namespacing syntax operator
-                print_token();
-                return;
-            }
+                    print_token();
+
+                    if (flags.var_line_tainted) {
+                        flags.var_line_tainted = false;
+                        print_newline();
+                    } else {
+                        output_space_before_token = true;
+                    }
+                    return;
+                }
 
 
-            // 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 (wanted_newline && (token_text === '--' || token_text === '++')) {
-                print_newline();
+                if (last_type === 'TK_END_BLOCK' && flags.mode !== MODE.Expression) {
+                    print_token();
+                    if (flags.mode === MODE.ObjectLiteral && flags.last_text === '}') {
+                        print_newline();
+                    } else {
+                        output_space_before_token = true;
+                    }
+                } else {
+                    if (flags.mode === MODE.ObjectLiteral) {
+                        print_token();
+                        print_newline();
+                    } else {
+                        // EXPR or DO_BLOCK
+                        print_token();
+                        output_space_before_token = true;
+                    }
+                }
             }
             }
 
 
-            if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array (flags.last_text, line_starters) || flags.last_text === ','))) {
-                // unary operators (and binary +/- pretending to be unary) special cases
+            function handle_operator() {
+                var space_before = true;
+                var space_after = true;
+                if (is_special_word(flags.last_text)) {
+                    // "return" had a special handling in TK_WORD. Now we need to return the favor
+                    output_space_before_token = true;
+                    print_token();
+                    return;
+                }
 
 
-                space_before = false;
-                space_after = false;
+                // hack for actionscript's import .*;
+                if (token_text === '*' && last_type === 'TK_DOT' && !last_last_text.match(/^\d+$/)) {
+                    print_token();
+                    return;
+                }
 
 
-                if  (flags.last_text === ';' && is_expression(flags.mode)) {
-                    // for (;; ++i)
-                    //        ^^^
-                    space_before = true;
+                if (token_text === ':' && flags.in_case) {
+                    flags.case_body = true;
+                    indent();
+                    print_token();
+                    print_newline();
+                    flags.in_case = false;
+                    return;
                 }
                 }
 
 
-                if (last_type === 'TK_WORD' && in_array (flags.last_text, line_starters)) {
-                    space_before = true;
+                if (token_text === '::') {
+                    // no spaces around exotic namespacing syntax operator
+                    print_token();
+                    return;
                 }
                 }
 
 
-                if ((flags.mode === MODE.BlockStatement || flags.mode === MODE.Statement) &&  (flags.last_text === '{' || flags.last_text === ';')) {
-                    // { foo; --i }
-                    // foo(); --bar;
+                // 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 (wanted_newline && (token_text === '--' || token_text === '++')) {
                     print_newline();
                     print_newline();
                 }
                 }
-            } else if (token_text === ':') {
-                if (flags.ternary_depth === 0) {
-                    if (flags.mode === MODE.BlockStatement) {
-                        flags.mode = MODE.ObjectLiteral;
-                    }
+
+                if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array(flags.last_text, line_starters) || flags.last_text === ','))) {
+                    // unary operators (and binary +/- pretending to be unary) special cases
+
                     space_before = false;
                     space_before = false;
-                } else {
-                    flags.ternary_depth -= 1;
-                }
-            } else if (token_text === '?') {
-                flags.ternary_depth += 1;
-            }
-            output_space_before_token = output_space_before_token || space_before;
-            print_token();
-            output_space_before_token = space_after;
-        }
+                    space_after = false;
 
 
-        function handle_block_comment() {
-            var lines = split_newlines(token_text);
-            var j; // iterator for this case
+                    if (flags.last_text === ';' && is_expression(flags.mode)) {
+                        // for (;; ++i)
+                        //        ^^^
+                        space_before = true;
+                    }
 
 
-            if (all_lines_start_with(lines.slice(1), '*')) {
-                // javadoc: reformat and reindent
-                print_newline(false, true);
-                print_token(lines[0]);
-                for (j = 1; j < lines.length; j++) {
-                    print_newline(false, true);
-                    print_token(' ' + trim(lines[j]));
+                    if (last_type === 'TK_WORD' && in_array(flags.last_text, line_starters)) {
+                        space_before = true;
+                    }
+
+                    if ((flags.mode === MODE.BlockStatement || flags.mode === MODE.Statement) && (flags.last_text === '{' || flags.last_text === ';')) {
+                        // { foo; --i }
+                        // foo(); --bar;
+                        print_newline();
+                    }
+                } else if (token_text === ':') {
+                    if (flags.ternary_depth === 0) {
+                        if (flags.mode === MODE.BlockStatement) {
+                            flags.mode = MODE.ObjectLiteral;
+                        }
+                        space_before = false;
+                    } else {
+                        flags.ternary_depth -= 1;
+                    }
+                } else if (token_text === '?') {
+                    flags.ternary_depth += 1;
                 }
                 }
+                output_space_before_token = output_space_before_token || space_before;
+                print_token();
+                output_space_before_token = space_after;
+            }
 
 
-            } else {
+            function handle_block_comment() {
+                var lines = split_newlines(token_text);
+                var j; // iterator for this case
 
 
-                // simple block comment: leave intact
-                if (lines.length > 1) {
-                    // multiline comment block starts with a new line
+                if (all_lines_start_with(lines.slice(1), '*')) {
+                    // javadoc: reformat and reindent
                     print_newline(false, true);
                     print_newline(false, true);
+                    print_token(lines[0]);
+                    for (j = 1; j < lines.length; j++) {
+                        print_newline(false, true);
+                        print_token(' ' + trim(lines[j]));
+                    }
+
                 } else {
                 } else {
-                    // single-line /* comment */ stays where it is
-                    if (last_type === 'TK_END_BLOCK') {
+
+                    // simple block comment: leave intact
+                    if (lines.length > 1) {
+                        // multiline comment block starts with a new line
                         print_newline(false, true);
                         print_newline(false, true);
                     } else {
                     } else {
-                        output_space_before_token = true;
-                    }
+                        // single-line /* comment */ stays where it is
+                        if (last_type === 'TK_END_BLOCK') {
+                            print_newline(false, true);
+                        } else {
+                            output_space_before_token = true;
+                        }
 
 
-                }
+                    }
 
 
-                print_token(lines[0]);
-                output.push("\n");
-                for (j = 1; j < lines.length; j++) {
-                    output.push(lines[j]);
+                    print_token(lines[0]);
                     output.push("\n");
                     output.push("\n");
+                    for (j = 1; j < lines.length; j++) {
+                        output.push(lines[j]);
+                        output.push("\n");
+                    }
+
                 }
                 }
 
 
+                if (!is_next('\n')) {
+                    print_newline(false, true);
+                }
             }
             }
 
 
-            if (!is_next('\n')) {
-                print_newline(false, true);
+            function handle_inline_comment() {
+                output_space_before_token = true;
+                print_token();
+                output_space_before_token = true;
             }
             }
-        }
 
 
-        function handle_inline_comment() {
-            output_space_before_token = true;
-            print_token();
-            output_space_before_token = true;
-        }
+            function handle_comment() {
+                if (wanted_newline) {
+                    print_newline(false, true);
+                }
+                if (flags.last_text === ',' && !wanted_newline) {
+                    trim_output(true);
+                }
 
 
-        function handle_comment() {
-            if (wanted_newline) {
+                output_space_before_token = true;
+                print_token();
                 print_newline(false, true);
                 print_newline(false, true);
             }
             }
-            if  (flags.last_text === ',' && !wanted_newline) {
-                trim_output(true);
-            }
 
 
-            output_space_before_token = true;
-            print_token();
-            print_newline(false, true);
-        }
+            function handle_dot() {
+                if (is_special_word(flags.last_text)) {
+                    output_space_before_token = true;
+                } else {
+                    // allow preserved newlines before dots in general
+                    // force newlines on dots after close paren when break_chained - for bar().baz()
+                    allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.break_chained_methods);
+                }
 
 
-        function handle_dot() {
-            if (is_special_word (flags.last_text)) {
-                output_space_before_token = true;
-            } else {
-                // allow preserved newlines before dots in general
-                // force newlines on dots after close paren when break_chained - for bar().baz()
-                allow_wrap_or_preserved_newline (flags.last_text === ')' && opt.break_chained_methods);
+                print_token();
             }
             }
 
 
-            print_token();
-        }
-
-        function handle_unknown() {
-            print_token();
-            if (token_text[token_text.length - 1] === '\n') {
-                print_newline();
+            function handle_unknown() {
+                print_token();
+                if (token_text[token_text.length - 1] === '\n') {
+                    print_newline();
+                }
             }
             }
         }
         }
-    }
+
+        self.onmessage = function (evt) {
+            var beautifier = new Beautifier(evt.data.js_source_text, evt.data.options);
+            var result = beautifier.beautify();
+            self.postMessage(result);
+        };
+    };
 
 
     module.exports.js_beautify = window.js_beautify = js_beautify;
     module.exports.js_beautify = window.js_beautify = js_beautify;
 }());
 }());

+ 17 - 17
apps/code-beautify/index.js

@@ -28,7 +28,18 @@ new Vue({
 
 
     methods: {
     methods: {
         format: function () {
         format: function () {
-            let txtResult = '';
+
+            let beauty = (result) => {
+                result = result.replace(/>/g, '&gt;').replace(/</g, '&lt;');
+                result = '<pre class="brush: ' + this.selectedType.toLowerCase() + ';toolbar:false;">' + result + '</pre>';
+                this.resultContent = result;
+
+                // 代码高亮
+                this.$nextTick(() => {
+                    SyntaxHighlighter.defaults['toolbar'] = false;
+                    SyntaxHighlighter.highlight();
+                })
+            };
 
 
             switch (this.selectedType) {
             switch (this.selectedType) {
                 case 'Javascript':
                 case 'Javascript':
@@ -45,35 +56,24 @@ new Vue({
                         unescape_strings: false,
                         unescape_strings: false,
                         wrap_line_length: "120"
                         wrap_line_length: "120"
                     };
                     };
-                    Tarp.require('./beautify.js');
-                    txtResult = js_beautify(this.sourceContent, opts);
+                    Tarp.require('./beautify.js').js_beautify(this.sourceContent, opts, result => beauty(result));
                     break;
                     break;
                 case 'CSS':
                 case 'CSS':
-                    Tarp.require('./beautify-css.js');
-                    txtResult = css_beautify(this.sourceContent);
+                    Tarp.require('./beautify-css.js').css_beautify(this.sourceContent, {}, result => beauty(result));
                     break;
                     break;
                 case 'HTML':
                 case 'HTML':
                     Tarp.require('./beautify-html.js');
                     Tarp.require('./beautify-html.js');
-                    txtResult = html_beautify(this.sourceContent);
+                    beauty(html_beautify(this.sourceContent));
                     break;
                     break;
                 case 'SQL':
                 case 'SQL':
                     Tarp.require('./vkbeautify.js');
                     Tarp.require('./vkbeautify.js');
-                    txtResult = vkbeautify.sql(this.sourceContent, 4);
+                    beauty(vkbeautify.sql(this.sourceContent, 4));
                     break;
                     break;
                 default:
                 default:
                     Tarp.require('./vkbeautify.js');
                     Tarp.require('./vkbeautify.js');
-                    txtResult = vkbeautify.xml(this.sourceContent);
+                    beauty(vkbeautify.xml(this.sourceContent));
             }
             }
 
 
-            txtResult = txtResult.replace(/>/g, '&gt;').replace(/</g, '&lt;');
-            txtResult = '<pre class="brush: ' + this.selectedType.toLowerCase() + ';toolbar:false;">' + txtResult + '</pre>';
-            this.resultContent = txtResult;
-
-            // 代码高亮
-            this.$nextTick(() => {
-                SyntaxHighlighter.defaults['toolbar'] = false;
-                SyntaxHighlighter.highlight();
-            })
         }
         }
     }
     }
 });
 });

+ 1 - 1
apps/manifest.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "WEB前端助手(FeHelper)",
   "name": "WEB前端助手(FeHelper)",
-  "version": "2018.04.2419",
+  "version": "2018.04.2519",
   "manifest_version": 2,
   "manifest_version": 2,
   "default_locale": "zh_CN",
   "default_locale": "zh_CN",
   "description": "FE助手:包括JSON格式化、二维码生成与解码、信息编解码、代码压缩、美化、页面取色、正则表达式、时间转换工具、编码规范检测、页面性能检测、Ajax接口调试",
   "description": "FE助手:包括JSON格式化、二维码生成与解码、信息编解码、代码压缩、美化、页面取色、正则表达式、时间转换工具、编码规范检测、页面性能检测、Ajax接口调试",