[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/jquery_ui/jquery.ui.old/demos/functional/js/ -> beautify.js (source)

   1  /*

   2  

   3   JS Beautifier

   4  ---------------

   5    $Date: 2008-04-21 16:13:36 +0300 (Mon, 21 Apr 2008) $

   6    $Revision: 53 $

   7  

   8  

   9    Written by Einars "elfz" Lielmanis, <elfz@laacz.lv> 

  10        http://elfz.laacz.lv/beautify/

  11  

  12    Originally converted to javascript by Vital, <vital76@gmail.com> 

  13        http://my.opera.com/Vital/blog/2007/11/21/javascript-beautify-on-javascript-translated

  14  

  15  

  16    You are free to use this in any way you want, in case you find this useful or working for you.

  17  

  18    Usage:

  19      js_beautify(js_source_text);

  20  

  21  */
  22  
  23  
  24  function js_beautify(js_source_text, indent_size, indent_character)
  25  {
  26  
  27      var input, output, token_text, last_type, last_text, last_word, current_mode, modes, indent_level, indent_string;
  28      var whitespace, wordchar, punct, parser_pos, line_starters, in_case;
  29      var prefix, token_type;
  30  
  31      function print_newline(ignore_repeated)
  32      {
  33          ignore_repeated = typeof ignore_repeated === 'undefined' ? true: ignore_repeated;
  34  
  35          // remove trailing whitespace and indent

  36          while (output.length && (output[output.length - 1] === ' ' || output[output.length - 1] === indent_string)) {
  37              output.pop();
  38          }
  39  
  40          if (!output.length) {
  41              return; // no newline on start of file

  42          }
  43  
  44          if (output[output.length - 1] !== "\n" || !ignore_repeated) {
  45              output.push("\n");
  46          }
  47          for (var i = 0; i < indent_level; i++) {
  48              output.push(indent_string);
  49          }
  50      }
  51  
  52  
  53  
  54      function print_space()
  55      {
  56          var last_output = output.length ? output[output.length - 1] : ' ';
  57          if (last_output !== ' ' && last_output !== '\n' && last_output !== indent_string) { // prevent occassional duplicate space
  58              output.push(' ');
  59          }
  60      }
  61  
  62  
  63      function print_token()
  64      {
  65          output.push(token_text);
  66      }
  67  
  68      function indent()
  69      {
  70          indent_level++;
  71      }
  72  
  73  
  74      function unindent()
  75      {
  76          if (indent_level) {
  77              indent_level--;
  78          }
  79      }
  80  
  81  
  82      function remove_indent()
  83      {
  84          if (output.length && output[output.length - 1] === indent_string) {
  85              output.pop();
  86          }
  87      }
  88  
  89  
  90      function set_mode(mode)
  91      {
  92          modes.push(current_mode);
  93          current_mode = mode;
  94      }
  95  
  96  
  97      function restore_mode()
  98      {
  99          current_mode = modes.pop();
 100      }
 101  
 102  
 103      function in_array(what, arr)
 104      {
 105          for (var i = 0; i < arr.length; i++)
 106          {
 107              if (arr[i] === what) {
 108                  return true;
 109              }
 110          }
 111          return false;
 112      }
 113  
 114  
 115  
 116      function get_next_token()
 117      {
 118          var n_newlines = 0;
 119          var c = '';
 120  
 121          do {
 122              if (parser_pos >= input.length) {
 123                  return ['', 'TK_EOF'];
 124              }
 125              c = input.charAt(parser_pos);
 126  
 127              parser_pos += 1;
 128              if (c === "\n") {
 129                  n_newlines += 1;
 130              }
 131          }
 132          while (in_array(c, whitespace));
 133  
 134          if (n_newlines > 1) {
 135              for (var i = 0; i < 2; i++) {
 136                  print_newline(i === 0);
 137              }
 138          }
 139          var wanted_newline = (n_newlines === 1);
 140  
 141  
 142          if (in_array(c, wordchar)) {
 143              if (parser_pos < input.length) {
 144                  while (in_array(input.charAt(parser_pos), wordchar)) {
 145                      c += input.charAt(parser_pos);
 146                      parser_pos += 1;
 147                      if (parser_pos === input.length) {
 148                          break;
 149                      }
 150                  }
 151              }
 152  
 153              // small and surprisingly unugly hack for 1E-10 representation

 154              if (parser_pos !== input.length && c.match(/^[0-9]+[Ee]$/) && input.charAt(parser_pos) === '-') {
 155                  parser_pos += 1;
 156  
 157                  var t = get_next_token(parser_pos);
 158                  c += '-' + t[0];
 159                  return [c, 'TK_WORD'];
 160              }
 161  
 162              if (c === 'in') { // hack for 'in' operator
 163                  return [c, 'TK_OPERATOR'];
 164              }
 165              return [c, 'TK_WORD'];
 166          }
 167          
 168          if (c === '(' || c === '[') {
 169              return [c, 'TK_START_EXPR'];
 170          }
 171  
 172          if (c === ')' || c === ']') {
 173              return [c, 'TK_END_EXPR'];
 174          }
 175  
 176          if (c === '{') {
 177              return [c, 'TK_START_BLOCK'];
 178          }
 179  
 180          if (c === '}') {
 181              return [c, 'TK_END_BLOCK'];
 182          }
 183  
 184          if (c === ';') {
 185              return [c, 'TK_END_COMMAND'];
 186          }
 187  
 188          if (c === '/') {
 189              var comment = '';
 190              // peek for comment /* ... */

 191              if (input.charAt(parser_pos) === '*') {
 192                  parser_pos += 1;
 193                  if (parser_pos < input.length) {
 194                      while (! (input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/') && parser_pos < input.length) {
 195                          comment += input.charAt(parser_pos);
 196                          parser_pos += 1;
 197                          if (parser_pos >= input.length) {
 198                              break;
 199                          }
 200                      }
 201                  }
 202                  parser_pos += 2;
 203                  return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
 204              }
 205              // peek for comment // ...

 206              if (input.charAt(parser_pos) === '/') {
 207                  comment = c;
 208                  while (input.charAt(parser_pos) !== "\x0d" && input.charAt(parser_pos) !== "\x0a") {
 209                      comment += input.charAt(parser_pos);
 210                      parser_pos += 1;
 211                      if (parser_pos >= input.length) {
 212                          break;
 213                      }
 214                  }
 215                  parser_pos += 1;
 216                  if (wanted_newline) {
 217                      print_newline();
 218                  }
 219                  return [comment, 'TK_COMMENT'];
 220              }
 221  
 222          }
 223  
 224          if (c === "'" || // string
 225          c === '"' || // string
 226          (c === '/' &&
 227          ((last_type === 'TK_WORD' && last_text === 'return') || (last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || last_type === 'TK_OPERATOR' || last_type === 'TK_EOF' || last_type === 'TK_END_COMMAND')))) { // regexp
 228              var sep = c;
 229              var esc = false;
 230              c = '';
 231  
 232              if (parser_pos < input.length) {
 233  
 234                  while (esc || input.charAt(parser_pos) !== sep) {
 235                      c += input.charAt(parser_pos);
 236                      if (!esc) {
 237                          esc = input.charAt(parser_pos) === '\\';
 238                      } else {
 239                          esc = false;
 240                      }
 241                      parser_pos += 1;
 242                      if (parser_pos >= input.length) {
 243                          break;
 244                      }
 245                  }
 246  
 247              }
 248  
 249              parser_pos += 1;
 250              if (last_type === 'TK_END_COMMAND') {
 251                  print_newline();
 252              }
 253              return [sep + c + sep, 'TK_STRING'];
 254          }
 255  
 256          if (in_array(c, punct)) {
 257              while (parser_pos < input.length && in_array(c + input.charAt(parser_pos), punct)) {
 258                  c += input.charAt(parser_pos);
 259                  parser_pos += 1;
 260                  if (parser_pos >= input.length) {
 261                      break;
 262                  }
 263              }
 264              return [c, 'TK_OPERATOR'];
 265          }
 266  
 267          return [c, 'TK_UNKNOWN'];
 268      }
 269  
 270  
 271      //----------------------------------

 272  
 273      indent_character = indent_character || ' ';
 274      indent_size = indent_size || 4;
 275  
 276      indent_string = '';
 277      while (indent_size--) {
 278          indent_string += indent_character;
 279      }
 280  
 281      input = js_source_text;
 282  
 283      last_word = ''; // last 'TK_WORD' passed

 284      last_type = 'TK_START_EXPR'; // last token type

 285      last_text = ''; // last token text

 286      output = [];
 287  
 288      whitespace = "\n\r\t ".split('');
 289      wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
 290      punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |='.split(' ');
 291  
 292      // words which should always start on new line.

 293      line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
 294  
 295      // states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'.

 296      // some formatting depends on that.

 297      current_mode = 'BLOCK';
 298      modes = [current_mode];
 299  
 300      indent_level = 0;
 301      parser_pos = 0; // parser position

 302      in_case = false; // flag for parser that case/default has been processed, and next colon needs special attention

 303      while (true) {
 304          var t = get_next_token(parser_pos);
 305          token_text = t[0];
 306          token_type = t[1];
 307          if (token_type === 'TK_EOF') {
 308              break;
 309          }
 310  
 311          switch (token_type) {
 312  
 313          case 'TK_START_EXPR':
 314  
 315              set_mode('EXPRESSION');
 316              if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR') {
 317                  // do nothing on (( and )( and ][ and ]( ..

 318              } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
 319                  print_space();
 320              } else if (in_array(last_word, line_starters) && last_word !== 'function') {
 321                  print_space();
 322              }
 323              print_token();
 324              break;
 325  
 326          case 'TK_END_EXPR':
 327  
 328              print_token();
 329              restore_mode();
 330              break;
 331  
 332          case 'TK_START_BLOCK':
 333  
 334              set_mode('BLOCK');
 335              if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
 336                  if (last_type === 'TK_START_BLOCK') {
 337                      print_newline();
 338                  } else {
 339                      print_space();
 340                  }
 341              }
 342              print_token();
 343              indent();
 344              break;
 345  
 346          case 'TK_END_BLOCK':
 347              if (last_type === 'TK_START_BLOCK') {
 348                  // nothing

 349                  unindent();
 350              } else {
 351                  unindent();
 352                  print_newline();
 353              }
 354              print_token();
 355              restore_mode();
 356              break;
 357  
 358          case 'TK_WORD':
 359  
 360              if (token_text === 'case' || token_text === 'default') {
 361                  if (last_text === ':') {
 362                      // switch cases following one another

 363                      remove_indent();
 364                  } else {
 365                      // case statement starts in the same line where switch

 366                      unindent();
 367                      print_newline();
 368                      indent();
 369                  }
 370                  print_token();
 371                  in_case = true;
 372                  break;
 373              }
 374  
 375              prefix = 'NONE';
 376              if (last_type === 'TK_END_BLOCK') {
 377                  if (!in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
 378                      prefix = 'NEWLINE';
 379                  } else {
 380                      prefix = 'SPACE';
 381                      print_space();
 382                  }
 383              } else if (last_type === 'TK_END_COMMAND' && current_mode === 'BLOCK') {
 384                  prefix = 'NEWLINE';
 385              } else if (last_type === 'TK_END_COMMAND' && current_mode === 'EXPRESSION') {
 386                  prefix = 'SPACE';
 387              } else if (last_type === 'TK_WORD') {
 388                  prefix = 'SPACE';
 389              } else if (last_type === 'TK_START_BLOCK') {
 390                  prefix = 'NEWLINE';
 391              } else if (last_type === 'TK_END_EXPR') {
 392                  print_space();
 393                  prefix = 'NEWLINE';
 394              }
 395  
 396              if (in_array(token_text, line_starters) || prefix === 'NEWLINE') {
 397  
 398                  if (last_text === 'else') {
 399                      // no need to force newline on else break

 400                      print_space();
 401                  } else if ((last_type === 'TK_START_EXPR' || last_text === '=') && token_text === 'function') {
 402                      // no need to force newline on 'function': (function

 403                      // DONOTHING

 404                  } else if (last_type === 'TK_WORD' && (last_text === 'return' || last_text === 'throw')) {
 405                      // no newline between 'return nnn'

 406                      print_space();
 407                  } else if (last_type !== 'TK_END_EXPR') {
 408                      if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && last_text !== ':') {
 409                          // no need to force newline on 'var': for (var x = 0...)

 410                          if (token_text === 'if' && last_type === 'TK_WORD' && last_word === 'else') {
 411                              // no newline for } else if {

 412                              print_space();
 413                          } else {
 414                              print_newline();
 415                          }
 416                      }
 417                  }
 418              } else if (prefix === 'SPACE') {
 419                  print_space();
 420              }
 421              print_token();
 422              last_word = token_text;
 423              break;
 424  
 425          case 'TK_END_COMMAND':
 426  
 427              print_token();
 428              break;
 429  
 430          case 'TK_STRING':
 431  
 432              if (last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK') {
 433                  print_newline();
 434              } else if (last_type === 'TK_WORD') {
 435                  print_space();
 436              }
 437              print_token();
 438              break;
 439  
 440          case 'TK_OPERATOR':
 441  
 442              var start_delim = true;
 443              var end_delim = true;
 444  
 445              if (token_text === ':' && in_case) {
 446                  print_token(); // colon really asks for separate treatment

 447                  print_newline();
 448                  break;
 449              }
 450  
 451              in_case = false;
 452  
 453              if (token_text === ',') {
 454                  if (last_type === 'TK_END_BLOCK') {
 455                      print_token();
 456                      print_newline();
 457                  } else {
 458                      if (current_mode === 'BLOCK') {
 459                          print_token();
 460                          print_newline();
 461                      } else {
 462                          print_token();
 463                          print_space();
 464                      }
 465                  }
 466                  break;
 467              } else if (token_text === '--' || token_text === '++') { // unary operators special case
 468                  if (last_text === ';') {
 469                      // space for (;; ++i)

 470                      start_delim = true;
 471                      end_delim = false;
 472                  } else {
 473                      start_delim = false;
 474                      end_delim = false;
 475                  }
 476              } else if (token_text === '!' && last_type === 'TK_START_EXPR') {
 477                  // special case handling: if (!a)

 478                  start_delim = false;
 479                  end_delim = false;
 480              } else if (last_type === 'TK_OPERATOR') {
 481                  start_delim = false;
 482                  end_delim = false;
 483              } else if (last_type === 'TK_END_EXPR') {
 484                  start_delim = true;
 485                  end_delim = true;
 486              } else if (token_text === '.') {
 487                  // decimal digits or object.property

 488                  start_delim = false;
 489                  end_delim = false;
 490  
 491              } else if (token_text === ':') {
 492                  // zz: xx

 493                  // can't differentiate ternary op, so for now it's a ? b: c; without space before colon

 494                  start_delim = false;
 495              }
 496              if (start_delim) {
 497                  print_space();
 498              }
 499  
 500              print_token();
 501  
 502              if (end_delim) {
 503                  print_space();
 504              }
 505              break;
 506  
 507          case 'TK_BLOCK_COMMENT':
 508  
 509              print_newline();
 510              print_token();
 511              print_newline();
 512              break;
 513  
 514          case 'TK_COMMENT':
 515  
 516              // print_newline();

 517              print_space();
 518              print_token();
 519              print_newline();
 520              break;
 521  
 522          case 'TK_UNKNOWN':
 523              print_token();
 524              break;
 525          }
 526  
 527          last_type = token_type;
 528          last_text = token_text;
 529      }
 530  
 531      return output.join('');
 532  
 533  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7