Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /*jslint onevar: false, plusplus: false */ |
michael@0 | 2 | /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */ |
michael@0 | 3 | /* |
michael@0 | 4 | |
michael@0 | 5 | JS Beautifier |
michael@0 | 6 | --------------- |
michael@0 | 7 | |
michael@0 | 8 | |
michael@0 | 9 | Written by Einar Lielmanis, <einar@jsbeautifier.org> |
michael@0 | 10 | http://jsbeautifier.org/ |
michael@0 | 11 | |
michael@0 | 12 | Originally converted to javascript by Vital, <vital76@gmail.com> |
michael@0 | 13 | "End braces on own line" added by Chris J. Shull, <chrisjshull@gmail.com> |
michael@0 | 14 | |
michael@0 | 15 | You are free to use this in any way you want, in case you find this useful or working for you. |
michael@0 | 16 | |
michael@0 | 17 | Usage: |
michael@0 | 18 | js_beautify(js_source_text); |
michael@0 | 19 | js_beautify(js_source_text, options); |
michael@0 | 20 | |
michael@0 | 21 | The options are: |
michael@0 | 22 | indent_size (default 4) - indentation size, |
michael@0 | 23 | indent_char (default space) - character to indent with, |
michael@0 | 24 | preserve_newlines (default true) - whether existing line breaks should be preserved, |
michael@0 | 25 | max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk, |
michael@0 | 26 | |
michael@0 | 27 | jslint_happy (default false) - if true, then jslint-stricter mode is enforced. |
michael@0 | 28 | |
michael@0 | 29 | jslint_happy !jslint_happy |
michael@0 | 30 | --------------------------------- |
michael@0 | 31 | function () function() |
michael@0 | 32 | |
michael@0 | 33 | brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "expand-strict" |
michael@0 | 34 | 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. |
michael@0 | 35 | |
michael@0 | 36 | expand-strict: put brace on own line even in such cases: |
michael@0 | 37 | |
michael@0 | 38 | var a = |
michael@0 | 39 | { |
michael@0 | 40 | a: 5, |
michael@0 | 41 | b: 6 |
michael@0 | 42 | } |
michael@0 | 43 | This mode may break your scripts - e.g "return { a: 1 }" will be broken into two lines, so beware. |
michael@0 | 44 | |
michael@0 | 45 | space_before_conditional (default true) - should the space before conditional statement be added, "if(true)" vs "if (true)", |
michael@0 | 46 | |
michael@0 | 47 | unescape_strings (default false) - should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65" |
michael@0 | 48 | |
michael@0 | 49 | e.g |
michael@0 | 50 | |
michael@0 | 51 | js_beautify(js_source_text, { |
michael@0 | 52 | 'indent_size': 1, |
michael@0 | 53 | 'indent_char': '\t' |
michael@0 | 54 | }); |
michael@0 | 55 | |
michael@0 | 56 | |
michael@0 | 57 | */ |
michael@0 | 58 | |
michael@0 | 59 | this.EXPORTED_SYMBOLS = ["js_beautify"]; |
michael@0 | 60 | |
michael@0 | 61 | this.js_beautify = function js_beautify(js_source_text, options) { |
michael@0 | 62 | |
michael@0 | 63 | var input, output, token_text, last_type, last_text, last_last_text, last_word, flags, flag_store, indent_string; |
michael@0 | 64 | var whitespace, wordchar, punct, parser_pos, line_starters, digits; |
michael@0 | 65 | var prefix, token_type, do_block_just_closed; |
michael@0 | 66 | var wanted_newline, just_added_newline, n_newlines; |
michael@0 | 67 | var preindent_string = ''; |
michael@0 | 68 | |
michael@0 | 69 | |
michael@0 | 70 | // Some interpreters have unexpected results with foo = baz || bar; |
michael@0 | 71 | options = options ? options : {}; |
michael@0 | 72 | |
michael@0 | 73 | var opt_brace_style; |
michael@0 | 74 | |
michael@0 | 75 | // compatibility |
michael@0 | 76 | if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) { |
michael@0 | 77 | options.jslint_happy = options.space_after_anon_function; |
michael@0 | 78 | } |
michael@0 | 79 | if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option |
michael@0 | 80 | opt_brace_style = options.braces_on_own_line ? "expand" : "collapse"; |
michael@0 | 81 | } |
michael@0 | 82 | opt_brace_style = options.brace_style ? options.brace_style : (opt_brace_style ? opt_brace_style : "collapse"); |
michael@0 | 83 | |
michael@0 | 84 | |
michael@0 | 85 | var opt_indent_size = options.indent_size ? options.indent_size : 4; |
michael@0 | 86 | var opt_indent_char = options.indent_char ? options.indent_char : ' '; |
michael@0 | 87 | var opt_preserve_newlines = typeof options.preserve_newlines === 'undefined' ? true : options.preserve_newlines; |
michael@0 | 88 | var opt_max_preserve_newlines = typeof options.max_preserve_newlines === 'undefined' ? false : options.max_preserve_newlines; |
michael@0 | 89 | var opt_jslint_happy = options.jslint_happy === 'undefined' ? false : options.jslint_happy; |
michael@0 | 90 | var opt_keep_array_indentation = typeof options.keep_array_indentation === 'undefined' ? false : options.keep_array_indentation; |
michael@0 | 91 | var opt_space_before_conditional = typeof options.space_before_conditional === 'undefined' ? true : options.space_before_conditional; |
michael@0 | 92 | var opt_indent_case = typeof options.indent_case === 'undefined' ? false : options.indent_case; |
michael@0 | 93 | var opt_unescape_strings = typeof options.unescape_strings === 'undefined' ? false : options.unescape_strings; |
michael@0 | 94 | |
michael@0 | 95 | just_added_newline = false; |
michael@0 | 96 | |
michael@0 | 97 | // cache the source's length. |
michael@0 | 98 | var input_length = js_source_text.length; |
michael@0 | 99 | |
michael@0 | 100 | function trim_output(eat_newlines) { |
michael@0 | 101 | eat_newlines = typeof eat_newlines === 'undefined' ? false : eat_newlines; |
michael@0 | 102 | while (output.length && (output[output.length - 1] === ' ' |
michael@0 | 103 | || output[output.length - 1] === indent_string |
michael@0 | 104 | || output[output.length - 1] === preindent_string |
michael@0 | 105 | || (eat_newlines && (output[output.length - 1] === '\n' || output[output.length - 1] === '\r')))) { |
michael@0 | 106 | output.pop(); |
michael@0 | 107 | } |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | function trim(s) { |
michael@0 | 111 | return s.replace(/^\s\s*|\s\s*$/, ''); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | // we could use just string.split, but |
michael@0 | 115 | // IE doesn't like returning empty strings |
michael@0 | 116 | function split_newlines(s) { |
michael@0 | 117 | return s.split(/\x0d\x0a|\x0a/); |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | function force_newline() { |
michael@0 | 121 | var old_keep_array_indentation = opt_keep_array_indentation; |
michael@0 | 122 | opt_keep_array_indentation = false; |
michael@0 | 123 | print_newline(); |
michael@0 | 124 | opt_keep_array_indentation = old_keep_array_indentation; |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | function print_newline(ignore_repeated) { |
michael@0 | 128 | |
michael@0 | 129 | flags.eat_next_space = false; |
michael@0 | 130 | if (opt_keep_array_indentation && is_array(flags.mode)) { |
michael@0 | 131 | return; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | ignore_repeated = typeof ignore_repeated === 'undefined' ? true : ignore_repeated; |
michael@0 | 135 | |
michael@0 | 136 | flags.if_line = false; |
michael@0 | 137 | trim_output(); |
michael@0 | 138 | |
michael@0 | 139 | if (!output.length) { |
michael@0 | 140 | return; // no newline on start of file |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | if (output[output.length - 1] !== "\n" || !ignore_repeated) { |
michael@0 | 144 | just_added_newline = true; |
michael@0 | 145 | output.push("\n"); |
michael@0 | 146 | } |
michael@0 | 147 | if (preindent_string) { |
michael@0 | 148 | output.push(preindent_string); |
michael@0 | 149 | } |
michael@0 | 150 | for (var i = 0; i < flags.indentation_level; i += 1) { |
michael@0 | 151 | output.push(indent_string); |
michael@0 | 152 | } |
michael@0 | 153 | if (flags.var_line && flags.var_line_reindented) { |
michael@0 | 154 | output.push(indent_string); // skip space-stuffing, if indenting with a tab |
michael@0 | 155 | } |
michael@0 | 156 | if (flags.case_body) { |
michael@0 | 157 | output.push(indent_string); |
michael@0 | 158 | } |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | |
michael@0 | 162 | |
michael@0 | 163 | function print_single_space() { |
michael@0 | 164 | |
michael@0 | 165 | if (last_type === 'TK_COMMENT') { |
michael@0 | 166 | return print_newline(); |
michael@0 | 167 | } |
michael@0 | 168 | if (flags.eat_next_space) { |
michael@0 | 169 | flags.eat_next_space = false; |
michael@0 | 170 | return; |
michael@0 | 171 | } |
michael@0 | 172 | var last_output = ' '; |
michael@0 | 173 | if (output.length) { |
michael@0 | 174 | last_output = output[output.length - 1]; |
michael@0 | 175 | } |
michael@0 | 176 | if (last_output !== ' ' && last_output !== '\n' && last_output !== indent_string) { // prevent occassional duplicate space |
michael@0 | 177 | output.push(' '); |
michael@0 | 178 | } |
michael@0 | 179 | } |
michael@0 | 180 | |
michael@0 | 181 | |
michael@0 | 182 | function print_token() { |
michael@0 | 183 | just_added_newline = false; |
michael@0 | 184 | flags.eat_next_space = false; |
michael@0 | 185 | output.push(token_text); |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | function indent() { |
michael@0 | 189 | flags.indentation_level += 1; |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | |
michael@0 | 193 | function remove_indent() { |
michael@0 | 194 | if (output.length && output[output.length - 1] === indent_string) { |
michael@0 | 195 | output.pop(); |
michael@0 | 196 | } |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | function set_mode(mode) { |
michael@0 | 200 | if (flags) { |
michael@0 | 201 | flag_store.push(flags); |
michael@0 | 202 | } |
michael@0 | 203 | flags = { |
michael@0 | 204 | previous_mode: flags ? flags.mode : 'BLOCK', |
michael@0 | 205 | mode: mode, |
michael@0 | 206 | var_line: false, |
michael@0 | 207 | var_line_tainted: false, |
michael@0 | 208 | var_line_reindented: false, |
michael@0 | 209 | in_html_comment: false, |
michael@0 | 210 | if_line: false, |
michael@0 | 211 | in_case_statement: false, // switch(..){ INSIDE HERE } |
michael@0 | 212 | in_case: false, // we're on the exact line with "case 0:" |
michael@0 | 213 | case_body: false, // the indented case-action block |
michael@0 | 214 | eat_next_space: false, |
michael@0 | 215 | indentation_baseline: -1, |
michael@0 | 216 | indentation_level: (flags ? flags.indentation_level + (flags.case_body ? 1 : 0) + ((flags.var_line && flags.var_line_reindented) ? 1 : 0) : 0), |
michael@0 | 217 | ternary_depth: 0 |
michael@0 | 218 | }; |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | function is_array(mode) { |
michael@0 | 222 | return mode === '[EXPRESSION]' || mode === '[INDENTED-EXPRESSION]'; |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | function is_expression(mode) { |
michael@0 | 226 | return in_array(mode, ['[EXPRESSION]', '(EXPRESSION)', '(FOR-EXPRESSION)', '(COND-EXPRESSION)']); |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | function restore_mode() { |
michael@0 | 230 | do_block_just_closed = flags.mode === 'DO_BLOCK'; |
michael@0 | 231 | if (flag_store.length > 0) { |
michael@0 | 232 | var mode = flags.mode; |
michael@0 | 233 | flags = flag_store.pop(); |
michael@0 | 234 | flags.previous_mode = mode; |
michael@0 | 235 | } |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | function all_lines_start_with(lines, c) { |
michael@0 | 239 | for (var i = 0; i < lines.length; i++) { |
michael@0 | 240 | var line = trim(lines[i]); |
michael@0 | 241 | if (line.charAt(0) !== c) { |
michael@0 | 242 | return false; |
michael@0 | 243 | } |
michael@0 | 244 | } |
michael@0 | 245 | return true; |
michael@0 | 246 | } |
michael@0 | 247 | |
michael@0 | 248 | function is_special_word(word) { |
michael@0 | 249 | return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']); |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | function in_array(what, arr) { |
michael@0 | 253 | for (var i = 0; i < arr.length; i += 1) { |
michael@0 | 254 | if (arr[i] === what) { |
michael@0 | 255 | return true; |
michael@0 | 256 | } |
michael@0 | 257 | } |
michael@0 | 258 | return false; |
michael@0 | 259 | } |
michael@0 | 260 | |
michael@0 | 261 | function look_up(exclude) { |
michael@0 | 262 | var local_pos = parser_pos; |
michael@0 | 263 | var c = input.charAt(local_pos); |
michael@0 | 264 | while (in_array(c, whitespace) && c !== exclude) { |
michael@0 | 265 | local_pos++; |
michael@0 | 266 | if (local_pos >= input_length) { |
michael@0 | 267 | return 0; |
michael@0 | 268 | } |
michael@0 | 269 | c = input.charAt(local_pos); |
michael@0 | 270 | } |
michael@0 | 271 | return c; |
michael@0 | 272 | } |
michael@0 | 273 | |
michael@0 | 274 | function get_next_token() { |
michael@0 | 275 | var i; |
michael@0 | 276 | var resulting_string; |
michael@0 | 277 | |
michael@0 | 278 | n_newlines = 0; |
michael@0 | 279 | |
michael@0 | 280 | if (parser_pos >= input_length) { |
michael@0 | 281 | return ['', 'TK_EOF']; |
michael@0 | 282 | } |
michael@0 | 283 | |
michael@0 | 284 | wanted_newline = false; |
michael@0 | 285 | |
michael@0 | 286 | var c = input.charAt(parser_pos); |
michael@0 | 287 | parser_pos += 1; |
michael@0 | 288 | |
michael@0 | 289 | |
michael@0 | 290 | var keep_whitespace = opt_keep_array_indentation && is_array(flags.mode); |
michael@0 | 291 | |
michael@0 | 292 | if (keep_whitespace) { |
michael@0 | 293 | |
michael@0 | 294 | // |
michael@0 | 295 | // slight mess to allow nice preservation of array indentation and reindent that correctly |
michael@0 | 296 | // first time when we get to the arrays: |
michael@0 | 297 | // var a = [ |
michael@0 | 298 | // ....'something' |
michael@0 | 299 | // we make note of whitespace_count = 4 into flags.indentation_baseline |
michael@0 | 300 | // so we know that 4 whitespaces in original source match indent_level of reindented source |
michael@0 | 301 | // |
michael@0 | 302 | // and afterwards, when we get to |
michael@0 | 303 | // 'something, |
michael@0 | 304 | // .......'something else' |
michael@0 | 305 | // we know that this should be indented to indent_level + (7 - indentation_baseline) spaces |
michael@0 | 306 | // |
michael@0 | 307 | var whitespace_count = 0; |
michael@0 | 308 | |
michael@0 | 309 | while (in_array(c, whitespace)) { |
michael@0 | 310 | |
michael@0 | 311 | if (c === "\n") { |
michael@0 | 312 | trim_output(); |
michael@0 | 313 | output.push("\n"); |
michael@0 | 314 | just_added_newline = true; |
michael@0 | 315 | whitespace_count = 0; |
michael@0 | 316 | } else { |
michael@0 | 317 | if (c === '\t') { |
michael@0 | 318 | whitespace_count += 4; |
michael@0 | 319 | } else if (c === '\r') { |
michael@0 | 320 | // nothing |
michael@0 | 321 | } else { |
michael@0 | 322 | whitespace_count += 1; |
michael@0 | 323 | } |
michael@0 | 324 | } |
michael@0 | 325 | |
michael@0 | 326 | if (parser_pos >= input_length) { |
michael@0 | 327 | return ['', 'TK_EOF']; |
michael@0 | 328 | } |
michael@0 | 329 | |
michael@0 | 330 | c = input.charAt(parser_pos); |
michael@0 | 331 | parser_pos += 1; |
michael@0 | 332 | |
michael@0 | 333 | } |
michael@0 | 334 | if (flags.indentation_baseline === -1) { |
michael@0 | 335 | flags.indentation_baseline = whitespace_count; |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | if (just_added_newline) { |
michael@0 | 339 | for (i = 0; i < flags.indentation_level + 1; i += 1) { |
michael@0 | 340 | output.push(indent_string); |
michael@0 | 341 | } |
michael@0 | 342 | if (flags.indentation_baseline !== -1) { |
michael@0 | 343 | for (i = 0; i < whitespace_count - flags.indentation_baseline; i++) { |
michael@0 | 344 | output.push(' '); |
michael@0 | 345 | } |
michael@0 | 346 | } |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | } else { |
michael@0 | 350 | while (in_array(c, whitespace)) { |
michael@0 | 351 | |
michael@0 | 352 | if (c === "\n") { |
michael@0 | 353 | n_newlines += ((opt_max_preserve_newlines) ? (n_newlines <= opt_max_preserve_newlines) ? 1 : 0 : 1); |
michael@0 | 354 | } |
michael@0 | 355 | |
michael@0 | 356 | |
michael@0 | 357 | if (parser_pos >= input_length) { |
michael@0 | 358 | return ['', 'TK_EOF']; |
michael@0 | 359 | } |
michael@0 | 360 | |
michael@0 | 361 | c = input.charAt(parser_pos); |
michael@0 | 362 | parser_pos += 1; |
michael@0 | 363 | |
michael@0 | 364 | } |
michael@0 | 365 | |
michael@0 | 366 | if (opt_preserve_newlines) { |
michael@0 | 367 | if (n_newlines > 1) { |
michael@0 | 368 | for (i = 0; i < n_newlines; i += 1) { |
michael@0 | 369 | print_newline(i === 0); |
michael@0 | 370 | just_added_newline = true; |
michael@0 | 371 | } |
michael@0 | 372 | } |
michael@0 | 373 | } |
michael@0 | 374 | wanted_newline = n_newlines > 0; |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | |
michael@0 | 378 | if (in_array(c, wordchar)) { |
michael@0 | 379 | if (parser_pos < input_length) { |
michael@0 | 380 | while (in_array(input.charAt(parser_pos), wordchar)) { |
michael@0 | 381 | c += input.charAt(parser_pos); |
michael@0 | 382 | parser_pos += 1; |
michael@0 | 383 | if (parser_pos === input_length) { |
michael@0 | 384 | break; |
michael@0 | 385 | } |
michael@0 | 386 | } |
michael@0 | 387 | } |
michael@0 | 388 | |
michael@0 | 389 | // small and surprisingly unugly hack for 1E-10 representation |
michael@0 | 390 | if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) { |
michael@0 | 391 | |
michael@0 | 392 | var sign = input.charAt(parser_pos); |
michael@0 | 393 | parser_pos += 1; |
michael@0 | 394 | |
michael@0 | 395 | var t = get_next_token(); |
michael@0 | 396 | c += sign + t[0]; |
michael@0 | 397 | return [c, 'TK_WORD']; |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | if (c === 'in') { // hack for 'in' operator |
michael@0 | 401 | return [c, 'TK_OPERATOR']; |
michael@0 | 402 | } |
michael@0 | 403 | if (wanted_newline && last_type !== 'TK_OPERATOR' |
michael@0 | 404 | && last_type !== 'TK_EQUALS' |
michael@0 | 405 | && !flags.if_line && (opt_preserve_newlines || last_text !== 'var')) { |
michael@0 | 406 | print_newline(); |
michael@0 | 407 | } |
michael@0 | 408 | return [c, 'TK_WORD']; |
michael@0 | 409 | } |
michael@0 | 410 | |
michael@0 | 411 | if (c === '(' || c === '[') { |
michael@0 | 412 | return [c, 'TK_START_EXPR']; |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | if (c === ')' || c === ']') { |
michael@0 | 416 | return [c, 'TK_END_EXPR']; |
michael@0 | 417 | } |
michael@0 | 418 | |
michael@0 | 419 | if (c === '{') { |
michael@0 | 420 | return [c, 'TK_START_BLOCK']; |
michael@0 | 421 | } |
michael@0 | 422 | |
michael@0 | 423 | if (c === '}') { |
michael@0 | 424 | return [c, 'TK_END_BLOCK']; |
michael@0 | 425 | } |
michael@0 | 426 | |
michael@0 | 427 | if (c === ';') { |
michael@0 | 428 | return [c, 'TK_SEMICOLON']; |
michael@0 | 429 | } |
michael@0 | 430 | |
michael@0 | 431 | if (c === '/') { |
michael@0 | 432 | var comment = ''; |
michael@0 | 433 | // peek for comment /* ... */ |
michael@0 | 434 | var inline_comment = true; |
michael@0 | 435 | if (input.charAt(parser_pos) === '*') { |
michael@0 | 436 | parser_pos += 1; |
michael@0 | 437 | if (parser_pos < input_length) { |
michael@0 | 438 | while (parser_pos < input_length && |
michael@0 | 439 | ! (input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) { |
michael@0 | 440 | c = input.charAt(parser_pos); |
michael@0 | 441 | comment += c; |
michael@0 | 442 | if (c === "\n" || c === "\r") { |
michael@0 | 443 | inline_comment = false; |
michael@0 | 444 | } |
michael@0 | 445 | parser_pos += 1; |
michael@0 | 446 | if (parser_pos >= input_length) { |
michael@0 | 447 | break; |
michael@0 | 448 | } |
michael@0 | 449 | } |
michael@0 | 450 | } |
michael@0 | 451 | parser_pos += 2; |
michael@0 | 452 | if (inline_comment && n_newlines === 0) { |
michael@0 | 453 | return ['/*' + comment + '*/', 'TK_INLINE_COMMENT']; |
michael@0 | 454 | } else { |
michael@0 | 455 | return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT']; |
michael@0 | 456 | } |
michael@0 | 457 | } |
michael@0 | 458 | // peek for comment // ... |
michael@0 | 459 | if (input.charAt(parser_pos) === '/') { |
michael@0 | 460 | comment = c; |
michael@0 | 461 | while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') { |
michael@0 | 462 | comment += input.charAt(parser_pos); |
michael@0 | 463 | parser_pos += 1; |
michael@0 | 464 | if (parser_pos >= input_length) { |
michael@0 | 465 | break; |
michael@0 | 466 | } |
michael@0 | 467 | } |
michael@0 | 468 | if (wanted_newline) { |
michael@0 | 469 | print_newline(); |
michael@0 | 470 | } |
michael@0 | 471 | return [comment, 'TK_COMMENT']; |
michael@0 | 472 | } |
michael@0 | 473 | |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | if (c === "'" || // string |
michael@0 | 477 | c === '"' || // string |
michael@0 | 478 | (c === '/' && |
michael@0 | 479 | ((last_type === 'TK_WORD' && is_special_word(last_text)) || |
michael@0 | 480 | (last_text === ')' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) || |
michael@0 | 481 | (last_type === 'TK_COMMA' || last_type === 'TK_COMMENT' || last_type === 'TK_START_EXPR' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_OPERATOR' || last_type === 'TK_EQUALS' || last_type === 'TK_EOF' || last_type === 'TK_SEMICOLON')))) { // regexp |
michael@0 | 482 | var sep = c; |
michael@0 | 483 | var esc = false; |
michael@0 | 484 | var esc1 = 0; |
michael@0 | 485 | var esc2 = 0; |
michael@0 | 486 | resulting_string = c; |
michael@0 | 487 | |
michael@0 | 488 | if (parser_pos < input_length) { |
michael@0 | 489 | if (sep === '/') { |
michael@0 | 490 | // |
michael@0 | 491 | // handle regexp separately... |
michael@0 | 492 | // |
michael@0 | 493 | var in_char_class = false; |
michael@0 | 494 | while (esc || in_char_class || input.charAt(parser_pos) !== sep) { |
michael@0 | 495 | resulting_string += input.charAt(parser_pos); |
michael@0 | 496 | if (!esc) { |
michael@0 | 497 | esc = input.charAt(parser_pos) === '\\'; |
michael@0 | 498 | if (input.charAt(parser_pos) === '[') { |
michael@0 | 499 | in_char_class = true; |
michael@0 | 500 | } else if (input.charAt(parser_pos) === ']') { |
michael@0 | 501 | in_char_class = false; |
michael@0 | 502 | } |
michael@0 | 503 | } else { |
michael@0 | 504 | esc = false; |
michael@0 | 505 | } |
michael@0 | 506 | parser_pos += 1; |
michael@0 | 507 | if (parser_pos >= input_length) { |
michael@0 | 508 | // incomplete string/rexp when end-of-file reached. |
michael@0 | 509 | // bail out with what had been received so far. |
michael@0 | 510 | return [resulting_string, 'TK_STRING']; |
michael@0 | 511 | } |
michael@0 | 512 | } |
michael@0 | 513 | |
michael@0 | 514 | } else { |
michael@0 | 515 | // |
michael@0 | 516 | // and handle string also separately |
michael@0 | 517 | // |
michael@0 | 518 | while (esc || input.charAt(parser_pos) !== sep) { |
michael@0 | 519 | resulting_string += input.charAt(parser_pos); |
michael@0 | 520 | if (esc1 && esc1 >= esc2) { |
michael@0 | 521 | esc1 = parseInt(resulting_string.substr(-esc2), 16); |
michael@0 | 522 | if (esc1 && esc1 >= 0x20 && esc1 <= 0x7e) { |
michael@0 | 523 | esc1 = String.fromCharCode(esc1); |
michael@0 | 524 | resulting_string = resulting_string.substr(0, resulting_string.length - esc2 - 2) + (((esc1 === sep) || (esc1 === '\\')) ? '\\' : '') + esc1; |
michael@0 | 525 | } |
michael@0 | 526 | esc1 = 0; |
michael@0 | 527 | } |
michael@0 | 528 | if (esc1) { |
michael@0 | 529 | esc1++; |
michael@0 | 530 | } else if (!esc) { |
michael@0 | 531 | esc = input.charAt(parser_pos) === '\\'; |
michael@0 | 532 | } else { |
michael@0 | 533 | esc = false; |
michael@0 | 534 | if (opt_unescape_strings) { |
michael@0 | 535 | if (input.charAt(parser_pos) === 'x') { |
michael@0 | 536 | esc1++; |
michael@0 | 537 | esc2 = 2; |
michael@0 | 538 | } else if (input.charAt(parser_pos) === 'u') { |
michael@0 | 539 | esc1++; |
michael@0 | 540 | esc2 = 4; |
michael@0 | 541 | } |
michael@0 | 542 | } |
michael@0 | 543 | } |
michael@0 | 544 | parser_pos += 1; |
michael@0 | 545 | if (parser_pos >= input_length) { |
michael@0 | 546 | // incomplete string/rexp when end-of-file reached. |
michael@0 | 547 | // bail out with what had been received so far. |
michael@0 | 548 | return [resulting_string, 'TK_STRING']; |
michael@0 | 549 | } |
michael@0 | 550 | } |
michael@0 | 551 | } |
michael@0 | 552 | |
michael@0 | 553 | |
michael@0 | 554 | |
michael@0 | 555 | } |
michael@0 | 556 | |
michael@0 | 557 | parser_pos += 1; |
michael@0 | 558 | |
michael@0 | 559 | resulting_string += sep; |
michael@0 | 560 | |
michael@0 | 561 | if (sep === '/') { |
michael@0 | 562 | // regexps may have modifiers /regexp/MOD , so fetch those, too |
michael@0 | 563 | while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) { |
michael@0 | 564 | resulting_string += input.charAt(parser_pos); |
michael@0 | 565 | parser_pos += 1; |
michael@0 | 566 | } |
michael@0 | 567 | } |
michael@0 | 568 | return [resulting_string, 'TK_STRING']; |
michael@0 | 569 | } |
michael@0 | 570 | |
michael@0 | 571 | if (c === '#') { |
michael@0 | 572 | |
michael@0 | 573 | |
michael@0 | 574 | if (output.length === 0 && input.charAt(parser_pos) === '!') { |
michael@0 | 575 | // shebang |
michael@0 | 576 | resulting_string = c; |
michael@0 | 577 | while (parser_pos < input_length && c !== '\n') { |
michael@0 | 578 | c = input.charAt(parser_pos); |
michael@0 | 579 | resulting_string += c; |
michael@0 | 580 | parser_pos += 1; |
michael@0 | 581 | } |
michael@0 | 582 | output.push(trim(resulting_string) + '\n'); |
michael@0 | 583 | print_newline(); |
michael@0 | 584 | return get_next_token(); |
michael@0 | 585 | } |
michael@0 | 586 | |
michael@0 | 587 | |
michael@0 | 588 | |
michael@0 | 589 | // Spidermonkey-specific sharp variables for circular references |
michael@0 | 590 | // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript |
michael@0 | 591 | // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935 |
michael@0 | 592 | var sharp = '#'; |
michael@0 | 593 | if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) { |
michael@0 | 594 | do { |
michael@0 | 595 | c = input.charAt(parser_pos); |
michael@0 | 596 | sharp += c; |
michael@0 | 597 | parser_pos += 1; |
michael@0 | 598 | } while (parser_pos < input_length && c !== '#' && c !== '='); |
michael@0 | 599 | if (c === '#') { |
michael@0 | 600 | // |
michael@0 | 601 | } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') { |
michael@0 | 602 | sharp += '[]'; |
michael@0 | 603 | parser_pos += 2; |
michael@0 | 604 | } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') { |
michael@0 | 605 | sharp += '{}'; |
michael@0 | 606 | parser_pos += 2; |
michael@0 | 607 | } |
michael@0 | 608 | return [sharp, 'TK_WORD']; |
michael@0 | 609 | } |
michael@0 | 610 | } |
michael@0 | 611 | |
michael@0 | 612 | if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') { |
michael@0 | 613 | parser_pos += 3; |
michael@0 | 614 | c = '<!--'; |
michael@0 | 615 | while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) { |
michael@0 | 616 | c += input.charAt(parser_pos); |
michael@0 | 617 | parser_pos++; |
michael@0 | 618 | } |
michael@0 | 619 | flags.in_html_comment = true; |
michael@0 | 620 | return [c, 'TK_COMMENT']; |
michael@0 | 621 | } |
michael@0 | 622 | |
michael@0 | 623 | if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') { |
michael@0 | 624 | flags.in_html_comment = false; |
michael@0 | 625 | parser_pos += 2; |
michael@0 | 626 | if (wanted_newline) { |
michael@0 | 627 | print_newline(); |
michael@0 | 628 | } |
michael@0 | 629 | return ['-->', 'TK_COMMENT']; |
michael@0 | 630 | } |
michael@0 | 631 | |
michael@0 | 632 | if (in_array(c, punct)) { |
michael@0 | 633 | while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) { |
michael@0 | 634 | c += input.charAt(parser_pos); |
michael@0 | 635 | parser_pos += 1; |
michael@0 | 636 | if (parser_pos >= input_length) { |
michael@0 | 637 | break; |
michael@0 | 638 | } |
michael@0 | 639 | } |
michael@0 | 640 | |
michael@0 | 641 | if (c === ',') { |
michael@0 | 642 | return [c, 'TK_COMMA']; |
michael@0 | 643 | } else if (c === '=') { |
michael@0 | 644 | return [c, 'TK_EQUALS']; |
michael@0 | 645 | } else { |
michael@0 | 646 | return [c, 'TK_OPERATOR']; |
michael@0 | 647 | } |
michael@0 | 648 | } |
michael@0 | 649 | |
michael@0 | 650 | return [c, 'TK_UNKNOWN']; |
michael@0 | 651 | } |
michael@0 | 652 | |
michael@0 | 653 | //---------------------------------- |
michael@0 | 654 | indent_string = ''; |
michael@0 | 655 | while (opt_indent_size > 0) { |
michael@0 | 656 | indent_string += opt_indent_char; |
michael@0 | 657 | opt_indent_size -= 1; |
michael@0 | 658 | } |
michael@0 | 659 | |
michael@0 | 660 | while (js_source_text && (js_source_text.charAt(0) === ' ' || js_source_text.charAt(0) === '\t')) { |
michael@0 | 661 | preindent_string += js_source_text.charAt(0); |
michael@0 | 662 | js_source_text = js_source_text.substring(1); |
michael@0 | 663 | } |
michael@0 | 664 | input = js_source_text; |
michael@0 | 665 | |
michael@0 | 666 | last_word = ''; // last 'TK_WORD' passed |
michael@0 | 667 | last_type = 'TK_START_EXPR'; // last token type |
michael@0 | 668 | last_text = ''; // last token text |
michael@0 | 669 | last_last_text = ''; // pre-last token text |
michael@0 | 670 | output = []; |
michael@0 | 671 | |
michael@0 | 672 | do_block_just_closed = false; |
michael@0 | 673 | |
michael@0 | 674 | whitespace = "\n\r\t ".split(''); |
michael@0 | 675 | wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split(''); |
michael@0 | 676 | digits = '0123456789'.split(''); |
michael@0 | 677 | |
michael@0 | 678 | punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::'; |
michael@0 | 679 | punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers |
michael@0 | 680 | punct = punct.split(' '); |
michael@0 | 681 | |
michael@0 | 682 | // words which should always start on new line. |
michael@0 | 683 | line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(','); |
michael@0 | 684 | |
michael@0 | 685 | // states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'. |
michael@0 | 686 | // some formatting depends on that. |
michael@0 | 687 | flag_store = []; |
michael@0 | 688 | set_mode('BLOCK'); |
michael@0 | 689 | |
michael@0 | 690 | parser_pos = 0; |
michael@0 | 691 | while (true) { |
michael@0 | 692 | var t = get_next_token(); |
michael@0 | 693 | token_text = t[0]; |
michael@0 | 694 | token_type = t[1]; |
michael@0 | 695 | if (token_type === 'TK_EOF') { |
michael@0 | 696 | break; |
michael@0 | 697 | } |
michael@0 | 698 | |
michael@0 | 699 | switch (token_type) { |
michael@0 | 700 | |
michael@0 | 701 | case 'TK_START_EXPR': |
michael@0 | 702 | |
michael@0 | 703 | if (token_text === '[') { |
michael@0 | 704 | |
michael@0 | 705 | if (last_type === 'TK_WORD' || last_text === ')') { |
michael@0 | 706 | // this is array index specifier, break immediately |
michael@0 | 707 | // a[x], fn()[x] |
michael@0 | 708 | if (in_array(last_text, line_starters)) { |
michael@0 | 709 | print_single_space(); |
michael@0 | 710 | } |
michael@0 | 711 | set_mode('(EXPRESSION)'); |
michael@0 | 712 | print_token(); |
michael@0 | 713 | break; |
michael@0 | 714 | } |
michael@0 | 715 | |
michael@0 | 716 | if (flags.mode === '[EXPRESSION]' || flags.mode === '[INDENTED-EXPRESSION]') { |
michael@0 | 717 | if (last_last_text === ']' && last_text === ',') { |
michael@0 | 718 | // ], [ goes to new line |
michael@0 | 719 | if (flags.mode === '[EXPRESSION]') { |
michael@0 | 720 | flags.mode = '[INDENTED-EXPRESSION]'; |
michael@0 | 721 | if (!opt_keep_array_indentation) { |
michael@0 | 722 | indent(); |
michael@0 | 723 | } |
michael@0 | 724 | } |
michael@0 | 725 | set_mode('[EXPRESSION]'); |
michael@0 | 726 | if (!opt_keep_array_indentation) { |
michael@0 | 727 | print_newline(); |
michael@0 | 728 | } |
michael@0 | 729 | } else if (last_text === '[') { |
michael@0 | 730 | if (flags.mode === '[EXPRESSION]') { |
michael@0 | 731 | flags.mode = '[INDENTED-EXPRESSION]'; |
michael@0 | 732 | if (!opt_keep_array_indentation) { |
michael@0 | 733 | indent(); |
michael@0 | 734 | } |
michael@0 | 735 | } |
michael@0 | 736 | set_mode('[EXPRESSION]'); |
michael@0 | 737 | |
michael@0 | 738 | if (!opt_keep_array_indentation) { |
michael@0 | 739 | print_newline(); |
michael@0 | 740 | } |
michael@0 | 741 | } else { |
michael@0 | 742 | set_mode('[EXPRESSION]'); |
michael@0 | 743 | } |
michael@0 | 744 | } else { |
michael@0 | 745 | set_mode('[EXPRESSION]'); |
michael@0 | 746 | } |
michael@0 | 747 | |
michael@0 | 748 | |
michael@0 | 749 | |
michael@0 | 750 | } else { |
michael@0 | 751 | if (last_word === 'for') { |
michael@0 | 752 | set_mode('(FOR-EXPRESSION)'); |
michael@0 | 753 | } else if (in_array(last_word, ['if', 'while'])) { |
michael@0 | 754 | set_mode('(COND-EXPRESSION)'); |
michael@0 | 755 | } else { |
michael@0 | 756 | set_mode('(EXPRESSION)'); |
michael@0 | 757 | } |
michael@0 | 758 | } |
michael@0 | 759 | |
michael@0 | 760 | if (last_text === ';' || last_type === 'TK_START_BLOCK') { |
michael@0 | 761 | print_newline(); |
michael@0 | 762 | } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || last_text === '.') { |
michael@0 | 763 | if (wanted_newline) { |
michael@0 | 764 | print_newline(); |
michael@0 | 765 | } |
michael@0 | 766 | // do nothing on (( and )( and ][ and ]( and .( |
michael@0 | 767 | } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') { |
michael@0 | 768 | print_single_space(); |
michael@0 | 769 | } else if (last_word === 'function' || last_word === 'typeof') { |
michael@0 | 770 | // function() vs function () |
michael@0 | 771 | if (opt_jslint_happy) { |
michael@0 | 772 | print_single_space(); |
michael@0 | 773 | } |
michael@0 | 774 | } else if (in_array(last_text, line_starters) || last_text === 'catch') { |
michael@0 | 775 | if (opt_space_before_conditional) { |
michael@0 | 776 | print_single_space(); |
michael@0 | 777 | } |
michael@0 | 778 | } |
michael@0 | 779 | print_token(); |
michael@0 | 780 | |
michael@0 | 781 | break; |
michael@0 | 782 | |
michael@0 | 783 | case 'TK_END_EXPR': |
michael@0 | 784 | if (token_text === ']') { |
michael@0 | 785 | if (opt_keep_array_indentation) { |
michael@0 | 786 | if (last_text === '}') { |
michael@0 | 787 | // trim_output(); |
michael@0 | 788 | // print_newline(true); |
michael@0 | 789 | remove_indent(); |
michael@0 | 790 | print_token(); |
michael@0 | 791 | restore_mode(); |
michael@0 | 792 | break; |
michael@0 | 793 | } |
michael@0 | 794 | } else { |
michael@0 | 795 | if (flags.mode === '[INDENTED-EXPRESSION]') { |
michael@0 | 796 | if (last_text === ']') { |
michael@0 | 797 | restore_mode(); |
michael@0 | 798 | print_newline(); |
michael@0 | 799 | print_token(); |
michael@0 | 800 | break; |
michael@0 | 801 | } |
michael@0 | 802 | } |
michael@0 | 803 | } |
michael@0 | 804 | } |
michael@0 | 805 | restore_mode(); |
michael@0 | 806 | print_token(); |
michael@0 | 807 | break; |
michael@0 | 808 | |
michael@0 | 809 | case 'TK_START_BLOCK': |
michael@0 | 810 | |
michael@0 | 811 | if (last_word === 'do') { |
michael@0 | 812 | set_mode('DO_BLOCK'); |
michael@0 | 813 | } else { |
michael@0 | 814 | set_mode('BLOCK'); |
michael@0 | 815 | } |
michael@0 | 816 | if (opt_brace_style === "expand" || opt_brace_style === "expand-strict") { |
michael@0 | 817 | var empty_braces = false; |
michael@0 | 818 | if (opt_brace_style === "expand-strict") { |
michael@0 | 819 | empty_braces = (look_up() === '}'); |
michael@0 | 820 | if (!empty_braces) { |
michael@0 | 821 | print_newline(true); |
michael@0 | 822 | } |
michael@0 | 823 | } else { |
michael@0 | 824 | if (last_type !== 'TK_OPERATOR') { |
michael@0 | 825 | if (last_text === '=' || (is_special_word(last_text) && last_text !== 'else')) { |
michael@0 | 826 | print_single_space(); |
michael@0 | 827 | } else { |
michael@0 | 828 | print_newline(true); |
michael@0 | 829 | } |
michael@0 | 830 | } |
michael@0 | 831 | } |
michael@0 | 832 | print_token(); |
michael@0 | 833 | if (!empty_braces) { |
michael@0 | 834 | indent(); |
michael@0 | 835 | } |
michael@0 | 836 | } else { |
michael@0 | 837 | if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') { |
michael@0 | 838 | if (last_type === 'TK_START_BLOCK') { |
michael@0 | 839 | print_newline(); |
michael@0 | 840 | } else { |
michael@0 | 841 | print_single_space(); |
michael@0 | 842 | } |
michael@0 | 843 | } else { |
michael@0 | 844 | // if TK_OPERATOR or TK_START_EXPR |
michael@0 | 845 | if (is_array(flags.previous_mode) && last_text === ',') { |
michael@0 | 846 | if (last_last_text === '}') { |
michael@0 | 847 | // }, { in array context |
michael@0 | 848 | print_single_space(); |
michael@0 | 849 | } else { |
michael@0 | 850 | print_newline(); // [a, b, c, { |
michael@0 | 851 | } |
michael@0 | 852 | } |
michael@0 | 853 | } |
michael@0 | 854 | indent(); |
michael@0 | 855 | print_token(); |
michael@0 | 856 | } |
michael@0 | 857 | |
michael@0 | 858 | break; |
michael@0 | 859 | |
michael@0 | 860 | case 'TK_END_BLOCK': |
michael@0 | 861 | restore_mode(); |
michael@0 | 862 | if (opt_brace_style === "expand" || opt_brace_style === "expand-strict") { |
michael@0 | 863 | if (last_text !== '{') { |
michael@0 | 864 | print_newline(); |
michael@0 | 865 | } |
michael@0 | 866 | print_token(); |
michael@0 | 867 | } else { |
michael@0 | 868 | if (last_type === 'TK_START_BLOCK') { |
michael@0 | 869 | // nothing |
michael@0 | 870 | if (just_added_newline) { |
michael@0 | 871 | remove_indent(); |
michael@0 | 872 | } else { |
michael@0 | 873 | // {} |
michael@0 | 874 | trim_output(); |
michael@0 | 875 | } |
michael@0 | 876 | } else { |
michael@0 | 877 | if (is_array(flags.mode) && opt_keep_array_indentation) { |
michael@0 | 878 | // we REALLY need a newline here, but newliner would skip that |
michael@0 | 879 | opt_keep_array_indentation = false; |
michael@0 | 880 | print_newline(); |
michael@0 | 881 | opt_keep_array_indentation = true; |
michael@0 | 882 | |
michael@0 | 883 | } else { |
michael@0 | 884 | print_newline(); |
michael@0 | 885 | } |
michael@0 | 886 | } |
michael@0 | 887 | print_token(); |
michael@0 | 888 | } |
michael@0 | 889 | break; |
michael@0 | 890 | |
michael@0 | 891 | case 'TK_WORD': |
michael@0 | 892 | |
michael@0 | 893 | // no, it's not you. even I have problems understanding how this works |
michael@0 | 894 | // and what does what. |
michael@0 | 895 | if (do_block_just_closed) { |
michael@0 | 896 | // do {} ## while () |
michael@0 | 897 | print_single_space(); |
michael@0 | 898 | print_token(); |
michael@0 | 899 | print_single_space(); |
michael@0 | 900 | do_block_just_closed = false; |
michael@0 | 901 | break; |
michael@0 | 902 | } |
michael@0 | 903 | |
michael@0 | 904 | prefix = 'NONE'; |
michael@0 | 905 | |
michael@0 | 906 | if (token_text === 'function') { |
michael@0 | 907 | if (flags.var_line && last_type !== 'TK_EQUALS' ) { |
michael@0 | 908 | flags.var_line_reindented = true; |
michael@0 | 909 | } |
michael@0 | 910 | if ((just_added_newline || last_text === ';') && last_text !== '{' |
michael@0 | 911 | && last_type !== 'TK_BLOCK_COMMENT' && last_type !== 'TK_COMMENT') { |
michael@0 | 912 | // make sure there is a nice clean space of at least one blank line |
michael@0 | 913 | // before a new function definition |
michael@0 | 914 | n_newlines = just_added_newline ? n_newlines : 0; |
michael@0 | 915 | if (!opt_preserve_newlines) { |
michael@0 | 916 | n_newlines = 1; |
michael@0 | 917 | } |
michael@0 | 918 | |
michael@0 | 919 | for (var i = 0; i < 2 - n_newlines; i++) { |
michael@0 | 920 | print_newline(false); |
michael@0 | 921 | } |
michael@0 | 922 | } |
michael@0 | 923 | if (last_type === 'TK_WORD') { |
michael@0 | 924 | if (last_text === 'get' || last_text === 'set' || last_text === 'new' || last_text === 'return') { |
michael@0 | 925 | print_single_space(); |
michael@0 | 926 | } else { |
michael@0 | 927 | print_newline(); |
michael@0 | 928 | } |
michael@0 | 929 | } else if (last_type === 'TK_OPERATOR' || last_text === '=') { |
michael@0 | 930 | // foo = function |
michael@0 | 931 | print_single_space(); |
michael@0 | 932 | } else if (is_expression(flags.mode)) { |
michael@0 | 933 | //ää print nothing |
michael@0 | 934 | } else { |
michael@0 | 935 | print_newline(); |
michael@0 | 936 | } |
michael@0 | 937 | |
michael@0 | 938 | print_token(); |
michael@0 | 939 | last_word = token_text; |
michael@0 | 940 | break; |
michael@0 | 941 | } |
michael@0 | 942 | |
michael@0 | 943 | if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) { |
michael@0 | 944 | if (last_text === ':' || flags.case_body) { |
michael@0 | 945 | // switch cases following one another |
michael@0 | 946 | remove_indent(); |
michael@0 | 947 | } else { |
michael@0 | 948 | // case statement starts in the same line where switch |
michael@0 | 949 | if (!opt_indent_case) { |
michael@0 | 950 | flags.indentation_level--; |
michael@0 | 951 | } |
michael@0 | 952 | print_newline(); |
michael@0 | 953 | if (!opt_indent_case) { |
michael@0 | 954 | flags.indentation_level++; |
michael@0 | 955 | } |
michael@0 | 956 | } |
michael@0 | 957 | print_token(); |
michael@0 | 958 | flags.in_case = true; |
michael@0 | 959 | flags.in_case_statement = true; |
michael@0 | 960 | flags.case_body = false; |
michael@0 | 961 | break; |
michael@0 | 962 | } |
michael@0 | 963 | |
michael@0 | 964 | if (last_type === 'TK_END_BLOCK') { |
michael@0 | 965 | |
michael@0 | 966 | if (!in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) { |
michael@0 | 967 | prefix = 'NEWLINE'; |
michael@0 | 968 | } else { |
michael@0 | 969 | if (opt_brace_style === "expand" || opt_brace_style === "end-expand" || opt_brace_style === "expand-strict") { |
michael@0 | 970 | prefix = 'NEWLINE'; |
michael@0 | 971 | } else { |
michael@0 | 972 | prefix = 'SPACE'; |
michael@0 | 973 | print_single_space(); |
michael@0 | 974 | } |
michael@0 | 975 | } |
michael@0 | 976 | } else if (last_type === 'TK_SEMICOLON' && (flags.mode === 'BLOCK' || flags.mode === 'DO_BLOCK')) { |
michael@0 | 977 | prefix = 'NEWLINE'; |
michael@0 | 978 | } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) { |
michael@0 | 979 | prefix = 'SPACE'; |
michael@0 | 980 | } else if (last_type === 'TK_STRING') { |
michael@0 | 981 | prefix = 'NEWLINE'; |
michael@0 | 982 | } else if (last_type === 'TK_WORD') { |
michael@0 | 983 | if (last_text === 'else') { |
michael@0 | 984 | // eat newlines between ...else *** some_op... |
michael@0 | 985 | // won't preserve extra newlines in this place (if any), but don't care that much |
michael@0 | 986 | trim_output(true); |
michael@0 | 987 | } |
michael@0 | 988 | prefix = 'SPACE'; |
michael@0 | 989 | } else if (last_type === 'TK_START_BLOCK') { |
michael@0 | 990 | prefix = 'NEWLINE'; |
michael@0 | 991 | } else if (last_type === 'TK_END_EXPR') { |
michael@0 | 992 | print_single_space(); |
michael@0 | 993 | prefix = 'NEWLINE'; |
michael@0 | 994 | } |
michael@0 | 995 | |
michael@0 | 996 | if (in_array(token_text, line_starters) && last_text !== ')') { |
michael@0 | 997 | if (last_text === 'else') { |
michael@0 | 998 | prefix = 'SPACE'; |
michael@0 | 999 | } else { |
michael@0 | 1000 | prefix = 'NEWLINE'; |
michael@0 | 1001 | } |
michael@0 | 1002 | |
michael@0 | 1003 | } |
michael@0 | 1004 | |
michael@0 | 1005 | if (flags.if_line && last_type === 'TK_END_EXPR') { |
michael@0 | 1006 | flags.if_line = false; |
michael@0 | 1007 | } |
michael@0 | 1008 | if (in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) { |
michael@0 | 1009 | if (last_type !== 'TK_END_BLOCK' || opt_brace_style === "expand" || opt_brace_style === "end-expand" || opt_brace_style === "expand-strict") { |
michael@0 | 1010 | print_newline(); |
michael@0 | 1011 | } else { |
michael@0 | 1012 | trim_output(true); |
michael@0 | 1013 | print_single_space(); |
michael@0 | 1014 | } |
michael@0 | 1015 | } else if (prefix === 'NEWLINE') { |
michael@0 | 1016 | if (is_special_word(last_text)) { |
michael@0 | 1017 | // no newline between 'return nnn' |
michael@0 | 1018 | print_single_space(); |
michael@0 | 1019 | } else if (last_type !== 'TK_END_EXPR') { |
michael@0 | 1020 | if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && last_text !== ':') { |
michael@0 | 1021 | // no need to force newline on 'var': for (var x = 0...) |
michael@0 | 1022 | if (token_text === 'if' && last_word === 'else' && last_text !== '{') { |
michael@0 | 1023 | // no newline for } else if { |
michael@0 | 1024 | print_single_space(); |
michael@0 | 1025 | } else { |
michael@0 | 1026 | flags.var_line = false; |
michael@0 | 1027 | flags.var_line_reindented = false; |
michael@0 | 1028 | print_newline(); |
michael@0 | 1029 | } |
michael@0 | 1030 | } |
michael@0 | 1031 | } else if (in_array(token_text, line_starters) && last_text !== ')') { |
michael@0 | 1032 | flags.var_line = false; |
michael@0 | 1033 | flags.var_line_reindented = false; |
michael@0 | 1034 | print_newline(); |
michael@0 | 1035 | } |
michael@0 | 1036 | } else if (is_array(flags.mode) && last_text === ',' && last_last_text === '}') { |
michael@0 | 1037 | print_newline(); // }, in lists get a newline treatment |
michael@0 | 1038 | } else if (prefix === 'SPACE') { |
michael@0 | 1039 | print_single_space(); |
michael@0 | 1040 | } |
michael@0 | 1041 | print_token(); |
michael@0 | 1042 | last_word = token_text; |
michael@0 | 1043 | |
michael@0 | 1044 | if (token_text === 'var') { |
michael@0 | 1045 | flags.var_line = true; |
michael@0 | 1046 | flags.var_line_reindented = false; |
michael@0 | 1047 | flags.var_line_tainted = false; |
michael@0 | 1048 | } |
michael@0 | 1049 | |
michael@0 | 1050 | if (token_text === 'if') { |
michael@0 | 1051 | flags.if_line = true; |
michael@0 | 1052 | } |
michael@0 | 1053 | if (token_text === 'else') { |
michael@0 | 1054 | flags.if_line = false; |
michael@0 | 1055 | } |
michael@0 | 1056 | |
michael@0 | 1057 | break; |
michael@0 | 1058 | |
michael@0 | 1059 | case 'TK_SEMICOLON': |
michael@0 | 1060 | |
michael@0 | 1061 | print_token(); |
michael@0 | 1062 | flags.var_line = false; |
michael@0 | 1063 | flags.var_line_reindented = false; |
michael@0 | 1064 | if (flags.mode === 'OBJECT') { |
michael@0 | 1065 | // OBJECT mode is weird and doesn't get reset too well. |
michael@0 | 1066 | flags.mode = 'BLOCK'; |
michael@0 | 1067 | } |
michael@0 | 1068 | break; |
michael@0 | 1069 | |
michael@0 | 1070 | case 'TK_STRING': |
michael@0 | 1071 | |
michael@0 | 1072 | if (last_type === 'TK_END_EXPR' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) { |
michael@0 | 1073 | print_single_space(); |
michael@0 | 1074 | } else if (last_type === 'TK_COMMENT' || last_type === 'TK_STRING' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_SEMICOLON') { |
michael@0 | 1075 | print_newline(); |
michael@0 | 1076 | } else if (last_type === 'TK_WORD') { |
michael@0 | 1077 | print_single_space(); |
michael@0 | 1078 | } |
michael@0 | 1079 | print_token(); |
michael@0 | 1080 | break; |
michael@0 | 1081 | |
michael@0 | 1082 | case 'TK_EQUALS': |
michael@0 | 1083 | if (flags.var_line) { |
michael@0 | 1084 | // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done |
michael@0 | 1085 | flags.var_line_tainted = true; |
michael@0 | 1086 | } |
michael@0 | 1087 | print_single_space(); |
michael@0 | 1088 | print_token(); |
michael@0 | 1089 | print_single_space(); |
michael@0 | 1090 | break; |
michael@0 | 1091 | |
michael@0 | 1092 | case 'TK_COMMA': |
michael@0 | 1093 | if (flags.var_line) { |
michael@0 | 1094 | if (is_expression(flags.mode) || last_type === 'TK_END_BLOCK' ) { |
michael@0 | 1095 | // do not break on comma, for(var a = 1, b = 2) |
michael@0 | 1096 | flags.var_line_tainted = false; |
michael@0 | 1097 | } |
michael@0 | 1098 | if (flags.var_line_tainted) { |
michael@0 | 1099 | print_token(); |
michael@0 | 1100 | flags.var_line_reindented = true; |
michael@0 | 1101 | flags.var_line_tainted = false; |
michael@0 | 1102 | print_newline(); |
michael@0 | 1103 | break; |
michael@0 | 1104 | } else { |
michael@0 | 1105 | flags.var_line_tainted = false; |
michael@0 | 1106 | } |
michael@0 | 1107 | |
michael@0 | 1108 | print_token(); |
michael@0 | 1109 | print_single_space(); |
michael@0 | 1110 | break; |
michael@0 | 1111 | } |
michael@0 | 1112 | |
michael@0 | 1113 | if (last_type === 'TK_COMMENT') { |
michael@0 | 1114 | print_newline(); |
michael@0 | 1115 | } |
michael@0 | 1116 | |
michael@0 | 1117 | if (last_type === 'TK_END_BLOCK' && flags.mode !== "(EXPRESSION)") { |
michael@0 | 1118 | print_token(); |
michael@0 | 1119 | if (flags.mode === 'OBJECT' && last_text === '}') { |
michael@0 | 1120 | print_newline(); |
michael@0 | 1121 | } else { |
michael@0 | 1122 | print_single_space(); |
michael@0 | 1123 | } |
michael@0 | 1124 | } else { |
michael@0 | 1125 | if (flags.mode === 'OBJECT') { |
michael@0 | 1126 | print_token(); |
michael@0 | 1127 | print_newline(); |
michael@0 | 1128 | } else { |
michael@0 | 1129 | // EXPR or DO_BLOCK |
michael@0 | 1130 | print_token(); |
michael@0 | 1131 | print_single_space(); |
michael@0 | 1132 | } |
michael@0 | 1133 | } |
michael@0 | 1134 | break; |
michael@0 | 1135 | |
michael@0 | 1136 | |
michael@0 | 1137 | case 'TK_OPERATOR': |
michael@0 | 1138 | |
michael@0 | 1139 | var space_before = true; |
michael@0 | 1140 | var space_after = true; |
michael@0 | 1141 | |
michael@0 | 1142 | if (is_special_word(last_text)) { |
michael@0 | 1143 | // "return" had a special handling in TK_WORD. Now we need to return the favor |
michael@0 | 1144 | print_single_space(); |
michael@0 | 1145 | print_token(); |
michael@0 | 1146 | break; |
michael@0 | 1147 | } |
michael@0 | 1148 | |
michael@0 | 1149 | // hack for actionscript's import .*; |
michael@0 | 1150 | if (token_text === '*' && last_type === 'TK_UNKNOWN' && !last_last_text.match(/^\d+$/)) { |
michael@0 | 1151 | print_token(); |
michael@0 | 1152 | break; |
michael@0 | 1153 | } |
michael@0 | 1154 | |
michael@0 | 1155 | if (token_text === ':' && flags.in_case) { |
michael@0 | 1156 | if (opt_indent_case) { |
michael@0 | 1157 | flags.case_body = true; |
michael@0 | 1158 | } |
michael@0 | 1159 | print_token(); // colon really asks for separate treatment |
michael@0 | 1160 | print_newline(); |
michael@0 | 1161 | flags.in_case = false; |
michael@0 | 1162 | break; |
michael@0 | 1163 | } |
michael@0 | 1164 | |
michael@0 | 1165 | if (token_text === '::') { |
michael@0 | 1166 | // no spaces around exotic namespacing syntax operator |
michael@0 | 1167 | print_token(); |
michael@0 | 1168 | break; |
michael@0 | 1169 | } |
michael@0 | 1170 | |
michael@0 | 1171 | if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array(last_text, line_starters)))) { |
michael@0 | 1172 | // unary operators (and binary +/- pretending to be unary) special cases |
michael@0 | 1173 | |
michael@0 | 1174 | space_before = false; |
michael@0 | 1175 | space_after = false; |
michael@0 | 1176 | |
michael@0 | 1177 | if (last_text === ';' && is_expression(flags.mode)) { |
michael@0 | 1178 | // for (;; ++i) |
michael@0 | 1179 | // ^^^ |
michael@0 | 1180 | space_before = true; |
michael@0 | 1181 | } |
michael@0 | 1182 | if (last_type === 'TK_WORD' && in_array(last_text, line_starters)) { |
michael@0 | 1183 | space_before = true; |
michael@0 | 1184 | } |
michael@0 | 1185 | |
michael@0 | 1186 | if (flags.mode === 'BLOCK' && (last_text === '{' || last_text === ';')) { |
michael@0 | 1187 | // { foo; --i } |
michael@0 | 1188 | // foo(); --bar; |
michael@0 | 1189 | print_newline(); |
michael@0 | 1190 | } |
michael@0 | 1191 | } else if (token_text === '.') { |
michael@0 | 1192 | // decimal digits or object.property |
michael@0 | 1193 | space_before = false; |
michael@0 | 1194 | |
michael@0 | 1195 | } else if (token_text === ':') { |
michael@0 | 1196 | if (flags.ternary_depth === 0) { |
michael@0 | 1197 | if (flags.mode === 'BLOCK') { |
michael@0 | 1198 | flags.mode = 'OBJECT'; |
michael@0 | 1199 | } |
michael@0 | 1200 | space_before = false; |
michael@0 | 1201 | } else { |
michael@0 | 1202 | flags.ternary_depth -= 1; |
michael@0 | 1203 | } |
michael@0 | 1204 | } else if (token_text === '?') { |
michael@0 | 1205 | flags.ternary_depth += 1; |
michael@0 | 1206 | } |
michael@0 | 1207 | if (space_before) { |
michael@0 | 1208 | print_single_space(); |
michael@0 | 1209 | } |
michael@0 | 1210 | |
michael@0 | 1211 | print_token(); |
michael@0 | 1212 | |
michael@0 | 1213 | if (space_after) { |
michael@0 | 1214 | print_single_space(); |
michael@0 | 1215 | } |
michael@0 | 1216 | |
michael@0 | 1217 | break; |
michael@0 | 1218 | |
michael@0 | 1219 | case 'TK_BLOCK_COMMENT': |
michael@0 | 1220 | |
michael@0 | 1221 | var lines = split_newlines(token_text); |
michael@0 | 1222 | var j; // iterator for this case |
michael@0 | 1223 | |
michael@0 | 1224 | if (all_lines_start_with(lines.slice(1), '*')) { |
michael@0 | 1225 | // javadoc: reformat and reindent |
michael@0 | 1226 | print_newline(); |
michael@0 | 1227 | output.push(lines[0]); |
michael@0 | 1228 | for (j = 1; j < lines.length; j++) { |
michael@0 | 1229 | print_newline(); |
michael@0 | 1230 | output.push(' '); |
michael@0 | 1231 | output.push(trim(lines[j])); |
michael@0 | 1232 | } |
michael@0 | 1233 | |
michael@0 | 1234 | } else { |
michael@0 | 1235 | |
michael@0 | 1236 | // simple block comment: leave intact |
michael@0 | 1237 | if (lines.length > 1) { |
michael@0 | 1238 | // multiline comment block starts with a new line |
michael@0 | 1239 | print_newline(); |
michael@0 | 1240 | } else { |
michael@0 | 1241 | // single-line /* comment */ stays where it is |
michael@0 | 1242 | if (last_type === 'TK_END_BLOCK') { |
michael@0 | 1243 | print_newline(); |
michael@0 | 1244 | } else { |
michael@0 | 1245 | print_single_space(); |
michael@0 | 1246 | } |
michael@0 | 1247 | |
michael@0 | 1248 | } |
michael@0 | 1249 | |
michael@0 | 1250 | for (j = 0; j < lines.length; j++) { |
michael@0 | 1251 | output.push(lines[j]); |
michael@0 | 1252 | output.push("\n"); |
michael@0 | 1253 | } |
michael@0 | 1254 | |
michael@0 | 1255 | } |
michael@0 | 1256 | if (look_up('\n') !== '\n') { |
michael@0 | 1257 | print_newline(); |
michael@0 | 1258 | } |
michael@0 | 1259 | break; |
michael@0 | 1260 | |
michael@0 | 1261 | case 'TK_INLINE_COMMENT': |
michael@0 | 1262 | print_single_space(); |
michael@0 | 1263 | print_token(); |
michael@0 | 1264 | if (is_expression(flags.mode)) { |
michael@0 | 1265 | print_single_space(); |
michael@0 | 1266 | } else { |
michael@0 | 1267 | force_newline(); |
michael@0 | 1268 | } |
michael@0 | 1269 | break; |
michael@0 | 1270 | |
michael@0 | 1271 | case 'TK_COMMENT': |
michael@0 | 1272 | |
michael@0 | 1273 | if (last_text === ',' && !wanted_newline) { |
michael@0 | 1274 | trim_output(true); |
michael@0 | 1275 | } |
michael@0 | 1276 | if (last_type !== 'TK_COMMENT') { |
michael@0 | 1277 | if (wanted_newline) { |
michael@0 | 1278 | print_newline(); |
michael@0 | 1279 | } else { |
michael@0 | 1280 | print_single_space(); |
michael@0 | 1281 | } |
michael@0 | 1282 | } |
michael@0 | 1283 | print_token(); |
michael@0 | 1284 | print_newline(); |
michael@0 | 1285 | break; |
michael@0 | 1286 | |
michael@0 | 1287 | case 'TK_UNKNOWN': |
michael@0 | 1288 | if (is_special_word(last_text)) { |
michael@0 | 1289 | print_single_space(); |
michael@0 | 1290 | } |
michael@0 | 1291 | print_token(); |
michael@0 | 1292 | break; |
michael@0 | 1293 | } |
michael@0 | 1294 | |
michael@0 | 1295 | last_last_text = last_text; |
michael@0 | 1296 | last_type = token_type; |
michael@0 | 1297 | last_text = token_text; |
michael@0 | 1298 | } |
michael@0 | 1299 | |
michael@0 | 1300 | var sweet_code = preindent_string + output.join('').replace(/[\r\n ]+$/, ''); |
michael@0 | 1301 | return sweet_code; |
michael@0 | 1302 | |
michael@0 | 1303 | } |