59843e205fe47066f8c47129a636dc3014b37585
[moodle.git] / lib / editor / atto / plugins / html / yui / src / beautify / js / beautify.js
1 /*jshint curly:false, eqeqeq:true, laxbreak:true, noempty:false */
2 /* AUTO-GENERATED. DO NOT MODIFY. */
3 /* see js/src/javascript/index.js */
4 /*
6   The MIT License (MIT)
8   Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
10   Permission is hereby granted, free of charge, to any person
11   obtaining a copy of this software and associated documentation files
12   (the "Software"), to deal in the Software without restriction,
13   including without limitation the rights to use, copy, modify, merge,
14   publish, distribute, sublicense, and/or sell copies of the Software,
15   and to permit persons to whom the Software is furnished to do so,
16   subject to the following conditions:
18   The above copyright notice and this permission notice shall be
19   included in all copies or substantial portions of the Software.
21   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28   SOFTWARE.
30  JS Beautifier
31 ---------------
34   Written by Einar Lielmanis, <einar@jsbeautifier.org>
35       http://jsbeautifier.org/
37   Originally converted to javascript by Vital, <vital76@gmail.com>
38   "End braces on own line" added by Chris J. Shull, <chrisjshull@gmail.com>
39   Parsing improvements for brace-less statements by Liam Newman <bitwiseman@gmail.com>
42   Usage:
43     js_beautify(js_source_text);
44     js_beautify(js_source_text, options);
46   The options are:
47     indent_size (default 4)          - indentation size,
48     indent_char (default space)      - character to indent with,
49     preserve_newlines (default true) - whether existing line breaks should be preserved,
50     max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk,
52     jslint_happy (default false) - if true, then jslint-stricter mode is enforced.
54             jslint_happy        !jslint_happy
55             ---------------------------------
56             function ()         function()
58             switch () {         switch() {
59             case 1:               case 1:
60               break;                break;
61             }                   }
63     space_after_anon_function (default false) - should the space before an anonymous function's parens be added, "function()" vs "function ()",
64           NOTE: This option is overriden by jslint_happy (i.e. if jslint_happy is true, space_after_anon_function is true by design)
66     brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "none" | any of the former + ",preserve-inline"
67             put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line, or attempt to keep them where they are.
68             preserve-inline will try to preserve inline blocks of curly braces
70     space_before_conditional (default true) - should the space before conditional statement be added, "if(true)" vs "if (true)",
72     unescape_strings (default false) - should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65"
74     wrap_line_length (default unlimited) - lines should wrap at next opportunity after this number of characters.
75           NOTE: This is not a hard limit. Lines will continue until a point where a newline would
76                 be preserved if it were present.
78     end_with_newline (default false)  - end output with a newline
81     e.g
83     js_beautify(js_source_text, {
84       'indent_size': 1,
85       'indent_char': '\t'
86     });
88 */
90 (function() {
91 var legacy_beautify_js =
92 /******/ (function(modules) { // webpackBootstrap
93 /******/        // The module cache
94 /******/        var installedModules = {};
95 /******/
96 /******/        // The require function
97 /******/        function __webpack_require__(moduleId) {
98 /******/
99 /******/                // Check if module is in cache
100 /******/                if(installedModules[moduleId]) {
101 /******/                        return installedModules[moduleId].exports;
102 /******/                }
103 /******/                // Create a new module (and put it into the cache)
104 /******/                var module = installedModules[moduleId] = {
105 /******/                        i: moduleId,
106 /******/                        l: false,
107 /******/                        exports: {}
108 /******/                };
109 /******/
110 /******/                // Execute the module function
111 /******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
112 /******/
113 /******/                // Flag the module as loaded
114 /******/                module.l = true;
115 /******/
116 /******/                // Return the exports of the module
117 /******/                return module.exports;
118 /******/        }
119 /******/
120 /******/
121 /******/        // expose the modules object (__webpack_modules__)
122 /******/        __webpack_require__.m = modules;
123 /******/
124 /******/        // expose the module cache
125 /******/        __webpack_require__.c = installedModules;
126 /******/
127 /******/        // identity function for calling harmony imports with the correct context
128 /******/        __webpack_require__.i = function(value) { return value; };
129 /******/
130 /******/        // define getter function for harmony exports
131 /******/        __webpack_require__.d = function(exports, name, getter) {
132 /******/                if(!__webpack_require__.o(exports, name)) {
133 /******/                        Object.defineProperty(exports, name, {
134 /******/                                configurable: false,
135 /******/                                enumerable: true,
136 /******/                                get: getter
137 /******/                        });
138 /******/                }
139 /******/        };
140 /******/
141 /******/        // getDefaultExport function for compatibility with non-harmony modules
142 /******/        __webpack_require__.n = function(module) {
143 /******/                var getter = module && module.__esModule ?
144 /******/                        function getDefault() { return module['default']; } :
145 /******/                        function getModuleExports() { return module; };
146 /******/                __webpack_require__.d(getter, 'a', getter);
147 /******/                return getter;
148 /******/        };
149 /******/
150 /******/        // Object.prototype.hasOwnProperty.call
151 /******/        __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
152 /******/
153 /******/        // __webpack_public_path__
154 /******/        __webpack_require__.p = "";
155 /******/
156 /******/        // Load entry module and return exports
157 /******/        return __webpack_require__(__webpack_require__.s = 6);
158 /******/ })
159 /************************************************************************/
160 /******/ ([
161 /* 0 */
162 /***/ (function(module, exports) {
164 /* jshint curly: false */
165 // This section of code is taken from acorn.
166 //
167 // Acorn was written by Marijn Haverbeke and released under an MIT
168 // license. The Unicode regexps (for identifiers and whitespace) were
169 // taken from [Esprima](http://esprima.org) by Ariya Hidayat.
170 //
171 // Git repositories for Acorn are available at
172 //
173 //     http://marijnhaverbeke.nl/git/acorn
174 //     https://github.com/marijnh/acorn.git
176 // ## Character categories
178 // Big ugly regular expressions that match characters in the
179 // whitespace, identifier, and identifier-start categories. These
180 // are only applied when a character is found to actually have a
181 // code point above 128.
183 var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; // jshint ignore:line
184 var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
185 var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
186 var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
187 var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
189 // Whether a single character denotes a newline.
191 exports.newline = /[\n\r\u2028\u2029]/;
193 // Matches a whole line break (where CRLF is considered a single
194 // line break). Used to count lines.
196 // in javascript, these two differ
197 // in python they are the same, different methods are called on them
198 exports.lineBreak = new RegExp('\r\n|' + exports.newline.source);
199 exports.allLineBreaks = new RegExp(exports.lineBreak.source, 'g');
202 // Test whether a given character code starts an identifier.
204 exports.isIdentifierStart = function(code) {
205     // permit $ (36) and @ (64). @ is used in ES7 decorators.
206     if (code < 65) return code === 36 || code === 64;
207     // 65 through 91 are uppercase letters.
208     if (code < 91) return true;
209     // permit _ (95).
210     if (code < 97) return code === 95;
211     // 97 through 123 are lowercase letters.
212     if (code < 123) return true;
213     return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
214 };
216 // Test whether a given character is part of an identifier.
218 exports.isIdentifierChar = function(code) {
219     if (code < 48) return code === 36;
220     if (code < 58) return true;
221     if (code < 65) return false;
222     if (code < 91) return true;
223     if (code < 97) return code === 95;
224     if (code < 123) return true;
225     return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
226 };
229 /***/ }),
230 /* 1 */
231 /***/ (function(module, exports, __webpack_require__) {
233 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
234 /*
236     The MIT License (MIT)
238     Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
240     Permission is hereby granted, free of charge, to any person
241     obtaining a copy of this software and associated documentation files
242     (the "Software"), to deal in the Software without restriction,
243     including without limitation the rights to use, copy, modify, merge,
244     publish, distribute, sublicense, and/or sell copies of the Software,
245     and to permit persons to whom the Software is furnished to do so,
246     subject to the following conditions:
248     The above copyright notice and this permission notice shall be
249     included in all copies or substantial portions of the Software.
251     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
252     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
253     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
254     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
255     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
256     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
257     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
258     SOFTWARE.
259 */
261 var mergeOpts = __webpack_require__(3).mergeOpts;
262 var acorn = __webpack_require__(0);
263 var Output = __webpack_require__(4).Output;
264 var Tokenizer = __webpack_require__(7).Tokenizer;
266 function remove_redundant_indentation(output, frame) {
267     // This implementation is effective but has some issues:
268     //     - can cause line wrap to happen too soon due to indent removal
269     //           after wrap points are calculated
270     // These issues are minor compared to ugly indentation.
272     if (frame.multiline_frame ||
273         frame.mode === MODE.ForInitializer ||
274         frame.mode === MODE.Conditional) {
275         return;
276     }
278     // remove one indent from each line inside this section
279     var start_index = frame.start_line_index;
281     output.remove_indent(start_index);
284 function in_array(what, arr) {
285     for (var i = 0; i < arr.length; i += 1) {
286         if (arr[i] === what) {
287             return true;
288         }
289     }
290     return false;
293 function trim(s) {
294     return s.replace(/^\s+|\s+$/g, '');
297 function ltrim(s) {
298     return s.replace(/^\s+/g, '');
301 // function rtrim(s) {
302 //     return s.replace(/\s+$/g, '');
303 // }
306 function generateMapFromStrings(list) {
307     var result = {};
308     for (var x = 0; x < list.length; x++) {
309         // make the mapped names underscored instead of dash
310         result[list[x].replace(/-/g, '_')] = list[x];
311     }
312     return result;
315 function sanitizeOperatorPosition(opPosition) {
316     opPosition = opPosition || OPERATOR_POSITION.before_newline;
318     if (!in_array(opPosition, validPositionValues)) {
319         throw new Error("Invalid Option Value: The option 'operator_position' must be one of the following values\n" +
320             validPositionValues +
321             "\nYou passed in: '" + opPosition + "'");
322     }
324     return opPosition;
327 var validPositionValues = ['before-newline', 'after-newline', 'preserve-newline'];
329 // Generate map from array
330 var OPERATOR_POSITION = generateMapFromStrings(validPositionValues);
332 var OPERATOR_POSITION_BEFORE_OR_PRESERVE = [OPERATOR_POSITION.before_newline, OPERATOR_POSITION.preserve_newline];
334 var MODE = {
335     BlockStatement: 'BlockStatement', // 'BLOCK'
336     Statement: 'Statement', // 'STATEMENT'
337     ObjectLiteral: 'ObjectLiteral', // 'OBJECT',
338     ArrayLiteral: 'ArrayLiteral', //'[EXPRESSION]',
339     ForInitializer: 'ForInitializer', //'(FOR-EXPRESSION)',
340     Conditional: 'Conditional', //'(COND-EXPRESSION)',
341     Expression: 'Expression' //'(EXPRESSION)'
342 };
344 function Beautifier(js_source_text, options) {
345     "use strict";
346     var output;
347     var tokens = [],
348         token_pos;
349     var tokenizer;
350     var current_token;
351     var last_type, last_last_text, indent_string;
352     var flags, previous_flags, flag_store;
353     var prefix;
355     var handlers, opt;
356     var baseIndentString = '';
358     handlers = {
359         'TK_START_EXPR': handle_start_expr,
360         'TK_END_EXPR': handle_end_expr,
361         'TK_START_BLOCK': handle_start_block,
362         'TK_END_BLOCK': handle_end_block,
363         'TK_WORD': handle_word,
364         'TK_RESERVED': handle_word,
365         'TK_SEMICOLON': handle_semicolon,
366         'TK_STRING': handle_string,
367         'TK_EQUALS': handle_equals,
368         'TK_OPERATOR': handle_operator,
369         'TK_COMMA': handle_comma,
370         'TK_BLOCK_COMMENT': handle_block_comment,
371         'TK_COMMENT': handle_comment,
372         'TK_DOT': handle_dot,
373         'TK_UNKNOWN': handle_unknown,
374         'TK_EOF': handle_eof
375     };
377     function create_flags(flags_base, mode) {
378         var next_indent_level = 0;
379         if (flags_base) {
380             next_indent_level = flags_base.indentation_level;
381             if (!output.just_added_newline() &&
382                 flags_base.line_indent_level > next_indent_level) {
383                 next_indent_level = flags_base.line_indent_level;
384             }
385         }
387         var next_flags = {
388             mode: mode,
389             parent: flags_base,
390             last_text: flags_base ? flags_base.last_text : '', // last token text
391             last_word: flags_base ? flags_base.last_word : '', // last 'TK_WORD' passed
392             declaration_statement: false,
393             declaration_assignment: false,
394             multiline_frame: false,
395             inline_frame: false,
396             if_block: false,
397             else_block: false,
398             do_block: false,
399             do_while: false,
400             import_block: false,
401             in_case_statement: false, // switch(..){ INSIDE HERE }
402             in_case: false, // we're on the exact line with "case 0:"
403             case_body: false, // the indented case-action block
404             indentation_level: next_indent_level,
405             line_indent_level: flags_base ? flags_base.line_indent_level : next_indent_level,
406             start_line_index: output.get_line_number(),
407             ternary_depth: 0
408         };
409         return next_flags;
410     }
412     // Some interpreters have unexpected results with foo = baz || bar;
413     options = options ? options : {};
415     // Allow the setting of language/file-type specific options
416     // with inheritance of overall settings
417     options = mergeOpts(options, 'js');
419     opt = {};
421     // compatibility, re
422     if (options.brace_style === "expand-strict") { //graceful handling of deprecated option
423         options.brace_style = "expand";
424     } else if (options.brace_style === "collapse-preserve-inline") { //graceful handling of deprecated option
425         options.brace_style = "collapse,preserve-inline";
426     } else if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
427         options.brace_style = options.braces_on_own_line ? "expand" : "collapse";
428     } else if (!options.brace_style) { //Nothing exists to set it
429         options.brace_style = "collapse";
430     }
432     //preserve-inline in delimited string will trigger brace_preserve_inline, everything
433     //else is considered a brace_style and the last one only will have an effect
434     var brace_style_split = options.brace_style.split(/[^a-zA-Z0-9_\-]+/);
435     opt.brace_preserve_inline = false; //Defaults in case one or other was not specified in meta-option
436     opt.brace_style = "collapse";
437     for (var bs = 0; bs < brace_style_split.length; bs++) {
438         if (brace_style_split[bs] === "preserve-inline") {
439             opt.brace_preserve_inline = true;
440         } else {
441             opt.brace_style = brace_style_split[bs];
442         }
443     }
445     opt.indent_size = options.indent_size ? parseInt(options.indent_size, 10) : 4;
446     opt.indent_char = options.indent_char ? options.indent_char : ' ';
447     opt.eol = options.eol ? options.eol : 'auto';
448     opt.preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
449     opt.unindent_chained_methods = (options.unindent_chained_methods === undefined) ? false : options.unindent_chained_methods;
450     opt.break_chained_methods = (options.break_chained_methods === undefined) ? false : options.break_chained_methods;
451     opt.max_preserve_newlines = (options.max_preserve_newlines === undefined) ? 0 : parseInt(options.max_preserve_newlines, 10);
452     opt.space_in_paren = (options.space_in_paren === undefined) ? false : options.space_in_paren;
453     opt.space_in_empty_paren = (options.space_in_empty_paren === undefined) ? false : options.space_in_empty_paren;
454     opt.jslint_happy = (options.jslint_happy === undefined) ? false : options.jslint_happy;
455     opt.space_after_anon_function = (options.space_after_anon_function === undefined) ? false : options.space_after_anon_function;
456     opt.keep_array_indentation = (options.keep_array_indentation === undefined) ? false : options.keep_array_indentation;
457     opt.space_before_conditional = (options.space_before_conditional === undefined) ? true : options.space_before_conditional;
458     opt.unescape_strings = (options.unescape_strings === undefined) ? false : options.unescape_strings;
459     opt.wrap_line_length = (options.wrap_line_length === undefined) ? 0 : parseInt(options.wrap_line_length, 10);
460     opt.e4x = (options.e4x === undefined) ? false : options.e4x;
461     opt.end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
462     opt.comma_first = (options.comma_first === undefined) ? false : options.comma_first;
463     opt.operator_position = sanitizeOperatorPosition(options.operator_position);
465     // For testing of beautify ignore:start directive
466     opt.test_output_raw = (options.test_output_raw === undefined) ? false : options.test_output_raw;
468     // force opt.space_after_anon_function to true if opt.jslint_happy
469     if (opt.jslint_happy) {
470         opt.space_after_anon_function = true;
471     }
473     if (options.indent_with_tabs) {
474         opt.indent_char = '\t';
475         opt.indent_size = 1;
476     }
478     if (opt.eol === 'auto') {
479         opt.eol = '\n';
480         if (js_source_text && acorn.lineBreak.test(js_source_text || '')) {
481             opt.eol = js_source_text.match(acorn.lineBreak)[0];
482         }
483     }
485     opt.eol = opt.eol.replace(/\\r/, '\r').replace(/\\n/, '\n');
487     //----------------------------------
488     indent_string = '';
489     while (opt.indent_size > 0) {
490         indent_string += opt.indent_char;
491         opt.indent_size -= 1;
492     }
494     var preindent_index = 0;
495     if (js_source_text && js_source_text.length) {
496         while ((js_source_text.charAt(preindent_index) === ' ' ||
497                 js_source_text.charAt(preindent_index) === '\t')) {
498             preindent_index += 1;
499         }
500         baseIndentString = js_source_text.substring(0, preindent_index);
501         js_source_text = js_source_text.substring(preindent_index);
502     }
504     last_type = 'TK_START_BLOCK'; // last token type
505     last_last_text = ''; // pre-last token text
506     output = new Output(indent_string, baseIndentString);
508     // If testing the ignore directive, start with output disable set to true
509     output.raw = opt.test_output_raw;
512     // Stack of parsing/formatting states, including MODE.
513     // We tokenize, parse, and output in an almost purely a forward-only stream of token input
514     // and formatted output.  This makes the beautifier less accurate than full parsers
515     // but also far more tolerant of syntax errors.
516     //
517     // For example, the default mode is MODE.BlockStatement. If we see a '{' we push a new frame of type
518     // MODE.BlockStatement on the the stack, even though it could be object literal.  If we later
519     // encounter a ":", we'll switch to to MODE.ObjectLiteral.  If we then see a ";",
520     // most full parsers would die, but the beautifier gracefully falls back to
521     // MODE.BlockStatement and continues on.
522     flag_store = [];
523     set_mode(MODE.BlockStatement);
525     this.beautify = function() {
527         /*jshint onevar:true */
528         var sweet_code;
529         tokenizer = new Tokenizer(js_source_text, opt, indent_string);
530         tokens = tokenizer.tokenize();
531         token_pos = 0;
533         current_token = get_token();
534         while (current_token) {
535             handlers[current_token.type]();
537             last_last_text = flags.last_text;
538             last_type = current_token.type;
539             flags.last_text = current_token.text;
541             token_pos += 1;
542             current_token = get_token();
543         }
545         sweet_code = output.get_code(opt.end_with_newline, opt.eol);
547         return sweet_code;
548     };
550     function handle_whitespace_and_comments(local_token, preserve_statement_flags) {
551         var newlines = local_token.newlines;
552         var keep_whitespace = opt.keep_array_indentation && is_array(flags.mode);
553         var temp_token = current_token;
555         for (var h = 0; h < local_token.comments_before.length; h++) {
556             // The cleanest handling of inline comments is to treat them as though they aren't there.
557             // Just continue formatting and the behavior should be logical.
558             // Also ignore unknown tokens.  Again, this should result in better behavior.
559             current_token = local_token.comments_before[h];
560             handle_whitespace_and_comments(current_token, preserve_statement_flags);
561             handlers[current_token.type](preserve_statement_flags);
562         }
563         current_token = temp_token;
565         if (keep_whitespace) {
566             for (var i = 0; i < newlines; i += 1) {
567                 print_newline(i > 0, preserve_statement_flags);
568             }
569         } else {
570             if (opt.max_preserve_newlines && newlines > opt.max_preserve_newlines) {
571                 newlines = opt.max_preserve_newlines;
572             }
574             if (opt.preserve_newlines) {
575                 if (local_token.newlines > 1) {
576                     print_newline(false, preserve_statement_flags);
577                     for (var j = 1; j < newlines; j += 1) {
578                         print_newline(true, preserve_statement_flags);
579                     }
580                 }
581             }
582         }
584     }
586     // we could use just string.split, but
587     // IE doesn't like returning empty strings
588     function split_linebreaks(s) {
589         //return s.split(/\x0d\x0a|\x0a/);
591         s = s.replace(acorn.allLineBreaks, '\n');
592         var out = [],
593             idx = s.indexOf("\n");
594         while (idx !== -1) {
595             out.push(s.substring(0, idx));
596             s = s.substring(idx + 1);
597             idx = s.indexOf("\n");
598         }
599         if (s.length) {
600             out.push(s);
601         }
602         return out;
603     }
605     var newline_restricted_tokens = ['break', 'continue', 'return', 'throw', 'yield'];
607     function allow_wrap_or_preserved_newline(force_linewrap) {
608         force_linewrap = (force_linewrap === undefined) ? false : force_linewrap;
610         // Never wrap the first token on a line
611         if (output.just_added_newline()) {
612             return;
613         }
615         var shouldPreserveOrForce = (opt.preserve_newlines && current_token.wanted_newline) || force_linewrap;
616         var operatorLogicApplies = in_array(flags.last_text, tokenizer.positionable_operators) || in_array(current_token.text, tokenizer.positionable_operators);
618         if (operatorLogicApplies) {
619             var shouldPrintOperatorNewline = (
620                     in_array(flags.last_text, tokenizer.positionable_operators) &&
621                     in_array(opt.operator_position, OPERATOR_POSITION_BEFORE_OR_PRESERVE)
622                 ) ||
623                 in_array(current_token.text, tokenizer.positionable_operators);
624             shouldPreserveOrForce = shouldPreserveOrForce && shouldPrintOperatorNewline;
625         }
627         if (shouldPreserveOrForce) {
628             print_newline(false, true);
629         } else if (opt.wrap_line_length) {
630             if (last_type === 'TK_RESERVED' && in_array(flags.last_text, newline_restricted_tokens)) {
631                 // These tokens should never have a newline inserted
632                 // between them and the following expression.
633                 return;
634             }
635             var proposed_line_length = output.current_line.get_character_count() + current_token.text.length +
636                 (output.space_before_token ? 1 : 0);
637             if (proposed_line_length >= opt.wrap_line_length) {
638                 print_newline(false, true);
639             }
640         }
641     }
643     function print_newline(force_newline, preserve_statement_flags) {
644         if (!preserve_statement_flags) {
645             if (flags.last_text !== ';' && flags.last_text !== ',' && flags.last_text !== '=' && last_type !== 'TK_OPERATOR') {
646                 var next_token = get_token(1);
647                 while (flags.mode === MODE.Statement &&
648                     !(flags.if_block && next_token && next_token.type === 'TK_RESERVED' && next_token.text === 'else') &&
649                     !flags.do_block) {
650                     restore_mode();
651                 }
652             }
653         }
655         if (output.add_new_line(force_newline)) {
656             flags.multiline_frame = true;
657         }
658     }
660     function print_token_line_indentation() {
661         if (output.just_added_newline()) {
662             if (opt.keep_array_indentation && is_array(flags.mode) && current_token.wanted_newline) {
663                 output.current_line.push(current_token.whitespace_before);
664                 output.space_before_token = false;
665             } else if (output.set_indent(flags.indentation_level)) {
666                 flags.line_indent_level = flags.indentation_level;
667             }
668         }
669     }
671     function print_token(printable_token) {
672         if (output.raw) {
673             output.add_raw_token(current_token);
674             return;
675         }
677         if (opt.comma_first && last_type === 'TK_COMMA' &&
678             output.just_added_newline()) {
679             if (output.previous_line.last() === ',') {
680                 var popped = output.previous_line.pop();
681                 // if the comma was already at the start of the line,
682                 // pull back onto that line and reprint the indentation
683                 if (output.previous_line.is_empty()) {
684                     output.previous_line.push(popped);
685                     output.trim(true);
686                     output.current_line.pop();
687                     output.trim();
688                 }
690                 // add the comma in front of the next token
691                 print_token_line_indentation();
692                 output.add_token(',');
693                 output.space_before_token = true;
694             }
695         }
697         printable_token = printable_token || current_token.text;
698         print_token_line_indentation();
699         output.add_token(printable_token);
700     }
702     function indent() {
703         flags.indentation_level += 1;
704     }
706     function deindent() {
707         if (flags.indentation_level > 0 &&
708             ((!flags.parent) || flags.indentation_level > flags.parent.indentation_level)) {
709             flags.indentation_level -= 1;
711         }
712     }
714     function set_mode(mode) {
715         if (flags) {
716             flag_store.push(flags);
717             previous_flags = flags;
718         } else {
719             previous_flags = create_flags(null, mode);
720         }
722         flags = create_flags(previous_flags, mode);
723     }
725     function is_array(mode) {
726         return mode === MODE.ArrayLiteral;
727     }
729     function is_expression(mode) {
730         return in_array(mode, [MODE.Expression, MODE.ForInitializer, MODE.Conditional]);
731     }
733     function restore_mode() {
734         if (flag_store.length > 0) {
735             previous_flags = flags;
736             flags = flag_store.pop();
737             if (previous_flags.mode === MODE.Statement && !opt.unindent_chained_methods) {
738                 remove_redundant_indentation(output, previous_flags);
739             }
740         }
741     }
743     function start_of_object_property() {
744         return flags.parent.mode === MODE.ObjectLiteral && flags.mode === MODE.Statement && (
745             (flags.last_text === ':' && flags.ternary_depth === 0) || (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['get', 'set'])));
746     }
748     function start_of_statement() {
749         if (
750             (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const']) && current_token.type === 'TK_WORD') ||
751             (last_type === 'TK_RESERVED' && flags.last_text === 'do') ||
752             (last_type === 'TK_RESERVED' && in_array(flags.last_text, newline_restricted_tokens) && !current_token.wanted_newline) ||
753             (last_type === 'TK_RESERVED' && flags.last_text === 'else' &&
754                 !(current_token.type === 'TK_RESERVED' && current_token.text === 'if' && !current_token.comments_before.length)) ||
755             (last_type === 'TK_END_EXPR' && (previous_flags.mode === MODE.ForInitializer || previous_flags.mode === MODE.Conditional)) ||
756             (last_type === 'TK_WORD' && flags.mode === MODE.BlockStatement &&
757                 !flags.in_case &&
758                 !(current_token.text === '--' || current_token.text === '++') &&
759                 last_last_text !== 'function' &&
760                 current_token.type !== 'TK_WORD' && current_token.type !== 'TK_RESERVED') ||
761             (flags.mode === MODE.ObjectLiteral && (
762                 (flags.last_text === ':' && flags.ternary_depth === 0) || (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['get', 'set']))))
763         ) {
765             set_mode(MODE.Statement);
766             if (!opt.unindent_chained_methods) {
767                 indent();
768             }
770             handle_whitespace_and_comments(current_token, true);
772             // Issue #276:
773             // If starting a new statement with [if, for, while, do], push to a new line.
774             // if (a) if (b) if(c) d(); else e(); else f();
775             if (!start_of_object_property()) {
776                 allow_wrap_or_preserved_newline(
777                     current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['do', 'for', 'if', 'while']));
778             }
780             return true;
781         }
782         return false;
783     }
785     function all_lines_start_with(lines, c) {
786         for (var i = 0; i < lines.length; i++) {
787             var line = trim(lines[i]);
788             if (line.charAt(0) !== c) {
789                 return false;
790             }
791         }
792         return true;
793     }
795     function each_line_matches_indent(lines, indent) {
796         var i = 0,
797             len = lines.length,
798             line;
799         for (; i < len; i++) {
800             line = lines[i];
801             // allow empty lines to pass through
802             if (line && line.indexOf(indent) !== 0) {
803                 return false;
804             }
805         }
806         return true;
807     }
809     function is_special_word(word) {
810         return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);
811     }
813     function get_token(offset) {
814         var index = token_pos + (offset || 0);
815         return (index < 0 || index >= tokens.length) ? null : tokens[index];
816     }
818     function handle_start_expr() {
819         // The conditional starts the statement if appropriate.
820         if (!start_of_statement()) {
821             handle_whitespace_and_comments(current_token);
822         }
824         var next_mode = MODE.Expression;
825         if (current_token.text === '[') {
827             if (last_type === 'TK_WORD' || flags.last_text === ')') {
828                 // this is array index specifier, break immediately
829                 // a[x], fn()[x]
830                 if (last_type === 'TK_RESERVED' && in_array(flags.last_text, tokenizer.line_starters)) {
831                     output.space_before_token = true;
832                 }
833                 set_mode(next_mode);
834                 print_token();
835                 indent();
836                 if (opt.space_in_paren) {
837                     output.space_before_token = true;
838                 }
839                 return;
840             }
842             next_mode = MODE.ArrayLiteral;
843             if (is_array(flags.mode)) {
844                 if (flags.last_text === '[' ||
845                     (flags.last_text === ',' && (last_last_text === ']' || last_last_text === '}'))) {
846                     // ], [ goes to new line
847                     // }, [ goes to new line
848                     if (!opt.keep_array_indentation) {
849                         print_newline();
850                     }
851                 }
852             }
854         } else {
855             if (last_type === 'TK_RESERVED' && flags.last_text === 'for') {
856                 next_mode = MODE.ForInitializer;
857             } else if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['if', 'while'])) {
858                 next_mode = MODE.Conditional;
859             } else {
860                 // next_mode = MODE.Expression;
861             }
862         }
864         if (flags.last_text === ';' || last_type === 'TK_START_BLOCK') {
865             print_newline();
866         } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || flags.last_text === '.') {
867             // TODO: Consider whether forcing this is required.  Review failing tests when removed.
868             allow_wrap_or_preserved_newline(current_token.wanted_newline);
869             // do nothing on (( and )( and ][ and ]( and .(
870         } else if (!(last_type === 'TK_RESERVED' && current_token.text === '(') && last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
871             output.space_before_token = true;
872         } else if ((last_type === 'TK_RESERVED' && (flags.last_word === 'function' || flags.last_word === 'typeof')) ||
873             (flags.last_text === '*' &&
874                 (in_array(last_last_text, ['function', 'yield']) ||
875                     (flags.mode === MODE.ObjectLiteral && in_array(last_last_text, ['{', ',']))))) {
876             // function() vs function ()
877             // yield*() vs yield* ()
878             // function*() vs function* ()
879             if (opt.space_after_anon_function) {
880                 output.space_before_token = true;
881             }
882         } else if (last_type === 'TK_RESERVED' && (in_array(flags.last_text, tokenizer.line_starters) || flags.last_text === 'catch')) {
883             if (opt.space_before_conditional) {
884                 output.space_before_token = true;
885             }
886         }
888         // Should be a space between await and an IIFE, or async and an arrow function
889         if (current_token.text === '(' && last_type === 'TK_RESERVED' && in_array(flags.last_word, ['await', 'async'])) {
890             output.space_before_token = true;
891         }
893         // Support of this kind of newline preservation.
894         // a = (b &&
895         //     (c || d));
896         if (current_token.text === '(') {
897             if (last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
898                 if (!start_of_object_property()) {
899                     allow_wrap_or_preserved_newline();
900                 }
901             }
902         }
904         // Support preserving wrapped arrow function expressions
905         // a.b('c',
906         //     () => d.e
907         // )
908         if (current_token.text === '(' && last_type !== 'TK_WORD' && last_type !== 'TK_RESERVED') {
909             allow_wrap_or_preserved_newline();
910         }
912         set_mode(next_mode);
913         print_token();
914         if (opt.space_in_paren) {
915             output.space_before_token = true;
916         }
918         // In all cases, if we newline while inside an expression it should be indented.
919         indent();
920     }
922     function handle_end_expr() {
923         // statements inside expressions are not valid syntax, but...
924         // statements must all be closed when their container closes
925         while (flags.mode === MODE.Statement) {
926             restore_mode();
927         }
929         handle_whitespace_and_comments(current_token);
931         if (flags.multiline_frame) {
932             allow_wrap_or_preserved_newline(current_token.text === ']' && is_array(flags.mode) && !opt.keep_array_indentation);
933         }
935         if (opt.space_in_paren) {
936             if (last_type === 'TK_START_EXPR' && !opt.space_in_empty_paren) {
937                 // () [] no inner space in empty parens like these, ever, ref #320
938                 output.trim();
939                 output.space_before_token = false;
940             } else {
941                 output.space_before_token = true;
942             }
943         }
944         if (current_token.text === ']' && opt.keep_array_indentation) {
945             print_token();
946             restore_mode();
947         } else {
948             restore_mode();
949             print_token();
950         }
951         remove_redundant_indentation(output, previous_flags);
953         // do {} while () // no statement required after
954         if (flags.do_while && previous_flags.mode === MODE.Conditional) {
955             previous_flags.mode = MODE.Expression;
956             flags.do_block = false;
957             flags.do_while = false;
959         }
960     }
962     function handle_start_block() {
963         handle_whitespace_and_comments(current_token);
965         // Check if this is should be treated as a ObjectLiteral
966         var next_token = get_token(1);
967         var second_token = get_token(2);
968         if (second_token && (
969                 (in_array(second_token.text, [':', ',']) && in_array(next_token.type, ['TK_STRING', 'TK_WORD', 'TK_RESERVED'])) ||
970                 (in_array(next_token.text, ['get', 'set', '...']) && in_array(second_token.type, ['TK_WORD', 'TK_RESERVED']))
971             )) {
972             // We don't support TypeScript,but we didn't break it for a very long time.
973             // We'll try to keep not breaking it.
974             if (!in_array(last_last_text, ['class', 'interface'])) {
975                 set_mode(MODE.ObjectLiteral);
976             } else {
977                 set_mode(MODE.BlockStatement);
978             }
979         } else if (last_type === 'TK_OPERATOR' && flags.last_text === '=>') {
980             // arrow function: (param1, paramN) => { statements }
981             set_mode(MODE.BlockStatement);
982         } else if (in_array(last_type, ['TK_EQUALS', 'TK_START_EXPR', 'TK_COMMA', 'TK_OPERATOR']) ||
983             (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['return', 'throw', 'import', 'default']))
984         ) {
985             // Detecting shorthand function syntax is difficult by scanning forward,
986             //     so check the surrounding context.
987             // If the block is being returned, imported, export default, passed as arg,
988             //     assigned with = or assigned in a nested object, treat as an ObjectLiteral.
989             set_mode(MODE.ObjectLiteral);
990         } else {
991             set_mode(MODE.BlockStatement);
992         }
994         var empty_braces = !next_token.comments_before.length && next_token.text === '}';
995         var empty_anonymous_function = empty_braces && flags.last_word === 'function' &&
996             last_type === 'TK_END_EXPR';
998         if (opt.brace_preserve_inline) // check for inline, set inline_frame if so
999         {
1000             // search forward for a newline wanted inside this block
1001             var index = 0;
1002             var check_token = null;
1003             flags.inline_frame = true;
1004             do {
1005                 index += 1;
1006                 check_token = get_token(index);
1007                 if (check_token.wanted_newline) {
1008                     flags.inline_frame = false;
1009                     break;
1010                 }
1011             } while (check_token.type !== 'TK_EOF' &&
1012                 !(check_token.type === 'TK_END_BLOCK' && check_token.opened === current_token));
1013         }
1015         if ((opt.brace_style === "expand" ||
1016                 (opt.brace_style === "none" && current_token.wanted_newline)) &&
1017             !flags.inline_frame) {
1018             if (last_type !== 'TK_OPERATOR' &&
1019                 (empty_anonymous_function ||
1020                     last_type === 'TK_EQUALS' ||
1021                     (last_type === 'TK_RESERVED' && is_special_word(flags.last_text) && flags.last_text !== 'else'))) {
1022                 output.space_before_token = true;
1023             } else {
1024                 print_newline(false, true);
1025             }
1026         } else { // collapse || inline_frame
1027             if (is_array(previous_flags.mode) && (last_type === 'TK_START_EXPR' || last_type === 'TK_COMMA')) {
1028                 if (last_type === 'TK_COMMA' || opt.space_in_paren) {
1029                     output.space_before_token = true;
1030                 }
1032                 if (last_type === 'TK_COMMA' || (last_type === 'TK_START_EXPR' && flags.inline_frame)) {
1033                     allow_wrap_or_preserved_newline();
1034                     previous_flags.multiline_frame = previous_flags.multiline_frame || flags.multiline_frame;
1035                     flags.multiline_frame = false;
1036                 }
1037             }
1038             if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
1039                 if (last_type === 'TK_START_BLOCK' && !flags.inline_frame) {
1040                     print_newline();
1041                 } else {
1042                     output.space_before_token = true;
1043                 }
1044             }
1045         }
1046         print_token();
1047         indent();
1048     }
1050     function handle_end_block() {
1051         // statements must all be closed when their container closes
1052         handle_whitespace_and_comments(current_token);
1054         while (flags.mode === MODE.Statement) {
1055             restore_mode();
1056         }
1058         var empty_braces = last_type === 'TK_START_BLOCK';
1060         if (flags.inline_frame && !empty_braces) { // try inline_frame (only set if opt.braces-preserve-inline) first
1061             output.space_before_token = true;
1062         } else if (opt.brace_style === "expand") {
1063             if (!empty_braces) {
1064                 print_newline();
1065             }
1066         } else {
1067             // skip {}
1068             if (!empty_braces) {
1069                 if (is_array(flags.mode) && opt.keep_array_indentation) {
1070                     // we REALLY need a newline here, but newliner would skip that
1071                     opt.keep_array_indentation = false;
1072                     print_newline();
1073                     opt.keep_array_indentation = true;
1075                 } else {
1076                     print_newline();
1077                 }
1078             }
1079         }
1080         restore_mode();
1081         print_token();
1082     }
1084     function handle_word() {
1085         if (current_token.type === 'TK_RESERVED') {
1086             if (in_array(current_token.text, ['set', 'get']) && flags.mode !== MODE.ObjectLiteral) {
1087                 current_token.type = 'TK_WORD';
1088             } else if (in_array(current_token.text, ['as', 'from']) && !flags.import_block) {
1089                 current_token.type = 'TK_WORD';
1090             } else if (flags.mode === MODE.ObjectLiteral) {
1091                 var next_token = get_token(1);
1092                 if (next_token.text === ':') {
1093                     current_token.type = 'TK_WORD';
1094                 }
1095             }
1096         }
1098         if (start_of_statement()) {
1099             // The conditional starts the statement if appropriate.
1100             if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const']) && current_token.type === 'TK_WORD') {
1101                 flags.declaration_statement = true;
1102             }
1103         } else if (current_token.wanted_newline && !is_expression(flags.mode) &&
1104             (last_type !== 'TK_OPERATOR' || (flags.last_text === '--' || flags.last_text === '++')) &&
1105             last_type !== 'TK_EQUALS' &&
1106             (opt.preserve_newlines || !(last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const', 'set', 'get'])))) {
1107             handle_whitespace_and_comments(current_token);
1108             print_newline();
1109         } else {
1110             handle_whitespace_and_comments(current_token);
1111         }
1113         if (flags.do_block && !flags.do_while) {
1114             if (current_token.type === 'TK_RESERVED' && current_token.text === 'while') {
1115                 // do {} ## while ()
1116                 output.space_before_token = true;
1117                 print_token();
1118                 output.space_before_token = true;
1119                 flags.do_while = true;
1120                 return;
1121             } else {
1122                 // do {} should always have while as the next word.
1123                 // if we don't see the expected while, recover
1124                 print_newline();
1125                 flags.do_block = false;
1126             }
1127         }
1129         // if may be followed by else, or not
1130         // Bare/inline ifs are tricky
1131         // Need to unwind the modes correctly: if (a) if (b) c(); else d(); else e();
1132         if (flags.if_block) {
1133             if (!flags.else_block && (current_token.type === 'TK_RESERVED' && current_token.text === 'else')) {
1134                 flags.else_block = true;
1135             } else {
1136                 while (flags.mode === MODE.Statement) {
1137                     restore_mode();
1138                 }
1139                 flags.if_block = false;
1140                 flags.else_block = false;
1141             }
1142         }
1144         if (current_token.type === 'TK_RESERVED' && (current_token.text === 'case' || (current_token.text === 'default' && flags.in_case_statement))) {
1145             print_newline();
1146             if (flags.case_body || opt.jslint_happy) {
1147                 // switch cases following one another
1148                 deindent();
1149                 flags.case_body = false;
1150             }
1151             print_token();
1152             flags.in_case = true;
1153             flags.in_case_statement = true;
1154             return;
1155         }
1157         if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
1158             if (!start_of_object_property()) {
1159                 allow_wrap_or_preserved_newline();
1160             }
1161         }
1163         if (current_token.type === 'TK_RESERVED' && current_token.text === 'function') {
1164             if (in_array(flags.last_text, ['}', ';']) ||
1165                 (output.just_added_newline() && !(in_array(flags.last_text, ['(', '[', '{', ':', '=', ',']) || last_type === 'TK_OPERATOR'))) {
1166                 // make sure there is a nice clean space of at least one blank line
1167                 // before a new function definition
1168                 if (!output.just_added_blankline() && !current_token.comments_before.length) {
1169                     print_newline();
1170                     print_newline(true);
1171                 }
1172             }
1173             if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') {
1174                 if (last_type === 'TK_RESERVED' && (
1175                         in_array(flags.last_text, ['get', 'set', 'new', 'export', 'async']) ||
1176                         in_array(flags.last_text, newline_restricted_tokens))) {
1177                     output.space_before_token = true;
1178                 } else if (last_type === 'TK_RESERVED' && flags.last_text === 'default' && last_last_text === 'export') {
1179                     output.space_before_token = true;
1180                 } else {
1181                     print_newline();
1182                 }
1183             } else if (last_type === 'TK_OPERATOR' || flags.last_text === '=') {
1184                 // foo = function
1185                 output.space_before_token = true;
1186             } else if (!flags.multiline_frame && (is_expression(flags.mode) || is_array(flags.mode))) {
1187                 // (function
1188             } else {
1189                 print_newline();
1190             }
1192             print_token();
1193             flags.last_word = current_token.text;
1194             return;
1195         }
1197         prefix = 'NONE';
1199         if (last_type === 'TK_END_BLOCK') {
1201             if (previous_flags.inline_frame) {
1202                 prefix = 'SPACE';
1203             } else if (!(current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['else', 'catch', 'finally', 'from']))) {
1204                 prefix = 'NEWLINE';
1205             } else {
1206                 if (opt.brace_style === "expand" ||
1207                     opt.brace_style === "end-expand" ||
1208                     (opt.brace_style === "none" && current_token.wanted_newline)) {
1209                     prefix = 'NEWLINE';
1210                 } else {
1211                     prefix = 'SPACE';
1212                     output.space_before_token = true;
1213                 }
1214             }
1215         } else if (last_type === 'TK_SEMICOLON' && flags.mode === MODE.BlockStatement) {
1216             // TODO: Should this be for STATEMENT as well?
1217             prefix = 'NEWLINE';
1218         } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {
1219             prefix = 'SPACE';
1220         } else if (last_type === 'TK_STRING') {
1221             prefix = 'NEWLINE';
1222         } else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD' ||
1223             (flags.last_text === '*' &&
1224                 (in_array(last_last_text, ['function', 'yield']) ||
1225                     (flags.mode === MODE.ObjectLiteral && in_array(last_last_text, ['{', ',']))))) {
1226             prefix = 'SPACE';
1227         } else if (last_type === 'TK_START_BLOCK') {
1228             if (flags.inline_frame) {
1229                 prefix = 'SPACE';
1230             } else {
1231                 prefix = 'NEWLINE';
1232             }
1233         } else if (last_type === 'TK_END_EXPR') {
1234             output.space_before_token = true;
1235             prefix = 'NEWLINE';
1236         }
1238         if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, tokenizer.line_starters) && flags.last_text !== ')') {
1239             if (flags.inline_frame || flags.last_text === 'else' || flags.last_text === 'export') {
1240                 prefix = 'SPACE';
1241             } else {
1242                 prefix = 'NEWLINE';
1243             }
1245         }
1247         if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['else', 'catch', 'finally'])) {
1248             if ((!(last_type === 'TK_END_BLOCK' && previous_flags.mode === MODE.BlockStatement) ||
1249                     opt.brace_style === "expand" ||
1250                     opt.brace_style === "end-expand" ||
1251                     (opt.brace_style === "none" && current_token.wanted_newline)) &&
1252                 !flags.inline_frame) {
1253                 print_newline();
1254             } else {
1255                 output.trim(true);
1256                 var line = output.current_line;
1257                 // If we trimmed and there's something other than a close block before us
1258                 // put a newline back in.  Handles '} // comment' scenario.
1259                 if (line.last() !== '}') {
1260                     print_newline();
1261                 }
1262                 output.space_before_token = true;
1263             }
1264         } else if (prefix === 'NEWLINE') {
1265             if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {
1266                 // no newline between 'return nnn'
1267                 output.space_before_token = true;
1268             } else if (last_type !== 'TK_END_EXPR') {
1269                 if ((last_type !== 'TK_START_EXPR' || !(current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['var', 'let', 'const']))) && flags.last_text !== ':') {
1270                     // no need to force newline on 'var': for (var x = 0...)
1271                     if (current_token.type === 'TK_RESERVED' && current_token.text === 'if' && flags.last_text === 'else') {
1272                         // no newline for } else if {
1273                         output.space_before_token = true;
1274                     } else {
1275                         print_newline();
1276                     }
1277                 }
1278             } else if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, tokenizer.line_starters) && flags.last_text !== ')') {
1279                 print_newline();
1280             }
1281         } else if (flags.multiline_frame && is_array(flags.mode) && flags.last_text === ',' && last_last_text === '}') {
1282             print_newline(); // }, in lists get a newline treatment
1283         } else if (prefix === 'SPACE') {
1284             output.space_before_token = true;
1285         }
1286         print_token();
1287         flags.last_word = current_token.text;
1289         if (current_token.type === 'TK_RESERVED') {
1290             if (current_token.text === 'do') {
1291                 flags.do_block = true;
1292             } else if (current_token.text === 'if') {
1293                 flags.if_block = true;
1294             } else if (current_token.text === 'import') {
1295                 flags.import_block = true;
1296             } else if (flags.import_block && current_token.type === 'TK_RESERVED' && current_token.text === 'from') {
1297                 flags.import_block = false;
1298             }
1299         }
1300     }
1302     function handle_semicolon() {
1303         if (start_of_statement()) {
1304             // The conditional starts the statement if appropriate.
1305             // Semicolon can be the start (and end) of a statement
1306             output.space_before_token = false;
1307         } else {
1308             handle_whitespace_and_comments(current_token);
1309         }
1311         var next_token = get_token(1);
1312         while (flags.mode === MODE.Statement &&
1313             !(flags.if_block && next_token && next_token.type === 'TK_RESERVED' && next_token.text === 'else') &&
1314             !flags.do_block) {
1315             restore_mode();
1316         }
1318         // hacky but effective for the moment
1319         if (flags.import_block) {
1320             flags.import_block = false;
1321         }
1322         print_token();
1323     }
1325     function handle_string() {
1326         if (start_of_statement()) {
1327             // The conditional starts the statement if appropriate.
1328             // One difference - strings want at least a space before
1329             output.space_before_token = true;
1330         } else {
1331             handle_whitespace_and_comments(current_token);
1332             if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD' || flags.inline_frame) {
1333                 output.space_before_token = true;
1334             } else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
1335                 if (!start_of_object_property()) {
1336                     allow_wrap_or_preserved_newline();
1337                 }
1338             } else {
1339                 print_newline();
1340             }
1341         }
1342         print_token();
1343     }
1345     function handle_equals() {
1346         if (start_of_statement()) {
1347             // The conditional starts the statement if appropriate.
1348         } else {
1349             handle_whitespace_and_comments(current_token);
1350         }
1352         if (flags.declaration_statement) {
1353             // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
1354             flags.declaration_assignment = true;
1355         }
1356         output.space_before_token = true;
1357         print_token();
1358         output.space_before_token = true;
1359     }
1361     function handle_comma() {
1362         handle_whitespace_and_comments(current_token, true);
1364         print_token();
1365         output.space_before_token = true;
1366         if (flags.declaration_statement) {
1367             if (is_expression(flags.parent.mode)) {
1368                 // do not break on comma, for(var a = 1, b = 2)
1369                 flags.declaration_assignment = false;
1370             }
1372             if (flags.declaration_assignment) {
1373                 flags.declaration_assignment = false;
1374                 print_newline(false, true);
1375             } else if (opt.comma_first) {
1376                 // for comma-first, we want to allow a newline before the comma
1377                 // to turn into a newline after the comma, which we will fixup later
1378                 allow_wrap_or_preserved_newline();
1379             }
1380         } else if (flags.mode === MODE.ObjectLiteral ||
1381             (flags.mode === MODE.Statement && flags.parent.mode === MODE.ObjectLiteral)) {
1382             if (flags.mode === MODE.Statement) {
1383                 restore_mode();
1384             }
1386             if (!flags.inline_frame) {
1387                 print_newline();
1388             }
1389         } else if (opt.comma_first) {
1390             // EXPR or DO_BLOCK
1391             // for comma-first, we want to allow a newline before the comma
1392             // to turn into a newline after the comma, which we will fixup later
1393             allow_wrap_or_preserved_newline();
1394         }
1395     }
1397     function handle_operator() {
1398         var isGeneratorAsterisk = current_token.text === '*' &&
1399             ((last_type === 'TK_RESERVED' && in_array(flags.last_text, ['function', 'yield'])) ||
1400                 (in_array(last_type, ['TK_START_BLOCK', 'TK_COMMA', 'TK_END_BLOCK', 'TK_SEMICOLON']))
1401             );
1402         var isUnary = in_array(current_token.text, ['-', '+']) && (
1403             in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) ||
1404             in_array(flags.last_text, tokenizer.line_starters) ||
1405             flags.last_text === ','
1406         );
1408         if (start_of_statement()) {
1409             // The conditional starts the statement if appropriate.
1410         } else {
1411             var preserve_statement_flags = !isGeneratorAsterisk;
1412             handle_whitespace_and_comments(current_token, preserve_statement_flags);
1413         }
1415         if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {
1416             // "return" had a special handling in TK_WORD. Now we need to return the favor
1417             output.space_before_token = true;
1418             print_token();
1419             return;
1420         }
1422         // hack for actionscript's import .*;
1423         if (current_token.text === '*' && last_type === 'TK_DOT') {
1424             print_token();
1425             return;
1426         }
1428         if (current_token.text === '::') {
1429             // no spaces around exotic namespacing syntax operator
1430             print_token();
1431             return;
1432         }
1434         // Allow line wrapping between operators when operator_position is
1435         //   set to before or preserve
1436         if (last_type === 'TK_OPERATOR' && in_array(opt.operator_position, OPERATOR_POSITION_BEFORE_OR_PRESERVE)) {
1437             allow_wrap_or_preserved_newline();
1438         }
1440         if (current_token.text === ':' && flags.in_case) {
1441             flags.case_body = true;
1442             indent();
1443             print_token();
1444             print_newline();
1445             flags.in_case = false;
1446             return;
1447         }
1449         var space_before = true;
1450         var space_after = true;
1451         var in_ternary = false;
1452         if (current_token.text === ':') {
1453             if (flags.ternary_depth === 0) {
1454                 // Colon is invalid javascript outside of ternary and object, but do our best to guess what was meant.
1455                 space_before = false;
1456             } else {
1457                 flags.ternary_depth -= 1;
1458                 in_ternary = true;
1459             }
1460         } else if (current_token.text === '?') {
1461             flags.ternary_depth += 1;
1462         }
1464         // let's handle the operator_position option prior to any conflicting logic
1465         if (!isUnary && !isGeneratorAsterisk && opt.preserve_newlines && in_array(current_token.text, tokenizer.positionable_operators)) {
1466             var isColon = current_token.text === ':';
1467             var isTernaryColon = (isColon && in_ternary);
1468             var isOtherColon = (isColon && !in_ternary);
1470             switch (opt.operator_position) {
1471                 case OPERATOR_POSITION.before_newline:
1472                     // if the current token is : and it's not a ternary statement then we set space_before to false
1473                     output.space_before_token = !isOtherColon;
1475                     print_token();
1477                     if (!isColon || isTernaryColon) {
1478                         allow_wrap_or_preserved_newline();
1479                     }
1481                     output.space_before_token = true;
1482                     return;
1484                 case OPERATOR_POSITION.after_newline:
1485                     // if the current token is anything but colon, or (via deduction) it's a colon and in a ternary statement,
1486                     //   then print a newline.
1488                     output.space_before_token = true;
1490                     if (!isColon || isTernaryColon) {
1491                         if (get_token(1).wanted_newline) {
1492                             print_newline(false, true);
1493                         } else {
1494                             allow_wrap_or_preserved_newline();
1495                         }
1496                     } else {
1497                         output.space_before_token = false;
1498                     }
1500                     print_token();
1502                     output.space_before_token = true;
1503                     return;
1505                 case OPERATOR_POSITION.preserve_newline:
1506                     if (!isOtherColon) {
1507                         allow_wrap_or_preserved_newline();
1508                     }
1510                     // if we just added a newline, or the current token is : and it's not a ternary statement,
1511                     //   then we set space_before to false
1512                     space_before = !(output.just_added_newline() || isOtherColon);
1514                     output.space_before_token = space_before;
1515                     print_token();
1516                     output.space_before_token = true;
1517                     return;
1518             }
1519         }
1521         if (isGeneratorAsterisk) {
1522             allow_wrap_or_preserved_newline();
1523             space_before = false;
1524             var next_token = get_token(1);
1525             space_after = next_token && in_array(next_token.type, ['TK_WORD', 'TK_RESERVED']);
1526         } else if (current_token.text === '...') {
1527             allow_wrap_or_preserved_newline();
1528             space_before = last_type === 'TK_START_BLOCK';
1529             space_after = false;
1530         } else if (in_array(current_token.text, ['--', '++', '!', '~']) || isUnary) {
1531             // unary operators (and binary +/- pretending to be unary) special cases
1533             space_before = false;
1534             space_after = false;
1536             // http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1
1537             // if there is a newline between -- or ++ and anything else we should preserve it.
1538             if (current_token.wanted_newline && (current_token.text === '--' || current_token.text === '++')) {
1539                 print_newline(false, true);
1540             }
1542             if (flags.last_text === ';' && is_expression(flags.mode)) {
1543                 // for (;; ++i)
1544                 //        ^^^
1545                 space_before = true;
1546             }
1548             if (last_type === 'TK_RESERVED') {
1549                 space_before = true;
1550             } else if (last_type === 'TK_END_EXPR') {
1551                 space_before = !(flags.last_text === ']' && (current_token.text === '--' || current_token.text === '++'));
1552             } else if (last_type === 'TK_OPERATOR') {
1553                 // a++ + ++b;
1554                 // a - -b
1555                 space_before = in_array(current_token.text, ['--', '-', '++', '+']) && in_array(flags.last_text, ['--', '-', '++', '+']);
1556                 // + and - are not unary when preceeded by -- or ++ operator
1557                 // a-- + b
1558                 // a * +b
1559                 // a - -b
1560                 if (in_array(current_token.text, ['+', '-']) && in_array(flags.last_text, ['--', '++'])) {
1561                     space_after = true;
1562                 }
1563             }
1566             if (((flags.mode === MODE.BlockStatement && !flags.inline_frame) || flags.mode === MODE.Statement) &&
1567                 (flags.last_text === '{' || flags.last_text === ';')) {
1568                 // { foo; --i }
1569                 // foo(); --bar;
1570                 print_newline();
1571             }
1572         }
1574         output.space_before_token = output.space_before_token || space_before;
1575         print_token();
1576         output.space_before_token = space_after;
1577     }
1579     function handle_block_comment(preserve_statement_flags) {
1580         if (output.raw) {
1581             output.add_raw_token(current_token);
1582             if (current_token.directives && current_token.directives.preserve === 'end') {
1583                 // If we're testing the raw output behavior, do not allow a directive to turn it off.
1584                 output.raw = opt.test_output_raw;
1585             }
1586             return;
1587         }
1589         if (current_token.directives) {
1590             print_newline(false, preserve_statement_flags);
1591             print_token();
1592             if (current_token.directives.preserve === 'start') {
1593                 output.raw = true;
1594             }
1595             print_newline(false, true);
1596             return;
1597         }
1599         // inline block
1600         if (!acorn.newline.test(current_token.text) && !current_token.wanted_newline) {
1601             output.space_before_token = true;
1602             print_token();
1603             output.space_before_token = true;
1604             return;
1605         }
1607         var lines = split_linebreaks(current_token.text);
1608         var j; // iterator for this case
1609         var javadoc = false;
1610         var starless = false;
1611         var lastIndent = current_token.whitespace_before;
1612         var lastIndentLength = lastIndent.length;
1614         // block comment starts with a new line
1615         print_newline(false, preserve_statement_flags);
1616         if (lines.length > 1) {
1617             javadoc = all_lines_start_with(lines.slice(1), '*');
1618             starless = each_line_matches_indent(lines.slice(1), lastIndent);
1619         }
1621         // first line always indented
1622         print_token(lines[0]);
1623         for (j = 1; j < lines.length; j++) {
1624             print_newline(false, true);
1625             if (javadoc) {
1626                 // javadoc: reformat and re-indent
1627                 print_token(' ' + ltrim(lines[j]));
1628             } else if (starless && lines[j].length > lastIndentLength) {
1629                 // starless: re-indent non-empty content, avoiding trim
1630                 print_token(lines[j].substring(lastIndentLength));
1631             } else {
1632                 // normal comments output raw
1633                 output.add_token(lines[j]);
1634             }
1635         }
1637         // for comments of more than one line, make sure there's a new line after
1638         print_newline(false, preserve_statement_flags);
1639     }
1641     function handle_comment(preserve_statement_flags) {
1642         if (current_token.wanted_newline) {
1643             print_newline(false, preserve_statement_flags);
1644         } else {
1645             output.trim(true);
1646         }
1648         output.space_before_token = true;
1649         print_token();
1650         print_newline(false, preserve_statement_flags);
1651     }
1653     function handle_dot() {
1654         if (start_of_statement()) {
1655             // The conditional starts the statement if appropriate.
1656         } else {
1657             handle_whitespace_and_comments(current_token, true);
1658         }
1660         if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {
1661             output.space_before_token = true;
1662         } else {
1663             // allow preserved newlines before dots in general
1664             // force newlines on dots after close paren when break_chained - for bar().baz()
1665             allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.break_chained_methods);
1666         }
1668         print_token();
1669     }
1671     function handle_unknown(preserve_statement_flags) {
1672         print_token();
1674         if (current_token.text[current_token.text.length - 1] === '\n') {
1675             print_newline(false, preserve_statement_flags);
1676         }
1677     }
1679     function handle_eof() {
1680         // Unwind any open statements
1681         while (flags.mode === MODE.Statement) {
1682             restore_mode();
1683         }
1684         handle_whitespace_and_comments(current_token);
1685     }
1688 module.exports.Beautifier = Beautifier;
1690 /***/ }),
1691 /* 2 */
1692 /***/ (function(module, exports) {
1694 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
1695 /*
1697   The MIT License (MIT)
1699   Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
1701   Permission is hereby granted, free of charge, to any person
1702   obtaining a copy of this software and associated documentation files
1703   (the "Software"), to deal in the Software without restriction,
1704   including without limitation the rights to use, copy, modify, merge,
1705   publish, distribute, sublicense, and/or sell copies of the Software,
1706   and to permit persons to whom the Software is furnished to do so,
1707   subject to the following conditions:
1709   The above copyright notice and this permission notice shall be
1710   included in all copies or substantial portions of the Software.
1712   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1713   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1714   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1715   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1716   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1717   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1718   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1719   SOFTWARE.
1720 */
1722 function InputScanner(input) {
1723     var _input = input;
1724     var _input_length = _input.length;
1725     var _position = 0;
1727     this.back = function() {
1728         _position -= 1;
1729     };
1731     this.hasNext = function() {
1732         return _position < _input_length;
1733     };
1735     this.next = function() {
1736         var val = null;
1737         if (this.hasNext()) {
1738             val = _input.charAt(_position);
1739             _position += 1;
1740         }
1741         return val;
1742     };
1744     this.peek = function(index) {
1745         var val = null;
1746         index = index || 0;
1747         index += _position;
1748         if (index >= 0 && index < _input_length) {
1749             val = _input.charAt(index);
1750         }
1751         return val;
1752     };
1754     this.peekCharCode = function(index) {
1755         var val = 0;
1756         index = index || 0;
1757         index += _position;
1758         if (index >= 0 && index < _input_length) {
1759             val = _input.charCodeAt(index);
1760         }
1761         return val;
1762     };
1764     this.test = function(pattern, index) {
1765         index = index || 0;
1766         pattern.lastIndex = _position + index;
1767         return pattern.test(_input);
1768     };
1770     this.testChar = function(pattern, index) {
1771         var val = this.peek(index);
1772         return val !== null && pattern.test(val);
1773     };
1775     this.match = function(pattern) {
1776         pattern.lastIndex = _position;
1777         var pattern_match = pattern.exec(_input);
1778         if (pattern_match && pattern_match.index === _position) {
1779             _position += pattern_match[0].length;
1780         } else {
1781             pattern_match = null;
1782         }
1783         return pattern_match;
1784     };
1788 module.exports.InputScanner = InputScanner;
1791 /***/ }),
1792 /* 3 */
1793 /***/ (function(module, exports) {
1795 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
1796 /*
1798     The MIT License (MIT)
1800     Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
1802     Permission is hereby granted, free of charge, to any person
1803     obtaining a copy of this software and associated documentation files
1804     (the "Software"), to deal in the Software without restriction,
1805     including without limitation the rights to use, copy, modify, merge,
1806     publish, distribute, sublicense, and/or sell copies of the Software,
1807     and to permit persons to whom the Software is furnished to do so,
1808     subject to the following conditions:
1810     The above copyright notice and this permission notice shall be
1811     included in all copies or substantial portions of the Software.
1813     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1814     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1815     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1816     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1817     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1818     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1819     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1820     SOFTWARE.
1821 */
1823 function mergeOpts(allOptions, targetType) {
1824     var finalOpts = {};
1825     var name;
1827     for (name in allOptions) {
1828         if (name !== targetType) {
1829             finalOpts[name] = allOptions[name];
1830         }
1831     }
1833     //merge in the per type settings for the targetType
1834     if (targetType in allOptions) {
1835         for (name in allOptions[targetType]) {
1836             finalOpts[name] = allOptions[targetType][name];
1837         }
1838     }
1839     return finalOpts;
1842 module.exports.mergeOpts = mergeOpts;
1845 /***/ }),
1846 /* 4 */
1847 /***/ (function(module, exports) {
1849 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
1850 /*
1852   The MIT License (MIT)
1854   Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
1856   Permission is hereby granted, free of charge, to any person
1857   obtaining a copy of this software and associated documentation files
1858   (the "Software"), to deal in the Software without restriction,
1859   including without limitation the rights to use, copy, modify, merge,
1860   publish, distribute, sublicense, and/or sell copies of the Software,
1861   and to permit persons to whom the Software is furnished to do so,
1862   subject to the following conditions:
1864   The above copyright notice and this permission notice shall be
1865   included in all copies or substantial portions of the Software.
1867   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1868   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1869   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1870   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1871   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1872   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1873   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1874   SOFTWARE.
1875 */
1877 function OutputLine(parent) {
1878     var _character_count = 0;
1879     // use indent_count as a marker for lines that have preserved indentation
1880     var _indent_count = -1;
1882     var _items = [];
1883     var _empty = true;
1885     this.set_indent = function(level) {
1886         _character_count = parent.baseIndentLength + level * parent.indent_length;
1887         _indent_count = level;
1888     };
1890     this.get_character_count = function() {
1891         return _character_count;
1892     };
1894     this.is_empty = function() {
1895         return _empty;
1896     };
1898     this.last = function() {
1899         if (!this._empty) {
1900             return _items[_items.length - 1];
1901         } else {
1902             return null;
1903         }
1904     };
1906     this.push = function(input) {
1907         _items.push(input);
1908         _character_count += input.length;
1909         _empty = false;
1910     };
1912     this.pop = function() {
1913         var item = null;
1914         if (!_empty) {
1915             item = _items.pop();
1916             _character_count -= item.length;
1917             _empty = _items.length === 0;
1918         }
1919         return item;
1920     };
1922     this.remove_indent = function() {
1923         if (_indent_count > 0) {
1924             _indent_count -= 1;
1925             _character_count -= parent.indent_length;
1926         }
1927     };
1929     this.trim = function() {
1930         while (this.last() === ' ') {
1931             _items.pop();
1932             _character_count -= 1;
1933         }
1934         _empty = _items.length === 0;
1935     };
1937     this.toString = function() {
1938         var result = '';
1939         if (!this._empty) {
1940             if (_indent_count >= 0) {
1941                 result = parent.indent_cache[_indent_count];
1942             }
1943             result += _items.join('');
1944         }
1945         return result;
1946     };
1949 function Output(indent_string, baseIndentString) {
1950     baseIndentString = baseIndentString || '';
1951     this.indent_cache = [baseIndentString];
1952     this.baseIndentLength = baseIndentString.length;
1953     this.indent_length = indent_string.length;
1954     this.raw = false;
1956     var lines = [];
1957     this.baseIndentString = baseIndentString;
1958     this.indent_string = indent_string;
1959     this.previous_line = null;
1960     this.current_line = null;
1961     this.space_before_token = false;
1963     this.add_outputline = function() {
1964         this.previous_line = this.current_line;
1965         this.current_line = new OutputLine(this);
1966         lines.push(this.current_line);
1967     };
1969     // initialize
1970     this.add_outputline();
1973     this.get_line_number = function() {
1974         return lines.length;
1975     };
1977     // Using object instead of string to allow for later expansion of info about each line
1978     this.add_new_line = function(force_newline) {
1979         if (this.get_line_number() === 1 && this.just_added_newline()) {
1980             return false; // no newline on start of file
1981         }
1983         if (force_newline || !this.just_added_newline()) {
1984             if (!this.raw) {
1985                 this.add_outputline();
1986             }
1987             return true;
1988         }
1990         return false;
1991     };
1993     this.get_code = function(end_with_newline, eol) {
1994         var sweet_code = lines.join('\n').replace(/[\r\n\t ]+$/, '');
1996         if (end_with_newline) {
1997             sweet_code += '\n';
1998         }
2000         if (eol !== '\n') {
2001             sweet_code = sweet_code.replace(/[\n]/g, eol);
2002         }
2004         return sweet_code;
2005     };
2007     this.set_indent = function(level) {
2008         // Never indent your first output indent at the start of the file
2009         if (lines.length > 1) {
2010             while (level >= this.indent_cache.length) {
2011                 this.indent_cache.push(this.indent_cache[this.indent_cache.length - 1] + this.indent_string);
2012             }
2014             this.current_line.set_indent(level);
2015             return true;
2016         }
2017         this.current_line.set_indent(0);
2018         return false;
2019     };
2021     this.add_raw_token = function(token) {
2022         for (var x = 0; x < token.newlines; x++) {
2023             this.add_outputline();
2024         }
2025         this.current_line.push(token.whitespace_before);
2026         this.current_line.push(token.text);
2027         this.space_before_token = false;
2028     };
2030     this.add_token = function(printable_token) {
2031         this.add_space_before_token();
2032         this.current_line.push(printable_token);
2033     };
2035     this.add_space_before_token = function() {
2036         if (this.space_before_token && !this.just_added_newline()) {
2037             this.current_line.push(' ');
2038         }
2039         this.space_before_token = false;
2040     };
2042     this.remove_indent = function(index) {
2043         var output_length = lines.length;
2044         while (index < output_length) {
2045             lines[index].remove_indent();
2046             index++;
2047         }
2048     };
2050     this.trim = function(eat_newlines) {
2051         eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;
2053         this.current_line.trim(indent_string, baseIndentString);
2055         while (eat_newlines && lines.length > 1 &&
2056             this.current_line.is_empty()) {
2057             lines.pop();
2058             this.current_line = lines[lines.length - 1];
2059             this.current_line.trim();
2060         }
2062         this.previous_line = lines.length > 1 ? lines[lines.length - 2] : null;
2063     };
2065     this.just_added_newline = function() {
2066         return this.current_line.is_empty();
2067     };
2069     this.just_added_blankline = function() {
2070         if (this.just_added_newline()) {
2071             if (lines.length === 1) {
2072                 return true; // start of the file and newline = blank
2073             }
2075             var line = lines[lines.length - 2];
2076             return line.is_empty();
2077         }
2078         return false;
2079     };
2082 module.exports.Output = Output;
2085 /***/ }),
2086 /* 5 */
2087 /***/ (function(module, exports) {
2089 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
2090 /*
2092   The MIT License (MIT)
2094   Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
2096   Permission is hereby granted, free of charge, to any person
2097   obtaining a copy of this software and associated documentation files
2098   (the "Software"), to deal in the Software without restriction,
2099   including without limitation the rights to use, copy, modify, merge,
2100   publish, distribute, sublicense, and/or sell copies of the Software,
2101   and to permit persons to whom the Software is furnished to do so,
2102   subject to the following conditions:
2104   The above copyright notice and this permission notice shall be
2105   included in all copies or substantial portions of the Software.
2107   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2108   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2109   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2110   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2111   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2112   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2113   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2114   SOFTWARE.
2115 */
2117 function Token(type, text, newlines, whitespace_before, parent) {
2118     this.type = type;
2119     this.text = text;
2121     // comments_before are
2122     // comments that have a new line before them
2123     // and may or may not have a newline after
2124     // this is a set of comments before
2125     this.comments_before = /* inline comment*/ [];
2128     this.comments_after = []; // no new line before and newline after
2129     this.newlines = newlines || 0;
2130     this.wanted_newline = newlines > 0;
2131     this.whitespace_before = whitespace_before || '';
2132     this.parent = parent || null;
2133     this.opened = null;
2134     this.directives = null;
2137 module.exports.Token = Token;
2140 /***/ }),
2141 /* 6 */
2142 /***/ (function(module, exports, __webpack_require__) {
2144 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
2145 /*
2147     The MIT License (MIT)
2149     Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
2151     Permission is hereby granted, free of charge, to any person
2152     obtaining a copy of this software and associated documentation files
2153     (the "Software"), to deal in the Software without restriction,
2154     including without limitation the rights to use, copy, modify, merge,
2155     publish, distribute, sublicense, and/or sell copies of the Software,
2156     and to permit persons to whom the Software is furnished to do so,
2157     subject to the following conditions:
2159     The above copyright notice and this permission notice shall be
2160     included in all copies or substantial portions of the Software.
2162     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2163     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2164     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2165     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2166     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2167     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2168     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2169     SOFTWARE.
2170 */
2172 var Beautifier = __webpack_require__(1).Beautifier;
2174 function js_beautify(js_source_text, options) {
2175     var beautifier = new Beautifier(js_source_text, options);
2176     return beautifier.beautify();
2179 module.exports = js_beautify;
2181 /***/ }),
2182 /* 7 */
2183 /***/ (function(module, exports, __webpack_require__) {
2185 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
2186 /*
2188     The MIT License (MIT)
2190     Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
2192     Permission is hereby granted, free of charge, to any person
2193     obtaining a copy of this software and associated documentation files
2194     (the "Software"), to deal in the Software without restriction,
2195     including without limitation the rights to use, copy, modify, merge,
2196     publish, distribute, sublicense, and/or sell copies of the Software,
2197     and to permit persons to whom the Software is furnished to do so,
2198     subject to the following conditions:
2200     The above copyright notice and this permission notice shall be
2201     included in all copies or substantial portions of the Software.
2203     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2204     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2205     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2206     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2207     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2208     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2209     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2210     SOFTWARE.
2211 */
2213 var InputScanner = __webpack_require__(2).InputScanner;
2214 var Token = __webpack_require__(5).Token;
2215 var acorn = __webpack_require__(0);
2217 function trim(s) {
2218     return s.replace(/^\s+|\s+$/g, '');
2221 function in_array(what, arr) {
2222     for (var i = 0; i < arr.length; i += 1) {
2223         if (arr[i] === what) {
2224             return true;
2225         }
2226     }
2227     return false;
2230 function Tokenizer(input_string, opts) {
2232     var whitespace = "\n\r\t ".split('');
2233     var digit = /[0-9]/;
2234     var digit_bin = /[01]/;
2235     var digit_oct = /[01234567]/;
2236     var digit_hex = /[0123456789abcdefABCDEF]/;
2238     this.positionable_operators = '!= !== % & && * ** + - / : < << <= == === > >= >> >>> ? ^ | ||'.split(' ');
2239     var punct = this.positionable_operators.concat(
2240         // non-positionable operators - these do not follow operator position settings
2241         '! %= &= *= **= ++ += , -- -= /= :: <<= = => >>= >>>= ^= |= ~ ...'.split(' '));
2243     // words which should always start on new line.
2244     this.line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export'.split(',');
2245     var reserved_words = this.line_starters.concat(['do', 'in', 'of', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await', 'from', 'as']);
2247     //  /* ... */ comment ends with nearest */ or end of file
2248     var block_comment_pattern = /([\s\S]*?)((?:\*\/)|$)/g;
2250     // comment ends just before nearest linefeed or end of file
2251     var comment_pattern = /([^\n\r\u2028\u2029]*)/g;
2253     var directives_block_pattern = /\/\* beautify( \w+[:]\w+)+ \*\//g;
2254     var directive_pattern = / (\w+)[:](\w+)/g;
2255     var directives_end_ignore_pattern = /([\s\S]*?)((?:\/\*\sbeautify\signore:end\s\*\/)|$)/g;
2257     var template_pattern = /((<\?php|<\?=)[\s\S]*?\?>)|(<%[\s\S]*?%>)/g;
2259     var n_newlines, whitespace_before_token, in_html_comment, tokens;
2260     var input;
2262     this.tokenize = function() {
2263         input = new InputScanner(input_string);
2264         in_html_comment = false;
2265         tokens = [];
2267         var next, last;
2268         var token_values;
2269         var open = null;
2270         var open_stack = [];
2271         var comments = [];
2273         while (!(last && last.type === 'TK_EOF')) {
2274             token_values = tokenize_next();
2275             next = new Token(token_values[1], token_values[0], n_newlines, whitespace_before_token);
2276             while (next.type === 'TK_COMMENT' || next.type === 'TK_BLOCK_COMMENT' || next.type === 'TK_UNKNOWN') {
2277                 if (next.type === 'TK_BLOCK_COMMENT') {
2278                     next.directives = token_values[2];
2279                 }
2280                 comments.push(next);
2281                 token_values = tokenize_next();
2282                 next = new Token(token_values[1], token_values[0], n_newlines, whitespace_before_token);
2283             }
2285             if (comments.length) {
2286                 next.comments_before = comments;
2287                 comments = [];
2288             }
2290             if (next.type === 'TK_START_BLOCK' || next.type === 'TK_START_EXPR') {
2291                 next.parent = last;
2292                 open_stack.push(open);
2293                 open = next;
2294             } else if ((next.type === 'TK_END_BLOCK' || next.type === 'TK_END_EXPR') &&
2295                 (open && (
2296                     (next.text === ']' && open.text === '[') ||
2297                     (next.text === ')' && open.text === '(') ||
2298                     (next.text === '}' && open.text === '{')))) {
2299                 next.parent = open.parent;
2300                 next.opened = open;
2302                 open = open_stack.pop();
2303             }
2305             tokens.push(next);
2306             last = next;
2307         }
2309         return tokens;
2310     };
2312     function get_directives(text) {
2313         if (!text.match(directives_block_pattern)) {
2314             return null;
2315         }
2317         var directives = {};
2318         directive_pattern.lastIndex = 0;
2319         var directive_match = directive_pattern.exec(text);
2321         while (directive_match) {
2322             directives[directive_match[1]] = directive_match[2];
2323             directive_match = directive_pattern.exec(text);
2324         }
2326         return directives;
2327     }
2329     function tokenize_next() {
2330         var resulting_string;
2331         var whitespace_on_this_line = [];
2333         n_newlines = 0;
2334         whitespace_before_token = '';
2336         var c = input.next();
2338         if (c === null) {
2339             return ['', 'TK_EOF'];
2340         }
2342         var last_token;
2343         if (tokens.length) {
2344             last_token = tokens[tokens.length - 1];
2345         } else {
2346             // For the sake of tokenizing we can pretend that there was on open brace to start
2347             last_token = new Token('TK_START_BLOCK', '{');
2348         }
2350         while (in_array(c, whitespace)) {
2352             if (acorn.newline.test(c)) {
2353                 if (!(c === '\n' && input.peek(-2) === '\r')) {
2354                     n_newlines += 1;
2355                     whitespace_on_this_line = [];
2356                 }
2357             } else {
2358                 whitespace_on_this_line.push(c);
2359             }
2361             c = input.next();
2363             if (c === null) {
2364                 return ['', 'TK_EOF'];
2365             }
2366         }
2368         if (whitespace_on_this_line.length) {
2369             whitespace_before_token = whitespace_on_this_line.join('');
2370         }
2372         if (digit.test(c) || (c === '.' && input.testChar(digit))) {
2373             var allow_decimal = true;
2374             var allow_e = true;
2375             var local_digit = digit;
2377             if (c === '0' && input.testChar(/[XxOoBb]/)) {
2378                 // switch to hex/oct/bin number, no decimal or e, just hex/oct/bin digits
2379                 allow_decimal = false;
2380                 allow_e = false;
2381                 if (input.testChar(/[Bb]/)) {
2382                     local_digit = digit_bin;
2383                 } else if (input.testChar(/[Oo]/)) {
2384                     local_digit = digit_oct;
2385                 } else {
2386                     local_digit = digit_hex;
2387                 }
2388                 c += input.next();
2389             } else if (c === '.') {
2390                 // Already have a decimal for this literal, don't allow another
2391                 allow_decimal = false;
2392             } else {
2393                 // we know this first loop will run.  It keeps the logic simpler.
2394                 c = '';
2395                 input.back();
2396             }
2398             // Add the digits
2399             while (input.testChar(local_digit)) {
2400                 c += input.next();
2402                 if (allow_decimal && input.peek() === '.') {
2403                     c += input.next();
2404                     allow_decimal = false;
2405                 }
2407                 // a = 1.e-7 is valid, so we test for . then e in one loop
2408                 if (allow_e && input.testChar(/[Ee]/)) {
2409                     c += input.next();
2411                     if (input.testChar(/[+-]/)) {
2412                         c += input.next();
2413                     }
2415                     allow_e = false;
2416                     allow_decimal = false;
2417                 }
2418             }
2420             return [c, 'TK_WORD'];
2421         }
2423         if (acorn.isIdentifierStart(input.peekCharCode(-1))) {
2424             if (input.hasNext()) {
2425                 while (acorn.isIdentifierChar(input.peekCharCode())) {
2426                     c += input.next();
2427                     if (!input.hasNext()) {
2428                         break;
2429                     }
2430                 }
2431             }
2433             if (!(last_token.type === 'TK_DOT' ||
2434                     (last_token.type === 'TK_RESERVED' && in_array(last_token.text, ['set', 'get']))) &&
2435                 in_array(c, reserved_words)) {
2436                 if (c === 'in' || c === 'of') { // hack for 'in' and 'of' operators
2437                     return [c, 'TK_OPERATOR'];
2438                 }
2439                 return [c, 'TK_RESERVED'];
2440             }
2442             return [c, 'TK_WORD'];
2443         }
2445         if (c === '(' || c === '[') {
2446             return [c, 'TK_START_EXPR'];
2447         }
2449         if (c === ')' || c === ']') {
2450             return [c, 'TK_END_EXPR'];
2451         }
2453         if (c === '{') {
2454             return [c, 'TK_START_BLOCK'];
2455         }
2457         if (c === '}') {
2458             return [c, 'TK_END_BLOCK'];
2459         }
2461         if (c === ';') {
2462             return [c, 'TK_SEMICOLON'];
2463         }
2465         if (c === '/') {
2466             var comment = '';
2467             var comment_match;
2468             // peek for comment /* ... */
2469             if (input.peek() === '*') {
2470                 input.next();
2471                 comment_match = input.match(block_comment_pattern);
2472                 comment = '/*' + comment_match[0];
2473                 var directives = get_directives(comment);
2474                 if (directives && directives.ignore === 'start') {
2475                     comment_match = input.match(directives_end_ignore_pattern);
2476                     comment += comment_match[0];
2477                 }
2478                 comment = comment.replace(acorn.allLineBreaks, '\n');
2479                 return [comment, 'TK_BLOCK_COMMENT', directives];
2480             }
2481             // peek for comment // ...
2482             if (input.peek() === '/') {
2483                 input.next();
2484                 comment_match = input.match(comment_pattern);
2485                 comment = '//' + comment_match[0];
2486                 return [comment, 'TK_COMMENT'];
2487             }
2489         }
2491         var startXmlRegExp = /<()([-a-zA-Z:0-9_.]+|{[\s\S]+?}|!\[CDATA\[[\s\S]*?\]\])(\s+{[\s\S]+?}|\s+[-a-zA-Z:0-9_.]+|\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{[\s\S]+?}))*\s*(\/?)\s*>/g;
2493         if (c === '`' || c === "'" || c === '"' || // string
2494             (
2495                 (c === '/') || // regexp
2496                 (opts.e4x && c === "<" && input.test(startXmlRegExp, -1)) // xml
2497             ) && ( // regex and xml can only appear in specific locations during parsing
2498                 (last_token.type === 'TK_RESERVED' && in_array(last_token.text, ['return', 'case', 'throw', 'else', 'do', 'typeof', 'yield'])) ||
2499                 (last_token.type === 'TK_END_EXPR' && last_token.text === ')' &&
2500                     last_token.parent && last_token.parent.type === 'TK_RESERVED' && in_array(last_token.parent.text, ['if', 'while', 'for'])) ||
2501                 (in_array(last_token.type, ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK',
2502                     'TK_END_BLOCK', 'TK_OPERATOR', 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA'
2503                 ]))
2504             )) {
2506             var sep = c,
2507                 esc = false,
2508                 has_char_escapes = false;
2510             resulting_string = c;
2512             if (sep === '/') {
2513                 //
2514                 // handle regexp
2515                 //
2516                 var in_char_class = false;
2517                 while (input.hasNext() &&
2518                     ((esc || in_char_class || input.peek() !== sep) &&
2519                         !input.testChar(acorn.newline))) {
2520                     resulting_string += input.peek();
2521                     if (!esc) {
2522                         esc = input.peek() === '\\';
2523                         if (input.peek() === '[') {
2524                             in_char_class = true;
2525                         } else if (input.peek() === ']') {
2526                             in_char_class = false;
2527                         }
2528                     } else {
2529                         esc = false;
2530                     }
2531                     input.next();
2532                 }
2533             } else if (opts.e4x && sep === '<') {
2534                 //
2535                 // handle e4x xml literals
2536                 //
2538                 var xmlRegExp = /[\s\S]*?<(\/?)([-a-zA-Z:0-9_.]+|{[\s\S]+?}|!\[CDATA\[[\s\S]*?\]\])(\s+{[\s\S]+?}|\s+[-a-zA-Z:0-9_.]+|\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{[\s\S]+?}))*\s*(\/?)\s*>/g;
2539                 input.back();
2540                 var xmlStr = '';
2541                 var match = input.match(startXmlRegExp);
2542                 if (match) {
2543                     // Trim root tag to attempt to
2544                     var rootTag = match[2].replace(/^{\s+/, '{').replace(/\s+}$/, '}');
2545                     var isCurlyRoot = rootTag.indexOf('{') === 0;
2546                     var depth = 0;
2547                     while (match) {
2548                         var isEndTag = !!match[1];
2549                         var tagName = match[2];
2550                         var isSingletonTag = (!!match[match.length - 1]) || (tagName.slice(0, 8) === "![CDATA[");
2551                         if (!isSingletonTag &&
2552                             (tagName === rootTag || (isCurlyRoot && tagName.replace(/^{\s+/, '{').replace(/\s+}$/, '}')))) {
2553                             if (isEndTag) {
2554                                 --depth;
2555                             } else {
2556                                 ++depth;
2557                             }
2558                         }
2559                         xmlStr += match[0];
2560                         if (depth <= 0) {
2561                             break;
2562                         }
2563                         match = input.match(xmlRegExp);
2564                     }
2565                     // if we didn't close correctly, keep unformatted.
2566                     if (!match) {
2567                         xmlStr += input.match(/[\s\S]*/g)[0];
2568                     }
2569                     xmlStr = xmlStr.replace(acorn.allLineBreaks, '\n');
2570                     return [xmlStr, "TK_STRING"];
2571                 }
2572             } else {
2573                 //
2574                 // handle string
2575                 //
2576                 var parse_string = function(delimiter, allow_unescaped_newlines, start_sub) {
2577                     // Template strings can travers lines without escape characters.
2578                     // Other strings cannot
2579                     var current_char;
2580                     while (input.hasNext()) {
2581                         current_char = input.peek();
2582                         if (!(esc || (current_char !== delimiter &&
2583                                 (allow_unescaped_newlines || !acorn.newline.test(current_char))))) {
2584                             break;
2585                         }
2587                         // Handle \r\n linebreaks after escapes or in template strings
2588                         if ((esc || allow_unescaped_newlines) && acorn.newline.test(current_char)) {
2589                             if (current_char === '\r' && input.peek(1) === '\n') {
2590                                 input.next();
2591                                 current_char = input.peek();
2592                             }
2593                             resulting_string += '\n';
2594                         } else {
2595                             resulting_string += current_char;
2596                         }
2598                         if (esc) {
2599                             if (current_char === 'x' || current_char === 'u') {
2600                                 has_char_escapes = true;
2601                             }
2602                             esc = false;
2603                         } else {
2604                             esc = current_char === '\\';
2605                         }
2607                         input.next();
2609                         if (start_sub && resulting_string.indexOf(start_sub, resulting_string.length - start_sub.length) !== -1) {
2610                             if (delimiter === '`') {
2611                                 parse_string('}', allow_unescaped_newlines, '`');
2612                             } else {
2613                                 parse_string('`', allow_unescaped_newlines, '${');
2614                             }
2616                             if (input.hasNext()) {
2617                                 resulting_string += input.next();
2618                             }
2619                         }
2620                     }
2621                 };
2623                 if (sep === '`') {
2624                     parse_string('`', true, '${');
2625                 } else {
2626                     parse_string(sep);
2627                 }
2628             }
2630             if (has_char_escapes && opts.unescape_strings) {
2631                 resulting_string = unescape_string(resulting_string);
2632             }
2634             if (input.peek() === sep) {
2635                 resulting_string += sep;
2636                 input.next();
2638                 if (sep === '/') {
2639                     // regexps may have modifiers /regexp/MOD , so fetch those, too
2640                     // Only [gim] are valid, but if the user puts in garbage, do what we can to take it.
2641                     while (input.hasNext() && acorn.isIdentifierStart(input.peekCharCode())) {
2642                         resulting_string += input.next();
2643                     }
2644                 }
2645             }
2646             return [resulting_string, 'TK_STRING'];
2647         }
2649         if (c === '#') {
2651             if (tokens.length === 0 && input.peek() === '!') {
2652                 // shebang
2653                 resulting_string = c;
2654                 while (input.hasNext() && c !== '\n') {
2655                     c = input.next();
2656                     resulting_string += c;
2657                 }
2658                 return [trim(resulting_string) + '\n', 'TK_UNKNOWN'];
2659             }
2663             // Spidermonkey-specific sharp variables for circular references
2664             // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
2665             // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935
2666             var sharp = '#';
2667             if (input.hasNext() && input.testChar(digit)) {
2668                 do {
2669                     c = input.next();
2670                     sharp += c;
2671                 } while (input.hasNext() && c !== '#' && c !== '=');
2672                 if (c === '#') {
2673                     //
2674                 } else if (input.peek() === '[' && input.peek(1) === ']') {
2675                     sharp += '[]';
2676                     input.next();
2677                     input.next();
2678                 } else if (input.peek() === '{' && input.peek(1) === '}') {
2679                     sharp += '{}';
2680                     input.next();
2681                     input.next();
2682                 }
2683                 return [sharp, 'TK_WORD'];
2684             }
2685         }
2687         if (c === '<' && (input.peek() === '?' || input.peek() === '%')) {
2688             input.back();
2689             var template_match = input.match(template_pattern);
2690             if (template_match) {
2691                 c = template_match[0];
2692                 c = c.replace(acorn.allLineBreaks, '\n');
2693                 return [c, 'TK_STRING'];
2694             }
2695         }
2697         if (c === '<' && input.match(/\!--/g)) {
2698             c = '<!--';
2699             while (input.hasNext() && !input.testChar(acorn.newline)) {
2700                 c += input.next();
2701             }
2702             in_html_comment = true;
2703             return [c, 'TK_COMMENT'];
2704         }
2706         if (c === '-' && in_html_comment && input.match(/->/g)) {
2707             in_html_comment = false;
2708             return ['-->', 'TK_COMMENT'];
2709         }
2711         if (c === '.') {
2712             if (input.peek() === '.' && input.peek(1) === '.') {
2713                 c += input.next() + input.next();
2714                 return [c, 'TK_OPERATOR'];
2715             }
2716             return [c, 'TK_DOT'];
2717         }
2719         if (in_array(c, punct)) {
2720             while (input.hasNext() && in_array(c + input.peek(), punct)) {
2721                 c += input.next();
2722                 if (!input.hasNext()) {
2723                     break;
2724                 }
2725             }
2727             if (c === ',') {
2728                 return [c, 'TK_COMMA'];
2729             } else if (c === '=') {
2730                 return [c, 'TK_EQUALS'];
2731             } else {
2732                 return [c, 'TK_OPERATOR'];
2733             }
2734         }
2736         return [c, 'TK_UNKNOWN'];
2737     }
2740     function unescape_string(s) {
2741         // You think that a regex would work for this
2742         // return s.replace(/\\x([0-9a-f]{2})/gi, function(match, val) {
2743         //         return String.fromCharCode(parseInt(val, 16));
2744         //     })
2745         // However, dealing with '\xff', '\\xff', '\\\xff' makes this more fun.
2746         var out = '',
2747             escaped = 0;
2749         var input_scan = new InputScanner(s);
2750         var matched = null;
2752         while (input_scan.hasNext()) {
2753             // Keep any whitespace, non-slash characters
2754             // also keep slash pairs.
2755             matched = input_scan.match(/([\s]|[^\\]|\\\\)+/g);
2757             if (matched) {
2758                 out += matched[0];
2759             }
2761             if (input_scan.peek() === '\\') {
2762                 input_scan.next();
2763                 if (input_scan.peek() === 'x') {
2764                     matched = input_scan.match(/x([0-9A-Fa-f]{2})/g);
2765                 } else if (input_scan.peek() === 'u') {
2766                     matched = input_scan.match(/u([0-9A-Fa-f]{4})/g);
2767                 } else {
2768                     out += '\\';
2769                     if (input_scan.hasNext()) {
2770                         out += input_scan.next();
2771                     }
2772                     continue;
2773                 }
2775                 // If there's some error decoding, return the original string
2776                 if (!matched) {
2777                     return s;
2778                 }
2780                 escaped = parseInt(matched[1], 16);
2782                 if (escaped > 0x7e && escaped <= 0xff && matched[0].indexOf('x') === 0) {
2783                     // we bail out on \x7f..\xff,
2784                     // leaving whole string escaped,
2785                     // as it's probably completely binary
2786                     return s;
2787                 } else if (escaped >= 0x00 && escaped < 0x20) {
2788                     // leave 0x00...0x1f escaped
2789                     out += '\\' + matched[0];
2790                     continue;
2791                 } else if (escaped === 0x22 || escaped === 0x27 || escaped === 0x5c) {
2792                     // single-quote, apostrophe, backslash - escape these
2793                     out += '\\' + String.fromCharCode(escaped);
2794                 } else {
2795                     out += String.fromCharCode(escaped);
2796                 }
2797             }
2798         }
2800         return out;
2801     }
2804 module.exports.Tokenizer = Tokenizer;
2806 /***/ })
2807 /******/ ]);
2808 var js_beautify = legacy_beautify_js;
2809 /* Footer */
2810 if (typeof define === "function" && define.amd) {
2811     // Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
2812     define([], function() {
2813         return { js_beautify: js_beautify };
2814     });
2815 } else if (typeof exports !== "undefined") {
2816     // Add support for CommonJS. Just put this file somewhere on your require.paths
2817     // and you will be able to `var js_beautify = require("beautify").js_beautify`.
2818     exports.js_beautify = js_beautify;
2819 } else if (typeof window !== "undefined") {
2820     // If we're running a web page and don't have either of the above, add our one global
2821     window.js_beautify = js_beautify;
2822 } else if (typeof global !== "undefined") {
2823     // If we don't even have window, try global.
2824     global.js_beautify = js_beautify;
2827 }());