beautify-html.js (110630B)
1 /* AUTO-GENERATED. DO NOT MODIFY. */ 2 /* 3 4 The MIT License (MIT) 5 6 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 8 Permission is hereby granted, free of charge, to any person 9 obtaining a copy of this software and associated documentation files 10 (the "Software"), to deal in the Software without restriction, 11 including without limitation the rights to use, copy, modify, merge, 12 publish, distribute, sublicense, and/or sell copies of the Software, 13 and to permit persons to whom the Software is furnished to do so, 14 subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be 17 included in all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 SOFTWARE. 27 28 29 Style HTML 30 --------------- 31 32 Written by Nochum Sossonko, (nsossonko@hotmail.com) 33 34 Based on code initially developed by: Einar Lielmanis, <einar@beautifier.io> 35 https://beautifier.io/ 36 37 Usage: 38 style_html(html_source); 39 40 style_html(html_source, options); 41 42 The options are: 43 indent_inner_html (default false) — indent <head> and <body> sections, 44 indent_size (default 4) — indentation size, 45 indent_char (default space) — character to indent with, 46 wrap_line_length (default 250) - maximum amount of characters per line (0 = disable) 47 brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "none" 48 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. 49 inline (defaults to inline tags) - list of tags to be considered inline tags 50 unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted 51 content_unformatted (defaults to ["pre", "textarea"] tags) - list of tags, whose content shouldn't be reformatted 52 indent_scripts (default normal) - "keep"|"separate"|"normal" 53 preserve_newlines (default true) - whether existing line breaks before elements should be preserved 54 Only works before elements, not inside tags or for text. 55 max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk 56 indent_handlebars (default false) - format and indent {{#foo}} and {{/foo}} 57 end_with_newline (false) - end with a newline 58 extra_liners (default [head,body,/html]) -List of tags that should have an extra newline before them. 59 60 e.g. 61 62 style_html(html_source, { 63 'indent_inner_html': false, 64 'indent_size': 2, 65 'indent_char': ' ', 66 'wrap_line_length': 78, 67 'brace_style': 'expand', 68 'preserve_newlines': true, 69 'max_preserve_newlines': 5, 70 'indent_handlebars': false, 71 'extra_liners': ['/html'] 72 }); 73 */ 74 75 (function() { 76 77 /* GENERATED_BUILD_OUTPUT */ 78 var legacy_beautify_html = 79 /******/ (function(modules) { // webpackBootstrap 80 /******/ // The module cache 81 /******/ var installedModules = {}; 82 /******/ 83 /******/ // The require function 84 /******/ function __webpack_require__(moduleId) { 85 /******/ 86 /******/ // Check if module is in cache 87 /******/ if(installedModules[moduleId]) { 88 /******/ return installedModules[moduleId].exports; 89 /******/ } 90 /******/ // Create a new module (and put it into the cache) 91 /******/ var module = installedModules[moduleId] = { 92 /******/ i: moduleId, 93 /******/ l: false, 94 /******/ exports: {} 95 /******/ }; 96 /******/ 97 /******/ // Execute the module function 98 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 99 /******/ 100 /******/ // Flag the module as loaded 101 /******/ module.l = true; 102 /******/ 103 /******/ // Return the exports of the module 104 /******/ return module.exports; 105 /******/ } 106 /******/ 107 /******/ 108 /******/ // expose the modules object (__webpack_modules__) 109 /******/ __webpack_require__.m = modules; 110 /******/ 111 /******/ // expose the module cache 112 /******/ __webpack_require__.c = installedModules; 113 /******/ 114 /******/ // define getter function for harmony exports 115 /******/ __webpack_require__.d = function(exports, name, getter) { 116 /******/ if(!__webpack_require__.o(exports, name)) { 117 /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 118 /******/ } 119 /******/ }; 120 /******/ 121 /******/ // define __esModule on exports 122 /******/ __webpack_require__.r = function(exports) { 123 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 124 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 125 /******/ } 126 /******/ Object.defineProperty(exports, '__esModule', { value: true }); 127 /******/ }; 128 /******/ 129 /******/ // create a fake namespace object 130 /******/ // mode & 1: value is a module id, require it 131 /******/ // mode & 2: merge all properties of value into the ns 132 /******/ // mode & 4: return value when already ns object 133 /******/ // mode & 8|1: behave like require 134 /******/ __webpack_require__.t = function(value, mode) { 135 /******/ if(mode & 1) value = __webpack_require__(value); 136 /******/ if(mode & 8) return value; 137 /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 138 /******/ var ns = Object.create(null); 139 /******/ __webpack_require__.r(ns); 140 /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 141 /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 142 /******/ return ns; 143 /******/ }; 144 /******/ 145 /******/ // getDefaultExport function for compatibility with non-harmony modules 146 /******/ __webpack_require__.n = function(module) { 147 /******/ var getter = module && module.__esModule ? 148 /******/ function getDefault() { return module['default']; } : 149 /******/ function getModuleExports() { return module; }; 150 /******/ __webpack_require__.d(getter, 'a', getter); 151 /******/ return getter; 152 /******/ }; 153 /******/ 154 /******/ // Object.prototype.hasOwnProperty.call 155 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 156 /******/ 157 /******/ // __webpack_public_path__ 158 /******/ __webpack_require__.p = ""; 159 /******/ 160 /******/ 161 /******/ // Load entry module and return exports 162 /******/ return __webpack_require__(__webpack_require__.s = 18); 163 /******/ }) 164 /************************************************************************/ 165 /******/ ([ 166 /* 0 */, 167 /* 1 */, 168 /* 2 */ 169 /***/ (function(module, exports, __webpack_require__) { 170 171 "use strict"; 172 /*jshint node:true */ 173 /* 174 The MIT License (MIT) 175 176 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 177 178 Permission is hereby granted, free of charge, to any person 179 obtaining a copy of this software and associated documentation files 180 (the "Software"), to deal in the Software without restriction, 181 including without limitation the rights to use, copy, modify, merge, 182 publish, distribute, sublicense, and/or sell copies of the Software, 183 and to permit persons to whom the Software is furnished to do so, 184 subject to the following conditions: 185 186 The above copyright notice and this permission notice shall be 187 included in all copies or substantial portions of the Software. 188 189 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 190 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 191 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 192 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 193 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 194 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 195 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 196 SOFTWARE. 197 */ 198 199 200 201 function OutputLine(parent) { 202 this.__parent = parent; 203 this.__character_count = 0; 204 // use indent_count as a marker for this.__lines that have preserved indentation 205 this.__indent_count = -1; 206 this.__alignment_count = 0; 207 this.__wrap_point_index = 0; 208 this.__wrap_point_character_count = 0; 209 this.__wrap_point_indent_count = -1; 210 this.__wrap_point_alignment_count = 0; 211 212 this.__items = []; 213 } 214 215 OutputLine.prototype.clone_empty = function() { 216 var line = new OutputLine(this.__parent); 217 line.set_indent(this.__indent_count, this.__alignment_count); 218 return line; 219 }; 220 221 OutputLine.prototype.item = function(index) { 222 if (index < 0) { 223 return this.__items[this.__items.length + index]; 224 } else { 225 return this.__items[index]; 226 } 227 }; 228 229 OutputLine.prototype.has_match = function(pattern) { 230 for (var lastCheckedOutput = this.__items.length - 1; lastCheckedOutput >= 0; lastCheckedOutput--) { 231 if (this.__items[lastCheckedOutput].match(pattern)) { 232 return true; 233 } 234 } 235 return false; 236 }; 237 238 OutputLine.prototype.set_indent = function(indent, alignment) { 239 if (this.is_empty()) { 240 this.__indent_count = indent || 0; 241 this.__alignment_count = alignment || 0; 242 this.__character_count = this.__parent.get_indent_size(this.__indent_count, this.__alignment_count); 243 } 244 }; 245 246 OutputLine.prototype._set_wrap_point = function() { 247 if (this.__parent.wrap_line_length) { 248 this.__wrap_point_index = this.__items.length; 249 this.__wrap_point_character_count = this.__character_count; 250 this.__wrap_point_indent_count = this.__parent.next_line.__indent_count; 251 this.__wrap_point_alignment_count = this.__parent.next_line.__alignment_count; 252 } 253 }; 254 255 OutputLine.prototype._should_wrap = function() { 256 return this.__wrap_point_index && 257 this.__character_count > this.__parent.wrap_line_length && 258 this.__wrap_point_character_count > this.__parent.next_line.__character_count; 259 }; 260 261 OutputLine.prototype._allow_wrap = function() { 262 if (this._should_wrap()) { 263 this.__parent.add_new_line(); 264 var next = this.__parent.current_line; 265 next.set_indent(this.__wrap_point_indent_count, this.__wrap_point_alignment_count); 266 next.__items = this.__items.slice(this.__wrap_point_index); 267 this.__items = this.__items.slice(0, this.__wrap_point_index); 268 269 next.__character_count += this.__character_count - this.__wrap_point_character_count; 270 this.__character_count = this.__wrap_point_character_count; 271 272 if (next.__items[0] === " ") { 273 next.__items.splice(0, 1); 274 next.__character_count -= 1; 275 } 276 return true; 277 } 278 return false; 279 }; 280 281 OutputLine.prototype.is_empty = function() { 282 return this.__items.length === 0; 283 }; 284 285 OutputLine.prototype.last = function() { 286 if (!this.is_empty()) { 287 return this.__items[this.__items.length - 1]; 288 } else { 289 return null; 290 } 291 }; 292 293 OutputLine.prototype.push = function(item) { 294 this.__items.push(item); 295 var last_newline_index = item.lastIndexOf('\n'); 296 if (last_newline_index !== -1) { 297 this.__character_count = item.length - last_newline_index; 298 } else { 299 this.__character_count += item.length; 300 } 301 }; 302 303 OutputLine.prototype.pop = function() { 304 var item = null; 305 if (!this.is_empty()) { 306 item = this.__items.pop(); 307 this.__character_count -= item.length; 308 } 309 return item; 310 }; 311 312 313 OutputLine.prototype._remove_indent = function() { 314 if (this.__indent_count > 0) { 315 this.__indent_count -= 1; 316 this.__character_count -= this.__parent.indent_size; 317 } 318 }; 319 320 OutputLine.prototype._remove_wrap_indent = function() { 321 if (this.__wrap_point_indent_count > 0) { 322 this.__wrap_point_indent_count -= 1; 323 } 324 }; 325 OutputLine.prototype.trim = function() { 326 while (this.last() === ' ') { 327 this.__items.pop(); 328 this.__character_count -= 1; 329 } 330 }; 331 332 OutputLine.prototype.toString = function() { 333 var result = ''; 334 if (this.is_empty()) { 335 if (this.__parent.indent_empty_lines) { 336 result = this.__parent.get_indent_string(this.__indent_count); 337 } 338 } else { 339 result = this.__parent.get_indent_string(this.__indent_count, this.__alignment_count); 340 result += this.__items.join(''); 341 } 342 return result; 343 }; 344 345 function IndentStringCache(options, baseIndentString) { 346 this.__cache = ['']; 347 this.__indent_size = options.indent_size; 348 this.__indent_string = options.indent_char; 349 if (!options.indent_with_tabs) { 350 this.__indent_string = new Array(options.indent_size + 1).join(options.indent_char); 351 } 352 353 // Set to null to continue support for auto detection of base indent 354 baseIndentString = baseIndentString || ''; 355 if (options.indent_level > 0) { 356 baseIndentString = new Array(options.indent_level + 1).join(this.__indent_string); 357 } 358 359 this.__base_string = baseIndentString; 360 this.__base_string_length = baseIndentString.length; 361 } 362 363 IndentStringCache.prototype.get_indent_size = function(indent, column) { 364 var result = this.__base_string_length; 365 column = column || 0; 366 if (indent < 0) { 367 result = 0; 368 } 369 result += indent * this.__indent_size; 370 result += column; 371 return result; 372 }; 373 374 IndentStringCache.prototype.get_indent_string = function(indent_level, column) { 375 var result = this.__base_string; 376 column = column || 0; 377 if (indent_level < 0) { 378 indent_level = 0; 379 result = ''; 380 } 381 column += indent_level * this.__indent_size; 382 this.__ensure_cache(column); 383 result += this.__cache[column]; 384 return result; 385 }; 386 387 IndentStringCache.prototype.__ensure_cache = function(column) { 388 while (column >= this.__cache.length) { 389 this.__add_column(); 390 } 391 }; 392 393 IndentStringCache.prototype.__add_column = function() { 394 var column = this.__cache.length; 395 var indent = 0; 396 var result = ''; 397 if (this.__indent_size && column >= this.__indent_size) { 398 indent = Math.floor(column / this.__indent_size); 399 column -= indent * this.__indent_size; 400 result = new Array(indent + 1).join(this.__indent_string); 401 } 402 if (column) { 403 result += new Array(column + 1).join(' '); 404 } 405 406 this.__cache.push(result); 407 }; 408 409 function Output(options, baseIndentString) { 410 this.__indent_cache = new IndentStringCache(options, baseIndentString); 411 this.raw = false; 412 this._end_with_newline = options.end_with_newline; 413 this.indent_size = options.indent_size; 414 this.wrap_line_length = options.wrap_line_length; 415 this.indent_empty_lines = options.indent_empty_lines; 416 this.__lines = []; 417 this.previous_line = null; 418 this.current_line = null; 419 this.next_line = new OutputLine(this); 420 this.space_before_token = false; 421 this.non_breaking_space = false; 422 this.previous_token_wrapped = false; 423 // initialize 424 this.__add_outputline(); 425 } 426 427 Output.prototype.__add_outputline = function() { 428 this.previous_line = this.current_line; 429 this.current_line = this.next_line.clone_empty(); 430 this.__lines.push(this.current_line); 431 }; 432 433 Output.prototype.get_line_number = function() { 434 return this.__lines.length; 435 }; 436 437 Output.prototype.get_indent_string = function(indent, column) { 438 return this.__indent_cache.get_indent_string(indent, column); 439 }; 440 441 Output.prototype.get_indent_size = function(indent, column) { 442 return this.__indent_cache.get_indent_size(indent, column); 443 }; 444 445 Output.prototype.is_empty = function() { 446 return !this.previous_line && this.current_line.is_empty(); 447 }; 448 449 Output.prototype.add_new_line = function(force_newline) { 450 // never newline at the start of file 451 // otherwise, newline only if we didn't just add one or we're forced 452 if (this.is_empty() || 453 (!force_newline && this.just_added_newline())) { 454 return false; 455 } 456 457 // if raw output is enabled, don't print additional newlines, 458 // but still return True as though you had 459 if (!this.raw) { 460 this.__add_outputline(); 461 } 462 return true; 463 }; 464 465 Output.prototype.get_code = function(eol) { 466 this.trim(true); 467 468 // handle some edge cases where the last tokens 469 // has text that ends with newline(s) 470 var last_item = this.current_line.pop(); 471 if (last_item) { 472 if (last_item[last_item.length - 1] === '\n') { 473 last_item = last_item.replace(/\n+$/g, ''); 474 } 475 this.current_line.push(last_item); 476 } 477 478 if (this._end_with_newline) { 479 this.__add_outputline(); 480 } 481 482 var sweet_code = this.__lines.join('\n'); 483 484 if (eol !== '\n') { 485 sweet_code = sweet_code.replace(/[\n]/g, eol); 486 } 487 return sweet_code; 488 }; 489 490 Output.prototype.set_wrap_point = function() { 491 this.current_line._set_wrap_point(); 492 }; 493 494 Output.prototype.set_indent = function(indent, alignment) { 495 indent = indent || 0; 496 alignment = alignment || 0; 497 498 // Next line stores alignment values 499 this.next_line.set_indent(indent, alignment); 500 501 // Never indent your first output indent at the start of the file 502 if (this.__lines.length > 1) { 503 this.current_line.set_indent(indent, alignment); 504 return true; 505 } 506 507 this.current_line.set_indent(); 508 return false; 509 }; 510 511 Output.prototype.add_raw_token = function(token) { 512 for (var x = 0; x < token.newlines; x++) { 513 this.__add_outputline(); 514 } 515 this.current_line.set_indent(-1); 516 this.current_line.push(token.whitespace_before); 517 this.current_line.push(token.text); 518 this.space_before_token = false; 519 this.non_breaking_space = false; 520 this.previous_token_wrapped = false; 521 }; 522 523 Output.prototype.add_token = function(printable_token) { 524 this.__add_space_before_token(); 525 this.current_line.push(printable_token); 526 this.space_before_token = false; 527 this.non_breaking_space = false; 528 this.previous_token_wrapped = this.current_line._allow_wrap(); 529 }; 530 531 Output.prototype.__add_space_before_token = function() { 532 if (this.space_before_token && !this.just_added_newline()) { 533 if (!this.non_breaking_space) { 534 this.set_wrap_point(); 535 } 536 this.current_line.push(' '); 537 } 538 }; 539 540 Output.prototype.remove_indent = function(index) { 541 var output_length = this.__lines.length; 542 while (index < output_length) { 543 this.__lines[index]._remove_indent(); 544 index++; 545 } 546 this.current_line._remove_wrap_indent(); 547 }; 548 549 Output.prototype.trim = function(eat_newlines) { 550 eat_newlines = (eat_newlines === undefined) ? false : eat_newlines; 551 552 this.current_line.trim(); 553 554 while (eat_newlines && this.__lines.length > 1 && 555 this.current_line.is_empty()) { 556 this.__lines.pop(); 557 this.current_line = this.__lines[this.__lines.length - 1]; 558 this.current_line.trim(); 559 } 560 561 this.previous_line = this.__lines.length > 1 ? 562 this.__lines[this.__lines.length - 2] : null; 563 }; 564 565 Output.prototype.just_added_newline = function() { 566 return this.current_line.is_empty(); 567 }; 568 569 Output.prototype.just_added_blankline = function() { 570 return this.is_empty() || 571 (this.current_line.is_empty() && this.previous_line.is_empty()); 572 }; 573 574 Output.prototype.ensure_empty_line_above = function(starts_with, ends_with) { 575 var index = this.__lines.length - 2; 576 while (index >= 0) { 577 var potentialEmptyLine = this.__lines[index]; 578 if (potentialEmptyLine.is_empty()) { 579 break; 580 } else if (potentialEmptyLine.item(0).indexOf(starts_with) !== 0 && 581 potentialEmptyLine.item(-1) !== ends_with) { 582 this.__lines.splice(index + 1, 0, new OutputLine(this)); 583 this.previous_line = this.__lines[this.__lines.length - 2]; 584 break; 585 } 586 index--; 587 } 588 }; 589 590 module.exports.Output = Output; 591 592 593 /***/ }), 594 /* 3 */ 595 /***/ (function(module, exports, __webpack_require__) { 596 597 "use strict"; 598 /*jshint node:true */ 599 /* 600 601 The MIT License (MIT) 602 603 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 604 605 Permission is hereby granted, free of charge, to any person 606 obtaining a copy of this software and associated documentation files 607 (the "Software"), to deal in the Software without restriction, 608 including without limitation the rights to use, copy, modify, merge, 609 publish, distribute, sublicense, and/or sell copies of the Software, 610 and to permit persons to whom the Software is furnished to do so, 611 subject to the following conditions: 612 613 The above copyright notice and this permission notice shall be 614 included in all copies or substantial portions of the Software. 615 616 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 617 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 618 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 619 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 620 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 621 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 622 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 623 SOFTWARE. 624 */ 625 626 627 628 function Token(type, text, newlines, whitespace_before) { 629 this.type = type; 630 this.text = text; 631 632 // comments_before are 633 // comments that have a new line before them 634 // and may or may not have a newline after 635 // this is a set of comments before 636 this.comments_before = null; /* inline comment*/ 637 638 639 // this.comments_after = new TokenStream(); // no new line before and newline after 640 this.newlines = newlines || 0; 641 this.whitespace_before = whitespace_before || ''; 642 this.parent = null; 643 this.next = null; 644 this.previous = null; 645 this.opened = null; 646 this.closed = null; 647 this.directives = null; 648 } 649 650 651 module.exports.Token = Token; 652 653 654 /***/ }), 655 /* 4 */, 656 /* 5 */, 657 /* 6 */ 658 /***/ (function(module, exports, __webpack_require__) { 659 660 "use strict"; 661 /*jshint node:true */ 662 /* 663 664 The MIT License (MIT) 665 666 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 667 668 Permission is hereby granted, free of charge, to any person 669 obtaining a copy of this software and associated documentation files 670 (the "Software"), to deal in the Software without restriction, 671 including without limitation the rights to use, copy, modify, merge, 672 publish, distribute, sublicense, and/or sell copies of the Software, 673 and to permit persons to whom the Software is furnished to do so, 674 subject to the following conditions: 675 676 The above copyright notice and this permission notice shall be 677 included in all copies or substantial portions of the Software. 678 679 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 680 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 681 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 682 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 683 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 684 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 685 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 686 SOFTWARE. 687 */ 688 689 690 691 function Options(options, merge_child_field) { 692 this.raw_options = _mergeOpts(options, merge_child_field); 693 694 // Support passing the source text back with no change 695 this.disabled = this._get_boolean('disabled'); 696 697 this.eol = this._get_characters('eol', 'auto'); 698 this.end_with_newline = this._get_boolean('end_with_newline'); 699 this.indent_size = this._get_number('indent_size', 4); 700 this.indent_char = this._get_characters('indent_char', ' '); 701 this.indent_level = this._get_number('indent_level'); 702 703 this.preserve_newlines = this._get_boolean('preserve_newlines', true); 704 this.max_preserve_newlines = this._get_number('max_preserve_newlines', 32786); 705 if (!this.preserve_newlines) { 706 this.max_preserve_newlines = 0; 707 } 708 709 this.indent_with_tabs = this._get_boolean('indent_with_tabs', this.indent_char === '\t'); 710 if (this.indent_with_tabs) { 711 this.indent_char = '\t'; 712 713 // indent_size behavior changed after 1.8.6 714 // It used to be that indent_size would be 715 // set to 1 for indent_with_tabs. That is no longer needed and 716 // actually doesn't make sense - why not use spaces? Further, 717 // that might produce unexpected behavior - tabs being used 718 // for single-column alignment. So, when indent_with_tabs is true 719 // and indent_size is 1, reset indent_size to 4. 720 if (this.indent_size === 1) { 721 this.indent_size = 4; 722 } 723 } 724 725 // Backwards compat with 1.3.x 726 this.wrap_line_length = this._get_number('wrap_line_length', this._get_number('max_char')); 727 728 this.indent_empty_lines = this._get_boolean('indent_empty_lines'); 729 730 // valid templating languages ['django', 'erb', 'handlebars', 'php'] 731 // For now, 'auto' = all off for javascript, all on for html (and inline javascript). 732 // other values ignored 733 this.templating = this._get_selection_list('templating', ['auto', 'none', 'django', 'erb', 'handlebars', 'php'], ['auto']); 734 } 735 736 Options.prototype._get_array = function(name, default_value) { 737 var option_value = this.raw_options[name]; 738 var result = default_value || []; 739 if (typeof option_value === 'object') { 740 if (option_value !== null && typeof option_value.concat === 'function') { 741 result = option_value.concat(); 742 } 743 } else if (typeof option_value === 'string') { 744 result = option_value.split(/[^a-zA-Z0-9_\/\-]+/); 745 } 746 return result; 747 }; 748 749 Options.prototype._get_boolean = function(name, default_value) { 750 var option_value = this.raw_options[name]; 751 var result = option_value === undefined ? !!default_value : !!option_value; 752 return result; 753 }; 754 755 Options.prototype._get_characters = function(name, default_value) { 756 var option_value = this.raw_options[name]; 757 var result = default_value || ''; 758 if (typeof option_value === 'string') { 759 result = option_value.replace(/\\r/, '\r').replace(/\\n/, '\n').replace(/\\t/, '\t'); 760 } 761 return result; 762 }; 763 764 Options.prototype._get_number = function(name, default_value) { 765 var option_value = this.raw_options[name]; 766 default_value = parseInt(default_value, 10); 767 if (isNaN(default_value)) { 768 default_value = 0; 769 } 770 var result = parseInt(option_value, 10); 771 if (isNaN(result)) { 772 result = default_value; 773 } 774 return result; 775 }; 776 777 Options.prototype._get_selection = function(name, selection_list, default_value) { 778 var result = this._get_selection_list(name, selection_list, default_value); 779 if (result.length !== 1) { 780 throw new Error( 781 "Invalid Option Value: The option '" + name + "' can only be one of the following values:\n" + 782 selection_list + "\nYou passed in: '" + this.raw_options[name] + "'"); 783 } 784 785 return result[0]; 786 }; 787 788 789 Options.prototype._get_selection_list = function(name, selection_list, default_value) { 790 if (!selection_list || selection_list.length === 0) { 791 throw new Error("Selection list cannot be empty."); 792 } 793 794 default_value = default_value || [selection_list[0]]; 795 if (!this._is_valid_selection(default_value, selection_list)) { 796 throw new Error("Invalid Default Value!"); 797 } 798 799 var result = this._get_array(name, default_value); 800 if (!this._is_valid_selection(result, selection_list)) { 801 throw new Error( 802 "Invalid Option Value: The option '" + name + "' can contain only the following values:\n" + 803 selection_list + "\nYou passed in: '" + this.raw_options[name] + "'"); 804 } 805 806 return result; 807 }; 808 809 Options.prototype._is_valid_selection = function(result, selection_list) { 810 return result.length && selection_list.length && 811 !result.some(function(item) { return selection_list.indexOf(item) === -1; }); 812 }; 813 814 815 // merges child options up with the parent options object 816 // Example: obj = {a: 1, b: {a: 2}} 817 // mergeOpts(obj, 'b') 818 // 819 // Returns: {a: 2} 820 function _mergeOpts(allOptions, childFieldName) { 821 var finalOpts = {}; 822 allOptions = _normalizeOpts(allOptions); 823 var name; 824 825 for (name in allOptions) { 826 if (name !== childFieldName) { 827 finalOpts[name] = allOptions[name]; 828 } 829 } 830 831 //merge in the per type settings for the childFieldName 832 if (childFieldName && allOptions[childFieldName]) { 833 for (name in allOptions[childFieldName]) { 834 finalOpts[name] = allOptions[childFieldName][name]; 835 } 836 } 837 return finalOpts; 838 } 839 840 function _normalizeOpts(options) { 841 var convertedOpts = {}; 842 var key; 843 844 for (key in options) { 845 var newKey = key.replace(/-/g, "_"); 846 convertedOpts[newKey] = options[key]; 847 } 848 return convertedOpts; 849 } 850 851 module.exports.Options = Options; 852 module.exports.normalizeOpts = _normalizeOpts; 853 module.exports.mergeOpts = _mergeOpts; 854 855 856 /***/ }), 857 /* 7 */, 858 /* 8 */ 859 /***/ (function(module, exports, __webpack_require__) { 860 861 "use strict"; 862 /*jshint node:true */ 863 /* 864 865 The MIT License (MIT) 866 867 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 868 869 Permission is hereby granted, free of charge, to any person 870 obtaining a copy of this software and associated documentation files 871 (the "Software"), to deal in the Software without restriction, 872 including without limitation the rights to use, copy, modify, merge, 873 publish, distribute, sublicense, and/or sell copies of the Software, 874 and to permit persons to whom the Software is furnished to do so, 875 subject to the following conditions: 876 877 The above copyright notice and this permission notice shall be 878 included in all copies or substantial portions of the Software. 879 880 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 881 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 882 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 883 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 884 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 885 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 886 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 887 SOFTWARE. 888 */ 889 890 891 892 var regexp_has_sticky = RegExp.prototype.hasOwnProperty('sticky'); 893 894 function InputScanner(input_string) { 895 this.__input = input_string || ''; 896 this.__input_length = this.__input.length; 897 this.__position = 0; 898 } 899 900 InputScanner.prototype.restart = function() { 901 this.__position = 0; 902 }; 903 904 InputScanner.prototype.back = function() { 905 if (this.__position > 0) { 906 this.__position -= 1; 907 } 908 }; 909 910 InputScanner.prototype.hasNext = function() { 911 return this.__position < this.__input_length; 912 }; 913 914 InputScanner.prototype.next = function() { 915 var val = null; 916 if (this.hasNext()) { 917 val = this.__input.charAt(this.__position); 918 this.__position += 1; 919 } 920 return val; 921 }; 922 923 InputScanner.prototype.peek = function(index) { 924 var val = null; 925 index = index || 0; 926 index += this.__position; 927 if (index >= 0 && index < this.__input_length) { 928 val = this.__input.charAt(index); 929 } 930 return val; 931 }; 932 933 // This is a JavaScript only helper function (not in python) 934 // Javascript doesn't have a match method 935 // and not all implementation support "sticky" flag. 936 // If they do not support sticky then both this.match() and this.test() method 937 // must get the match and check the index of the match. 938 // If sticky is supported and set, this method will use it. 939 // Otherwise it will check that global is set, and fall back to the slower method. 940 InputScanner.prototype.__match = function(pattern, index) { 941 pattern.lastIndex = index; 942 var pattern_match = pattern.exec(this.__input); 943 944 if (pattern_match && !(regexp_has_sticky && pattern.sticky)) { 945 if (pattern_match.index !== index) { 946 pattern_match = null; 947 } 948 } 949 950 return pattern_match; 951 }; 952 953 InputScanner.prototype.test = function(pattern, index) { 954 index = index || 0; 955 index += this.__position; 956 957 if (index >= 0 && index < this.__input_length) { 958 return !!this.__match(pattern, index); 959 } else { 960 return false; 961 } 962 }; 963 964 InputScanner.prototype.testChar = function(pattern, index) { 965 // test one character regex match 966 var val = this.peek(index); 967 pattern.lastIndex = 0; 968 return val !== null && pattern.test(val); 969 }; 970 971 InputScanner.prototype.match = function(pattern) { 972 var pattern_match = this.__match(pattern, this.__position); 973 if (pattern_match) { 974 this.__position += pattern_match[0].length; 975 } else { 976 pattern_match = null; 977 } 978 return pattern_match; 979 }; 980 981 InputScanner.prototype.read = function(starting_pattern, until_pattern, until_after) { 982 var val = ''; 983 var match; 984 if (starting_pattern) { 985 match = this.match(starting_pattern); 986 if (match) { 987 val += match[0]; 988 } 989 } 990 if (until_pattern && (match || !starting_pattern)) { 991 val += this.readUntil(until_pattern, until_after); 992 } 993 return val; 994 }; 995 996 InputScanner.prototype.readUntil = function(pattern, until_after) { 997 var val = ''; 998 var match_index = this.__position; 999 pattern.lastIndex = this.__position; 1000 var pattern_match = pattern.exec(this.__input); 1001 if (pattern_match) { 1002 match_index = pattern_match.index; 1003 if (until_after) { 1004 match_index += pattern_match[0].length; 1005 } 1006 } else { 1007 match_index = this.__input_length; 1008 } 1009 1010 val = this.__input.substring(this.__position, match_index); 1011 this.__position = match_index; 1012 return val; 1013 }; 1014 1015 InputScanner.prototype.readUntilAfter = function(pattern) { 1016 return this.readUntil(pattern, true); 1017 }; 1018 1019 InputScanner.prototype.get_regexp = function(pattern, match_from) { 1020 var result = null; 1021 var flags = 'g'; 1022 if (match_from && regexp_has_sticky) { 1023 flags = 'y'; 1024 } 1025 // strings are converted to regexp 1026 if (typeof pattern === "string" && pattern !== '') { 1027 // result = new RegExp(pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), flags); 1028 result = new RegExp(pattern, flags); 1029 } else if (pattern) { 1030 result = new RegExp(pattern.source, flags); 1031 } 1032 return result; 1033 }; 1034 1035 InputScanner.prototype.get_literal_regexp = function(literal_string) { 1036 return RegExp(literal_string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')); 1037 }; 1038 1039 /* css beautifier legacy helpers */ 1040 InputScanner.prototype.peekUntilAfter = function(pattern) { 1041 var start = this.__position; 1042 var val = this.readUntilAfter(pattern); 1043 this.__position = start; 1044 return val; 1045 }; 1046 1047 InputScanner.prototype.lookBack = function(testVal) { 1048 var start = this.__position - 1; 1049 return start >= testVal.length && this.__input.substring(start - testVal.length, start) 1050 .toLowerCase() === testVal; 1051 }; 1052 1053 module.exports.InputScanner = InputScanner; 1054 1055 1056 /***/ }), 1057 /* 9 */ 1058 /***/ (function(module, exports, __webpack_require__) { 1059 1060 "use strict"; 1061 /*jshint node:true */ 1062 /* 1063 1064 The MIT License (MIT) 1065 1066 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1067 1068 Permission is hereby granted, free of charge, to any person 1069 obtaining a copy of this software and associated documentation files 1070 (the "Software"), to deal in the Software without restriction, 1071 including without limitation the rights to use, copy, modify, merge, 1072 publish, distribute, sublicense, and/or sell copies of the Software, 1073 and to permit persons to whom the Software is furnished to do so, 1074 subject to the following conditions: 1075 1076 The above copyright notice and this permission notice shall be 1077 included in all copies or substantial portions of the Software. 1078 1079 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1080 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1081 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1082 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1083 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1084 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1085 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1086 SOFTWARE. 1087 */ 1088 1089 1090 1091 var InputScanner = __webpack_require__(8).InputScanner; 1092 var Token = __webpack_require__(3).Token; 1093 var TokenStream = __webpack_require__(10).TokenStream; 1094 var WhitespacePattern = __webpack_require__(11).WhitespacePattern; 1095 1096 var TOKEN = { 1097 START: 'TK_START', 1098 RAW: 'TK_RAW', 1099 EOF: 'TK_EOF' 1100 }; 1101 1102 var Tokenizer = function(input_string, options) { 1103 this._input = new InputScanner(input_string); 1104 this._options = options || {}; 1105 this.__tokens = null; 1106 1107 this._patterns = {}; 1108 this._patterns.whitespace = new WhitespacePattern(this._input); 1109 }; 1110 1111 Tokenizer.prototype.tokenize = function() { 1112 this._input.restart(); 1113 this.__tokens = new TokenStream(); 1114 1115 this._reset(); 1116 1117 var current; 1118 var previous = new Token(TOKEN.START, ''); 1119 var open_token = null; 1120 var open_stack = []; 1121 var comments = new TokenStream(); 1122 1123 while (previous.type !== TOKEN.EOF) { 1124 current = this._get_next_token(previous, open_token); 1125 while (this._is_comment(current)) { 1126 comments.add(current); 1127 current = this._get_next_token(previous, open_token); 1128 } 1129 1130 if (!comments.isEmpty()) { 1131 current.comments_before = comments; 1132 comments = new TokenStream(); 1133 } 1134 1135 current.parent = open_token; 1136 1137 if (this._is_opening(current)) { 1138 open_stack.push(open_token); 1139 open_token = current; 1140 } else if (open_token && this._is_closing(current, open_token)) { 1141 current.opened = open_token; 1142 open_token.closed = current; 1143 open_token = open_stack.pop(); 1144 current.parent = open_token; 1145 } 1146 1147 current.previous = previous; 1148 previous.next = current; 1149 1150 this.__tokens.add(current); 1151 previous = current; 1152 } 1153 1154 return this.__tokens; 1155 }; 1156 1157 1158 Tokenizer.prototype._is_first_token = function() { 1159 return this.__tokens.isEmpty(); 1160 }; 1161 1162 Tokenizer.prototype._reset = function() {}; 1163 1164 Tokenizer.prototype._get_next_token = function(previous_token, open_token) { // jshint unused:false 1165 this._readWhitespace(); 1166 var resulting_string = this._input.read(/.+/g); 1167 if (resulting_string) { 1168 return this._create_token(TOKEN.RAW, resulting_string); 1169 } else { 1170 return this._create_token(TOKEN.EOF, ''); 1171 } 1172 }; 1173 1174 Tokenizer.prototype._is_comment = function(current_token) { // jshint unused:false 1175 return false; 1176 }; 1177 1178 Tokenizer.prototype._is_opening = function(current_token) { // jshint unused:false 1179 return false; 1180 }; 1181 1182 Tokenizer.prototype._is_closing = function(current_token, open_token) { // jshint unused:false 1183 return false; 1184 }; 1185 1186 Tokenizer.prototype._create_token = function(type, text) { 1187 var token = new Token(type, text, 1188 this._patterns.whitespace.newline_count, 1189 this._patterns.whitespace.whitespace_before_token); 1190 return token; 1191 }; 1192 1193 Tokenizer.prototype._readWhitespace = function() { 1194 return this._patterns.whitespace.read(); 1195 }; 1196 1197 1198 1199 module.exports.Tokenizer = Tokenizer; 1200 module.exports.TOKEN = TOKEN; 1201 1202 1203 /***/ }), 1204 /* 10 */ 1205 /***/ (function(module, exports, __webpack_require__) { 1206 1207 "use strict"; 1208 /*jshint node:true */ 1209 /* 1210 1211 The MIT License (MIT) 1212 1213 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1214 1215 Permission is hereby granted, free of charge, to any person 1216 obtaining a copy of this software and associated documentation files 1217 (the "Software"), to deal in the Software without restriction, 1218 including without limitation the rights to use, copy, modify, merge, 1219 publish, distribute, sublicense, and/or sell copies of the Software, 1220 and to permit persons to whom the Software is furnished to do so, 1221 subject to the following conditions: 1222 1223 The above copyright notice and this permission notice shall be 1224 included in all copies or substantial portions of the Software. 1225 1226 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1227 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1228 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1229 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1230 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1231 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1232 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1233 SOFTWARE. 1234 */ 1235 1236 1237 1238 function TokenStream(parent_token) { 1239 // private 1240 this.__tokens = []; 1241 this.__tokens_length = this.__tokens.length; 1242 this.__position = 0; 1243 this.__parent_token = parent_token; 1244 } 1245 1246 TokenStream.prototype.restart = function() { 1247 this.__position = 0; 1248 }; 1249 1250 TokenStream.prototype.isEmpty = function() { 1251 return this.__tokens_length === 0; 1252 }; 1253 1254 TokenStream.prototype.hasNext = function() { 1255 return this.__position < this.__tokens_length; 1256 }; 1257 1258 TokenStream.prototype.next = function() { 1259 var val = null; 1260 if (this.hasNext()) { 1261 val = this.__tokens[this.__position]; 1262 this.__position += 1; 1263 } 1264 return val; 1265 }; 1266 1267 TokenStream.prototype.peek = function(index) { 1268 var val = null; 1269 index = index || 0; 1270 index += this.__position; 1271 if (index >= 0 && index < this.__tokens_length) { 1272 val = this.__tokens[index]; 1273 } 1274 return val; 1275 }; 1276 1277 TokenStream.prototype.add = function(token) { 1278 if (this.__parent_token) { 1279 token.parent = this.__parent_token; 1280 } 1281 this.__tokens.push(token); 1282 this.__tokens_length += 1; 1283 }; 1284 1285 module.exports.TokenStream = TokenStream; 1286 1287 1288 /***/ }), 1289 /* 11 */ 1290 /***/ (function(module, exports, __webpack_require__) { 1291 1292 "use strict"; 1293 /*jshint node:true */ 1294 /* 1295 1296 The MIT License (MIT) 1297 1298 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1299 1300 Permission is hereby granted, free of charge, to any person 1301 obtaining a copy of this software and associated documentation files 1302 (the "Software"), to deal in the Software without restriction, 1303 including without limitation the rights to use, copy, modify, merge, 1304 publish, distribute, sublicense, and/or sell copies of the Software, 1305 and to permit persons to whom the Software is furnished to do so, 1306 subject to the following conditions: 1307 1308 The above copyright notice and this permission notice shall be 1309 included in all copies or substantial portions of the Software. 1310 1311 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1312 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1313 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1314 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1315 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1316 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1317 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1318 SOFTWARE. 1319 */ 1320 1321 1322 1323 var Pattern = __webpack_require__(12).Pattern; 1324 1325 function WhitespacePattern(input_scanner, parent) { 1326 Pattern.call(this, input_scanner, parent); 1327 if (parent) { 1328 this._line_regexp = this._input.get_regexp(parent._line_regexp); 1329 } else { 1330 this.__set_whitespace_patterns('', ''); 1331 } 1332 1333 this.newline_count = 0; 1334 this.whitespace_before_token = ''; 1335 } 1336 WhitespacePattern.prototype = new Pattern(); 1337 1338 WhitespacePattern.prototype.__set_whitespace_patterns = function(whitespace_chars, newline_chars) { 1339 whitespace_chars += '\\t '; 1340 newline_chars += '\\n\\r'; 1341 1342 this._match_pattern = this._input.get_regexp( 1343 '[' + whitespace_chars + newline_chars + ']+', true); 1344 this._newline_regexp = this._input.get_regexp( 1345 '\\r\\n|[' + newline_chars + ']'); 1346 }; 1347 1348 WhitespacePattern.prototype.read = function() { 1349 this.newline_count = 0; 1350 this.whitespace_before_token = ''; 1351 1352 var resulting_string = this._input.read(this._match_pattern); 1353 if (resulting_string === ' ') { 1354 this.whitespace_before_token = ' '; 1355 } else if (resulting_string) { 1356 var matches = this.__split(this._newline_regexp, resulting_string); 1357 this.newline_count = matches.length - 1; 1358 this.whitespace_before_token = matches[this.newline_count]; 1359 } 1360 1361 return resulting_string; 1362 }; 1363 1364 WhitespacePattern.prototype.matching = function(whitespace_chars, newline_chars) { 1365 var result = this._create(); 1366 result.__set_whitespace_patterns(whitespace_chars, newline_chars); 1367 result._update(); 1368 return result; 1369 }; 1370 1371 WhitespacePattern.prototype._create = function() { 1372 return new WhitespacePattern(this._input, this); 1373 }; 1374 1375 WhitespacePattern.prototype.__split = function(regexp, input_string) { 1376 regexp.lastIndex = 0; 1377 var start_index = 0; 1378 var result = []; 1379 var next_match = regexp.exec(input_string); 1380 while (next_match) { 1381 result.push(input_string.substring(start_index, next_match.index)); 1382 start_index = next_match.index + next_match[0].length; 1383 next_match = regexp.exec(input_string); 1384 } 1385 1386 if (start_index < input_string.length) { 1387 result.push(input_string.substring(start_index, input_string.length)); 1388 } else { 1389 result.push(''); 1390 } 1391 1392 return result; 1393 }; 1394 1395 1396 1397 module.exports.WhitespacePattern = WhitespacePattern; 1398 1399 1400 /***/ }), 1401 /* 12 */ 1402 /***/ (function(module, exports, __webpack_require__) { 1403 1404 "use strict"; 1405 /*jshint node:true */ 1406 /* 1407 1408 The MIT License (MIT) 1409 1410 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1411 1412 Permission is hereby granted, free of charge, to any person 1413 obtaining a copy of this software and associated documentation files 1414 (the "Software"), to deal in the Software without restriction, 1415 including without limitation the rights to use, copy, modify, merge, 1416 publish, distribute, sublicense, and/or sell copies of the Software, 1417 and to permit persons to whom the Software is furnished to do so, 1418 subject to the following conditions: 1419 1420 The above copyright notice and this permission notice shall be 1421 included in all copies or substantial portions of the Software. 1422 1423 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1424 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1425 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1426 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1427 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1428 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1429 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1430 SOFTWARE. 1431 */ 1432 1433 1434 1435 function Pattern(input_scanner, parent) { 1436 this._input = input_scanner; 1437 this._starting_pattern = null; 1438 this._match_pattern = null; 1439 this._until_pattern = null; 1440 this._until_after = false; 1441 1442 if (parent) { 1443 this._starting_pattern = this._input.get_regexp(parent._starting_pattern, true); 1444 this._match_pattern = this._input.get_regexp(parent._match_pattern, true); 1445 this._until_pattern = this._input.get_regexp(parent._until_pattern); 1446 this._until_after = parent._until_after; 1447 } 1448 } 1449 1450 Pattern.prototype.read = function() { 1451 var result = this._input.read(this._starting_pattern); 1452 if (!this._starting_pattern || result) { 1453 result += this._input.read(this._match_pattern, this._until_pattern, this._until_after); 1454 } 1455 return result; 1456 }; 1457 1458 Pattern.prototype.read_match = function() { 1459 return this._input.match(this._match_pattern); 1460 }; 1461 1462 Pattern.prototype.until_after = function(pattern) { 1463 var result = this._create(); 1464 result._until_after = true; 1465 result._until_pattern = this._input.get_regexp(pattern); 1466 result._update(); 1467 return result; 1468 }; 1469 1470 Pattern.prototype.until = function(pattern) { 1471 var result = this._create(); 1472 result._until_after = false; 1473 result._until_pattern = this._input.get_regexp(pattern); 1474 result._update(); 1475 return result; 1476 }; 1477 1478 Pattern.prototype.starting_with = function(pattern) { 1479 var result = this._create(); 1480 result._starting_pattern = this._input.get_regexp(pattern, true); 1481 result._update(); 1482 return result; 1483 }; 1484 1485 Pattern.prototype.matching = function(pattern) { 1486 var result = this._create(); 1487 result._match_pattern = this._input.get_regexp(pattern, true); 1488 result._update(); 1489 return result; 1490 }; 1491 1492 Pattern.prototype._create = function() { 1493 return new Pattern(this._input, this); 1494 }; 1495 1496 Pattern.prototype._update = function() {}; 1497 1498 module.exports.Pattern = Pattern; 1499 1500 1501 /***/ }), 1502 /* 13 */ 1503 /***/ (function(module, exports, __webpack_require__) { 1504 1505 "use strict"; 1506 /*jshint node:true */ 1507 /* 1508 1509 The MIT License (MIT) 1510 1511 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1512 1513 Permission is hereby granted, free of charge, to any person 1514 obtaining a copy of this software and associated documentation files 1515 (the "Software"), to deal in the Software without restriction, 1516 including without limitation the rights to use, copy, modify, merge, 1517 publish, distribute, sublicense, and/or sell copies of the Software, 1518 and to permit persons to whom the Software is furnished to do so, 1519 subject to the following conditions: 1520 1521 The above copyright notice and this permission notice shall be 1522 included in all copies or substantial portions of the Software. 1523 1524 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1525 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1526 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1527 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1528 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1529 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1530 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1531 SOFTWARE. 1532 */ 1533 1534 1535 1536 function Directives(start_block_pattern, end_block_pattern) { 1537 start_block_pattern = typeof start_block_pattern === 'string' ? start_block_pattern : start_block_pattern.source; 1538 end_block_pattern = typeof end_block_pattern === 'string' ? end_block_pattern : end_block_pattern.source; 1539 this.__directives_block_pattern = new RegExp(start_block_pattern + / beautify( \w+[:]\w+)+ /.source + end_block_pattern, 'g'); 1540 this.__directive_pattern = / (\w+)[:](\w+)/g; 1541 1542 this.__directives_end_ignore_pattern = new RegExp(start_block_pattern + /\sbeautify\signore:end\s/.source + end_block_pattern, 'g'); 1543 } 1544 1545 Directives.prototype.get_directives = function(text) { 1546 if (!text.match(this.__directives_block_pattern)) { 1547 return null; 1548 } 1549 1550 var directives = {}; 1551 this.__directive_pattern.lastIndex = 0; 1552 var directive_match = this.__directive_pattern.exec(text); 1553 1554 while (directive_match) { 1555 directives[directive_match[1]] = directive_match[2]; 1556 directive_match = this.__directive_pattern.exec(text); 1557 } 1558 1559 return directives; 1560 }; 1561 1562 Directives.prototype.readIgnored = function(input) { 1563 return input.readUntilAfter(this.__directives_end_ignore_pattern); 1564 }; 1565 1566 1567 module.exports.Directives = Directives; 1568 1569 1570 /***/ }), 1571 /* 14 */ 1572 /***/ (function(module, exports, __webpack_require__) { 1573 1574 "use strict"; 1575 /*jshint node:true */ 1576 /* 1577 1578 The MIT License (MIT) 1579 1580 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1581 1582 Permission is hereby granted, free of charge, to any person 1583 obtaining a copy of this software and associated documentation files 1584 (the "Software"), to deal in the Software without restriction, 1585 including without limitation the rights to use, copy, modify, merge, 1586 publish, distribute, sublicense, and/or sell copies of the Software, 1587 and to permit persons to whom the Software is furnished to do so, 1588 subject to the following conditions: 1589 1590 The above copyright notice and this permission notice shall be 1591 included in all copies or substantial portions of the Software. 1592 1593 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1594 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1595 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1596 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1597 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1598 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1599 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1600 SOFTWARE. 1601 */ 1602 1603 1604 1605 var Pattern = __webpack_require__(12).Pattern; 1606 1607 1608 var template_names = { 1609 django: false, 1610 erb: false, 1611 handlebars: false, 1612 php: false 1613 }; 1614 1615 // This lets templates appear anywhere we would do a readUntil 1616 // The cost is higher but it is pay to play. 1617 function TemplatablePattern(input_scanner, parent) { 1618 Pattern.call(this, input_scanner, parent); 1619 this.__template_pattern = null; 1620 this._disabled = Object.assign({}, template_names); 1621 this._excluded = Object.assign({}, template_names); 1622 1623 if (parent) { 1624 this.__template_pattern = this._input.get_regexp(parent.__template_pattern); 1625 this._excluded = Object.assign(this._excluded, parent._excluded); 1626 this._disabled = Object.assign(this._disabled, parent._disabled); 1627 } 1628 var pattern = new Pattern(input_scanner); 1629 this.__patterns = { 1630 handlebars_comment: pattern.starting_with(/{{!--/).until_after(/--}}/), 1631 handlebars_unescaped: pattern.starting_with(/{{{/).until_after(/}}}/), 1632 handlebars: pattern.starting_with(/{{/).until_after(/}}/), 1633 php: pattern.starting_with(/<\?(?:[=]|php)/).until_after(/\?>/), 1634 erb: pattern.starting_with(/<%[^%]/).until_after(/[^%]%>/), 1635 // django coflicts with handlebars a bit. 1636 django: pattern.starting_with(/{%/).until_after(/%}/), 1637 django_value: pattern.starting_with(/{{/).until_after(/}}/), 1638 django_comment: pattern.starting_with(/{#/).until_after(/#}/) 1639 }; 1640 } 1641 TemplatablePattern.prototype = new Pattern(); 1642 1643 TemplatablePattern.prototype._create = function() { 1644 return new TemplatablePattern(this._input, this); 1645 }; 1646 1647 TemplatablePattern.prototype._update = function() { 1648 this.__set_templated_pattern(); 1649 }; 1650 1651 TemplatablePattern.prototype.disable = function(language) { 1652 var result = this._create(); 1653 result._disabled[language] = true; 1654 result._update(); 1655 return result; 1656 }; 1657 1658 TemplatablePattern.prototype.read_options = function(options) { 1659 var result = this._create(); 1660 for (var language in template_names) { 1661 result._disabled[language] = options.templating.indexOf(language) === -1; 1662 } 1663 result._update(); 1664 return result; 1665 }; 1666 1667 TemplatablePattern.prototype.exclude = function(language) { 1668 var result = this._create(); 1669 result._excluded[language] = true; 1670 result._update(); 1671 return result; 1672 }; 1673 1674 TemplatablePattern.prototype.read = function() { 1675 var result = ''; 1676 if (this._match_pattern) { 1677 result = this._input.read(this._starting_pattern); 1678 } else { 1679 result = this._input.read(this._starting_pattern, this.__template_pattern); 1680 } 1681 var next = this._read_template(); 1682 while (next) { 1683 if (this._match_pattern) { 1684 next += this._input.read(this._match_pattern); 1685 } else { 1686 next += this._input.readUntil(this.__template_pattern); 1687 } 1688 result += next; 1689 next = this._read_template(); 1690 } 1691 1692 if (this._until_after) { 1693 result += this._input.readUntilAfter(this._until_pattern); 1694 } 1695 return result; 1696 }; 1697 1698 TemplatablePattern.prototype.__set_templated_pattern = function() { 1699 var items = []; 1700 1701 if (!this._disabled.php) { 1702 items.push(this.__patterns.php._starting_pattern.source); 1703 } 1704 if (!this._disabled.handlebars) { 1705 items.push(this.__patterns.handlebars._starting_pattern.source); 1706 } 1707 if (!this._disabled.erb) { 1708 items.push(this.__patterns.erb._starting_pattern.source); 1709 } 1710 if (!this._disabled.django) { 1711 items.push(this.__patterns.django._starting_pattern.source); 1712 items.push(this.__patterns.django_value._starting_pattern.source); 1713 items.push(this.__patterns.django_comment._starting_pattern.source); 1714 } 1715 1716 if (this._until_pattern) { 1717 items.push(this._until_pattern.source); 1718 } 1719 this.__template_pattern = this._input.get_regexp('(?:' + items.join('|') + ')'); 1720 }; 1721 1722 TemplatablePattern.prototype._read_template = function() { 1723 var resulting_string = ''; 1724 var c = this._input.peek(); 1725 if (c === '<') { 1726 var peek1 = this._input.peek(1); 1727 //if we're in a comment, do something special 1728 // We treat all comments as literals, even more than preformatted tags 1729 // we just look for the appropriate close tag 1730 if (!this._disabled.php && !this._excluded.php && peek1 === '?') { 1731 resulting_string = resulting_string || 1732 this.__patterns.php.read(); 1733 } 1734 if (!this._disabled.erb && !this._excluded.erb && peek1 === '%') { 1735 resulting_string = resulting_string || 1736 this.__patterns.erb.read(); 1737 } 1738 } else if (c === '{') { 1739 if (!this._disabled.handlebars && !this._excluded.handlebars) { 1740 resulting_string = resulting_string || 1741 this.__patterns.handlebars_comment.read(); 1742 resulting_string = resulting_string || 1743 this.__patterns.handlebars_unescaped.read(); 1744 resulting_string = resulting_string || 1745 this.__patterns.handlebars.read(); 1746 } 1747 if (!this._disabled.django) { 1748 // django coflicts with handlebars a bit. 1749 if (!this._excluded.django && !this._excluded.handlebars) { 1750 resulting_string = resulting_string || 1751 this.__patterns.django_value.read(); 1752 } 1753 if (!this._excluded.django) { 1754 resulting_string = resulting_string || 1755 this.__patterns.django_comment.read(); 1756 resulting_string = resulting_string || 1757 this.__patterns.django.read(); 1758 } 1759 } 1760 } 1761 return resulting_string; 1762 }; 1763 1764 1765 module.exports.TemplatablePattern = TemplatablePattern; 1766 1767 1768 /***/ }), 1769 /* 15 */, 1770 /* 16 */, 1771 /* 17 */, 1772 /* 18 */ 1773 /***/ (function(module, exports, __webpack_require__) { 1774 1775 "use strict"; 1776 /*jshint node:true */ 1777 /* 1778 1779 The MIT License (MIT) 1780 1781 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1782 1783 Permission is hereby granted, free of charge, to any person 1784 obtaining a copy of this software and associated documentation files 1785 (the "Software"), to deal in the Software without restriction, 1786 including without limitation the rights to use, copy, modify, merge, 1787 publish, distribute, sublicense, and/or sell copies of the Software, 1788 and to permit persons to whom the Software is furnished to do so, 1789 subject to the following conditions: 1790 1791 The above copyright notice and this permission notice shall be 1792 included in all copies or substantial portions of the Software. 1793 1794 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1795 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1796 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1797 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1798 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1799 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1800 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1801 SOFTWARE. 1802 */ 1803 1804 1805 1806 var Beautifier = __webpack_require__(19).Beautifier, 1807 Options = __webpack_require__(20).Options; 1808 1809 function style_html(html_source, options, js_beautify, css_beautify) { 1810 var beautifier = new Beautifier(html_source, options, js_beautify, css_beautify); 1811 return beautifier.beautify(); 1812 } 1813 1814 module.exports = style_html; 1815 module.exports.defaultOptions = function() { 1816 return new Options(); 1817 }; 1818 1819 1820 /***/ }), 1821 /* 19 */ 1822 /***/ (function(module, exports, __webpack_require__) { 1823 1824 "use strict"; 1825 /*jshint node:true */ 1826 /* 1827 1828 The MIT License (MIT) 1829 1830 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 1831 1832 Permission is hereby granted, free of charge, to any person 1833 obtaining a copy of this software and associated documentation files 1834 (the "Software"), to deal in the Software without restriction, 1835 including without limitation the rights to use, copy, modify, merge, 1836 publish, distribute, sublicense, and/or sell copies of the Software, 1837 and to permit persons to whom the Software is furnished to do so, 1838 subject to the following conditions: 1839 1840 The above copyright notice and this permission notice shall be 1841 included in all copies or substantial portions of the Software. 1842 1843 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1844 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1845 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1846 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 1847 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1848 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1849 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1850 SOFTWARE. 1851 */ 1852 1853 1854 1855 var Options = __webpack_require__(20).Options; 1856 var Output = __webpack_require__(2).Output; 1857 var Tokenizer = __webpack_require__(21).Tokenizer; 1858 var TOKEN = __webpack_require__(21).TOKEN; 1859 1860 var lineBreak = /\r\n|[\r\n]/; 1861 var allLineBreaks = /\r\n|[\r\n]/g; 1862 1863 var Printer = function(options, base_indent_string) { //handles input/output and some other printing functions 1864 1865 this.indent_level = 0; 1866 this.alignment_size = 0; 1867 this.max_preserve_newlines = options.max_preserve_newlines; 1868 this.preserve_newlines = options.preserve_newlines; 1869 1870 this._output = new Output(options, base_indent_string); 1871 1872 }; 1873 1874 Printer.prototype.current_line_has_match = function(pattern) { 1875 return this._output.current_line.has_match(pattern); 1876 }; 1877 1878 Printer.prototype.set_space_before_token = function(value, non_breaking) { 1879 this._output.space_before_token = value; 1880 this._output.non_breaking_space = non_breaking; 1881 }; 1882 1883 Printer.prototype.set_wrap_point = function() { 1884 this._output.set_indent(this.indent_level, this.alignment_size); 1885 this._output.set_wrap_point(); 1886 }; 1887 1888 1889 Printer.prototype.add_raw_token = function(token) { 1890 this._output.add_raw_token(token); 1891 }; 1892 1893 Printer.prototype.print_preserved_newlines = function(raw_token) { 1894 var newlines = 0; 1895 if (raw_token.type !== TOKEN.TEXT && raw_token.previous.type !== TOKEN.TEXT) { 1896 newlines = raw_token.newlines ? 1 : 0; 1897 } 1898 1899 if (this.preserve_newlines) { 1900 newlines = raw_token.newlines < this.max_preserve_newlines + 1 ? raw_token.newlines : this.max_preserve_newlines + 1; 1901 } 1902 for (var n = 0; n < newlines; n++) { 1903 this.print_newline(n > 0); 1904 } 1905 1906 return newlines !== 0; 1907 }; 1908 1909 Printer.prototype.traverse_whitespace = function(raw_token) { 1910 if (raw_token.whitespace_before || raw_token.newlines) { 1911 if (!this.print_preserved_newlines(raw_token)) { 1912 this._output.space_before_token = true; 1913 } 1914 return true; 1915 } 1916 return false; 1917 }; 1918 1919 Printer.prototype.previous_token_wrapped = function() { 1920 return this._output.previous_token_wrapped; 1921 }; 1922 1923 Printer.prototype.print_newline = function(force) { 1924 this._output.add_new_line(force); 1925 }; 1926 1927 Printer.prototype.print_token = function(token) { 1928 if (token.text) { 1929 this._output.set_indent(this.indent_level, this.alignment_size); 1930 this._output.add_token(token.text); 1931 } 1932 }; 1933 1934 Printer.prototype.indent = function() { 1935 this.indent_level++; 1936 }; 1937 1938 Printer.prototype.get_full_indent = function(level) { 1939 level = this.indent_level + (level || 0); 1940 if (level < 1) { 1941 return ''; 1942 } 1943 1944 return this._output.get_indent_string(level); 1945 }; 1946 1947 var get_type_attribute = function(start_token) { 1948 var result = null; 1949 var raw_token = start_token.next; 1950 1951 // Search attributes for a type attribute 1952 while (raw_token.type !== TOKEN.EOF && start_token.closed !== raw_token) { 1953 if (raw_token.type === TOKEN.ATTRIBUTE && raw_token.text === 'type') { 1954 if (raw_token.next && raw_token.next.type === TOKEN.EQUALS && 1955 raw_token.next.next && raw_token.next.next.type === TOKEN.VALUE) { 1956 result = raw_token.next.next.text; 1957 } 1958 break; 1959 } 1960 raw_token = raw_token.next; 1961 } 1962 1963 return result; 1964 }; 1965 1966 var get_custom_beautifier_name = function(tag_check, raw_token) { 1967 var typeAttribute = null; 1968 var result = null; 1969 1970 if (!raw_token.closed) { 1971 return null; 1972 } 1973 1974 if (tag_check === 'script') { 1975 typeAttribute = 'text/javascript'; 1976 } else if (tag_check === 'style') { 1977 typeAttribute = 'text/css'; 1978 } 1979 1980 typeAttribute = get_type_attribute(raw_token) || typeAttribute; 1981 1982 // For script and style tags that have a type attribute, only enable custom beautifiers for matching values 1983 // For those without a type attribute use default; 1984 if (typeAttribute.search('text/css') > -1) { 1985 result = 'css'; 1986 } else if (typeAttribute.search(/module|((text|application|dojo)\/(x-)?(javascript|ecmascript|jscript|livescript|(ld\+)?json|method|aspect))/) > -1) { 1987 result = 'javascript'; 1988 } else if (typeAttribute.search(/(text|application|dojo)\/(x-)?(html)/) > -1) { 1989 result = 'html'; 1990 } else if (typeAttribute.search(/test\/null/) > -1) { 1991 // Test only mime-type for testing the beautifier when null is passed as beautifing function 1992 result = 'null'; 1993 } 1994 1995 return result; 1996 }; 1997 1998 function in_array(what, arr) { 1999 return arr.indexOf(what) !== -1; 2000 } 2001 2002 function TagFrame(parent, parser_token, indent_level) { 2003 this.parent = parent || null; 2004 this.tag = parser_token ? parser_token.tag_name : ''; 2005 this.indent_level = indent_level || 0; 2006 this.parser_token = parser_token || null; 2007 } 2008 2009 function TagStack(printer) { 2010 this._printer = printer; 2011 this._current_frame = null; 2012 } 2013 2014 TagStack.prototype.get_parser_token = function() { 2015 return this._current_frame ? this._current_frame.parser_token : null; 2016 }; 2017 2018 TagStack.prototype.record_tag = function(parser_token) { //function to record a tag and its parent in this.tags Object 2019 var new_frame = new TagFrame(this._current_frame, parser_token, this._printer.indent_level); 2020 this._current_frame = new_frame; 2021 }; 2022 2023 TagStack.prototype._try_pop_frame = function(frame) { //function to retrieve the opening tag to the corresponding closer 2024 var parser_token = null; 2025 2026 if (frame) { 2027 parser_token = frame.parser_token; 2028 this._printer.indent_level = frame.indent_level; 2029 this._current_frame = frame.parent; 2030 } 2031 2032 return parser_token; 2033 }; 2034 2035 TagStack.prototype._get_frame = function(tag_list, stop_list) { //function to retrieve the opening tag to the corresponding closer 2036 var frame = this._current_frame; 2037 2038 while (frame) { //till we reach '' (the initial value); 2039 if (tag_list.indexOf(frame.tag) !== -1) { //if this is it use it 2040 break; 2041 } else if (stop_list && stop_list.indexOf(frame.tag) !== -1) { 2042 frame = null; 2043 break; 2044 } 2045 frame = frame.parent; 2046 } 2047 2048 return frame; 2049 }; 2050 2051 TagStack.prototype.try_pop = function(tag, stop_list) { //function to retrieve the opening tag to the corresponding closer 2052 var frame = this._get_frame([tag], stop_list); 2053 return this._try_pop_frame(frame); 2054 }; 2055 2056 TagStack.prototype.indent_to_tag = function(tag_list) { 2057 var frame = this._get_frame(tag_list); 2058 if (frame) { 2059 this._printer.indent_level = frame.indent_level; 2060 } 2061 }; 2062 2063 function Beautifier(source_text, options, js_beautify, css_beautify) { 2064 //Wrapper function to invoke all the necessary constructors and deal with the output. 2065 this._source_text = source_text || ''; 2066 options = options || {}; 2067 this._js_beautify = js_beautify; 2068 this._css_beautify = css_beautify; 2069 this._tag_stack = null; 2070 2071 // Allow the setting of language/file-type specific options 2072 // with inheritance of overall settings 2073 var optionHtml = new Options(options, 'html'); 2074 2075 this._options = optionHtml; 2076 2077 this._is_wrap_attributes_force = this._options.wrap_attributes.substr(0, 'force'.length) === 'force'; 2078 this._is_wrap_attributes_force_expand_multiline = (this._options.wrap_attributes === 'force-expand-multiline'); 2079 this._is_wrap_attributes_force_aligned = (this._options.wrap_attributes === 'force-aligned'); 2080 this._is_wrap_attributes_aligned_multiple = (this._options.wrap_attributes === 'aligned-multiple'); 2081 this._is_wrap_attributes_preserve = this._options.wrap_attributes.substr(0, 'preserve'.length) === 'preserve'; 2082 this._is_wrap_attributes_preserve_aligned = (this._options.wrap_attributes === 'preserve-aligned'); 2083 } 2084 2085 Beautifier.prototype.beautify = function() { 2086 2087 // if disabled, return the input unchanged. 2088 if (this._options.disabled) { 2089 return this._source_text; 2090 } 2091 2092 var source_text = this._source_text; 2093 var eol = this._options.eol; 2094 if (this._options.eol === 'auto') { 2095 eol = '\n'; 2096 if (source_text && lineBreak.test(source_text)) { 2097 eol = source_text.match(lineBreak)[0]; 2098 } 2099 } 2100 2101 // HACK: newline parsing inconsistent. This brute force normalizes the input. 2102 source_text = source_text.replace(allLineBreaks, '\n'); 2103 2104 var baseIndentString = source_text.match(/^[\t ]*/)[0]; 2105 2106 var last_token = { 2107 text: '', 2108 type: '' 2109 }; 2110 2111 var last_tag_token = new TagOpenParserToken(); 2112 2113 var printer = new Printer(this._options, baseIndentString); 2114 var tokens = new Tokenizer(source_text, this._options).tokenize(); 2115 2116 this._tag_stack = new TagStack(printer); 2117 2118 var parser_token = null; 2119 var raw_token = tokens.next(); 2120 while (raw_token.type !== TOKEN.EOF) { 2121 2122 if (raw_token.type === TOKEN.TAG_OPEN || raw_token.type === TOKEN.COMMENT) { 2123 parser_token = this._handle_tag_open(printer, raw_token, last_tag_token, last_token); 2124 last_tag_token = parser_token; 2125 } else if ((raw_token.type === TOKEN.ATTRIBUTE || raw_token.type === TOKEN.EQUALS || raw_token.type === TOKEN.VALUE) || 2126 (raw_token.type === TOKEN.TEXT && !last_tag_token.tag_complete)) { 2127 parser_token = this._handle_inside_tag(printer, raw_token, last_tag_token, tokens); 2128 } else if (raw_token.type === TOKEN.TAG_CLOSE) { 2129 parser_token = this._handle_tag_close(printer, raw_token, last_tag_token); 2130 } else if (raw_token.type === TOKEN.TEXT) { 2131 parser_token = this._handle_text(printer, raw_token, last_tag_token); 2132 } else { 2133 // This should never happen, but if it does. Print the raw token 2134 printer.add_raw_token(raw_token); 2135 } 2136 2137 last_token = parser_token; 2138 2139 raw_token = tokens.next(); 2140 } 2141 var sweet_code = printer._output.get_code(eol); 2142 2143 return sweet_code; 2144 }; 2145 2146 Beautifier.prototype._handle_tag_close = function(printer, raw_token, last_tag_token) { 2147 var parser_token = { 2148 text: raw_token.text, 2149 type: raw_token.type 2150 }; 2151 printer.alignment_size = 0; 2152 last_tag_token.tag_complete = true; 2153 2154 printer.set_space_before_token(raw_token.newlines || raw_token.whitespace_before !== '', true); 2155 if (last_tag_token.is_unformatted) { 2156 printer.add_raw_token(raw_token); 2157 } else { 2158 if (last_tag_token.tag_start_char === '<') { 2159 printer.set_space_before_token(raw_token.text[0] === '/', true); // space before />, no space before > 2160 if (this._is_wrap_attributes_force_expand_multiline && last_tag_token.has_wrapped_attrs) { 2161 printer.print_newline(false); 2162 } 2163 } 2164 printer.print_token(raw_token); 2165 2166 } 2167 2168 if (last_tag_token.indent_content && 2169 !(last_tag_token.is_unformatted || last_tag_token.is_content_unformatted)) { 2170 printer.indent(); 2171 2172 // only indent once per opened tag 2173 last_tag_token.indent_content = false; 2174 } 2175 2176 if (!last_tag_token.is_inline_element && 2177 !(last_tag_token.is_unformatted || last_tag_token.is_content_unformatted)) { 2178 printer.set_wrap_point(); 2179 } 2180 2181 return parser_token; 2182 }; 2183 2184 Beautifier.prototype._handle_inside_tag = function(printer, raw_token, last_tag_token, tokens) { 2185 var wrapped = last_tag_token.has_wrapped_attrs; 2186 var parser_token = { 2187 text: raw_token.text, 2188 type: raw_token.type 2189 }; 2190 2191 printer.set_space_before_token(raw_token.newlines || raw_token.whitespace_before !== '', true); 2192 if (last_tag_token.is_unformatted) { 2193 printer.add_raw_token(raw_token); 2194 } else if (last_tag_token.tag_start_char === '{' && raw_token.type === TOKEN.TEXT) { 2195 // For the insides of handlebars allow newlines or a single space between open and contents 2196 if (printer.print_preserved_newlines(raw_token)) { 2197 raw_token.newlines = 0; 2198 printer.add_raw_token(raw_token); 2199 } else { 2200 printer.print_token(raw_token); 2201 } 2202 } else { 2203 if (raw_token.type === TOKEN.ATTRIBUTE) { 2204 printer.set_space_before_token(true); 2205 last_tag_token.attr_count += 1; 2206 } else if (raw_token.type === TOKEN.EQUALS) { //no space before = 2207 printer.set_space_before_token(false); 2208 } else if (raw_token.type === TOKEN.VALUE && raw_token.previous.type === TOKEN.EQUALS) { //no space before value 2209 printer.set_space_before_token(false); 2210 } 2211 2212 if (raw_token.type === TOKEN.ATTRIBUTE && last_tag_token.tag_start_char === '<') { 2213 if (this._is_wrap_attributes_preserve || this._is_wrap_attributes_preserve_aligned) { 2214 printer.traverse_whitespace(raw_token); 2215 wrapped = wrapped || raw_token.newlines !== 0; 2216 } 2217 2218 2219 if (this._is_wrap_attributes_force) { 2220 var force_attr_wrap = last_tag_token.attr_count > 1; 2221 if (this._is_wrap_attributes_force_expand_multiline && last_tag_token.attr_count === 1) { 2222 var is_only_attribute = true; 2223 var peek_index = 0; 2224 var peek_token; 2225 do { 2226 peek_token = tokens.peek(peek_index); 2227 if (peek_token.type === TOKEN.ATTRIBUTE) { 2228 is_only_attribute = false; 2229 break; 2230 } 2231 peek_index += 1; 2232 } while (peek_index < 4 && peek_token.type !== TOKEN.EOF && peek_token.type !== TOKEN.TAG_CLOSE); 2233 2234 force_attr_wrap = !is_only_attribute; 2235 } 2236 2237 if (force_attr_wrap) { 2238 printer.print_newline(false); 2239 wrapped = true; 2240 } 2241 } 2242 } 2243 printer.print_token(raw_token); 2244 wrapped = wrapped || printer.previous_token_wrapped(); 2245 last_tag_token.has_wrapped_attrs = wrapped; 2246 } 2247 return parser_token; 2248 }; 2249 2250 Beautifier.prototype._handle_text = function(printer, raw_token, last_tag_token) { 2251 var parser_token = { 2252 text: raw_token.text, 2253 type: 'TK_CONTENT' 2254 }; 2255 if (last_tag_token.custom_beautifier_name) { //check if we need to format javascript 2256 this._print_custom_beatifier_text(printer, raw_token, last_tag_token); 2257 } else if (last_tag_token.is_unformatted || last_tag_token.is_content_unformatted) { 2258 printer.add_raw_token(raw_token); 2259 } else { 2260 printer.traverse_whitespace(raw_token); 2261 printer.print_token(raw_token); 2262 } 2263 return parser_token; 2264 }; 2265 2266 Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token, last_tag_token) { 2267 var local = this; 2268 if (raw_token.text !== '') { 2269 2270 var text = raw_token.text, 2271 _beautifier, 2272 script_indent_level = 1, 2273 pre = '', 2274 post = ''; 2275 if (last_tag_token.custom_beautifier_name === 'javascript' && typeof this._js_beautify === 'function') { 2276 _beautifier = this._js_beautify; 2277 } else if (last_tag_token.custom_beautifier_name === 'css' && typeof this._css_beautify === 'function') { 2278 _beautifier = this._css_beautify; 2279 } else if (last_tag_token.custom_beautifier_name === 'html') { 2280 _beautifier = function(html_source, options) { 2281 var beautifier = new Beautifier(html_source, options, local._js_beautify, local._css_beautify); 2282 return beautifier.beautify(); 2283 }; 2284 } 2285 2286 if (this._options.indent_scripts === "keep") { 2287 script_indent_level = 0; 2288 } else if (this._options.indent_scripts === "separate") { 2289 script_indent_level = -printer.indent_level; 2290 } 2291 2292 var indentation = printer.get_full_indent(script_indent_level); 2293 2294 // if there is at least one empty line at the end of this text, strip it 2295 // we'll be adding one back after the text but before the containing tag. 2296 text = text.replace(/\n[ \t]*$/, ''); 2297 2298 // Handle the case where content is wrapped in a comment or cdata. 2299 if (last_tag_token.custom_beautifier_name !== 'html' && 2300 text[0] === '<' && text.match(/^(<!--|<!\[CDATA\[)/)) { 2301 var matched = /^(<!--[^\n]*|<!\[CDATA\[)(\n?)([ \t\n]*)([\s\S]*)(-->|]]>)$/.exec(text); 2302 2303 // if we start to wrap but don't finish, print raw 2304 if (!matched) { 2305 printer.add_raw_token(raw_token); 2306 return; 2307 } 2308 2309 pre = indentation + matched[1] + '\n'; 2310 text = matched[4]; 2311 if (matched[5]) { 2312 post = indentation + matched[5]; 2313 } 2314 2315 // if there is at least one empty line at the end of this text, strip it 2316 // we'll be adding one back after the text but before the containing tag. 2317 text = text.replace(/\n[ \t]*$/, ''); 2318 2319 if (matched[2] || matched[3].indexOf('\n') !== -1) { 2320 // if the first line of the non-comment text has spaces 2321 // use that as the basis for indenting in null case. 2322 matched = matched[3].match(/[ \t]+$/); 2323 if (matched) { 2324 raw_token.whitespace_before = matched[0]; 2325 } 2326 } 2327 } 2328 2329 if (text) { 2330 if (_beautifier) { 2331 2332 // call the Beautifier if avaliable 2333 var Child_options = function() { 2334 this.eol = '\n'; 2335 }; 2336 Child_options.prototype = this._options.raw_options; 2337 var child_options = new Child_options(); 2338 text = _beautifier(indentation + text, child_options); 2339 } else { 2340 // simply indent the string otherwise 2341 var white = raw_token.whitespace_before; 2342 if (white) { 2343 text = text.replace(new RegExp('\n(' + white + ')?', 'g'), '\n'); 2344 } 2345 2346 text = indentation + text.replace(/\n/g, '\n' + indentation); 2347 } 2348 } 2349 2350 if (pre) { 2351 if (!text) { 2352 text = pre + post; 2353 } else { 2354 text = pre + text + '\n' + post; 2355 } 2356 } 2357 2358 printer.print_newline(false); 2359 if (text) { 2360 raw_token.text = text; 2361 raw_token.whitespace_before = ''; 2362 raw_token.newlines = 0; 2363 printer.add_raw_token(raw_token); 2364 printer.print_newline(true); 2365 } 2366 } 2367 }; 2368 2369 Beautifier.prototype._handle_tag_open = function(printer, raw_token, last_tag_token, last_token) { 2370 var parser_token = this._get_tag_open_token(raw_token); 2371 2372 if ((last_tag_token.is_unformatted || last_tag_token.is_content_unformatted) && 2373 !last_tag_token.is_empty_element && 2374 raw_token.type === TOKEN.TAG_OPEN && raw_token.text.indexOf('</') === 0) { 2375 // End element tags for unformatted or content_unformatted elements 2376 // are printed raw to keep any newlines inside them exactly the same. 2377 printer.add_raw_token(raw_token); 2378 parser_token.start_tag_token = this._tag_stack.try_pop(parser_token.tag_name); 2379 } else { 2380 printer.traverse_whitespace(raw_token); 2381 this._set_tag_position(printer, raw_token, parser_token, last_tag_token, last_token); 2382 if (!parser_token.is_inline_element) { 2383 printer.set_wrap_point(); 2384 } 2385 printer.print_token(raw_token); 2386 } 2387 2388 //indent attributes an auto, forced, aligned or forced-align line-wrap 2389 if (this._is_wrap_attributes_force_aligned || this._is_wrap_attributes_aligned_multiple || this._is_wrap_attributes_preserve_aligned) { 2390 parser_token.alignment_size = raw_token.text.length + 1; 2391 } 2392 2393 if (!parser_token.tag_complete && !parser_token.is_unformatted) { 2394 printer.alignment_size = parser_token.alignment_size; 2395 } 2396 2397 return parser_token; 2398 }; 2399 2400 var TagOpenParserToken = function(parent, raw_token) { 2401 this.parent = parent || null; 2402 this.text = ''; 2403 this.type = 'TK_TAG_OPEN'; 2404 this.tag_name = ''; 2405 this.is_inline_element = false; 2406 this.is_unformatted = false; 2407 this.is_content_unformatted = false; 2408 this.is_empty_element = false; 2409 this.is_start_tag = false; 2410 this.is_end_tag = false; 2411 this.indent_content = false; 2412 this.multiline_content = false; 2413 this.custom_beautifier_name = null; 2414 this.start_tag_token = null; 2415 this.attr_count = 0; 2416 this.has_wrapped_attrs = false; 2417 this.alignment_size = 0; 2418 this.tag_complete = false; 2419 this.tag_start_char = ''; 2420 this.tag_check = ''; 2421 2422 if (!raw_token) { 2423 this.tag_complete = true; 2424 } else { 2425 var tag_check_match; 2426 2427 this.tag_start_char = raw_token.text[0]; 2428 this.text = raw_token.text; 2429 2430 if (this.tag_start_char === '<') { 2431 tag_check_match = raw_token.text.match(/^<([^\s>]*)/); 2432 this.tag_check = tag_check_match ? tag_check_match[1] : ''; 2433 } else { 2434 tag_check_match = raw_token.text.match(/^{{(?:[\^]|#\*?)?([^\s}]+)/); 2435 this.tag_check = tag_check_match ? tag_check_match[1] : ''; 2436 2437 // handle "{{#> myPartial}} 2438 if (raw_token.text === '{{#>' && this.tag_check === '>' && raw_token.next !== null) { 2439 this.tag_check = raw_token.next.text; 2440 } 2441 } 2442 this.tag_check = this.tag_check.toLowerCase(); 2443 2444 if (raw_token.type === TOKEN.COMMENT) { 2445 this.tag_complete = true; 2446 } 2447 2448 this.is_start_tag = this.tag_check.charAt(0) !== '/'; 2449 this.tag_name = !this.is_start_tag ? this.tag_check.substr(1) : this.tag_check; 2450 this.is_end_tag = !this.is_start_tag || 2451 (raw_token.closed && raw_token.closed.text === '/>'); 2452 2453 // handlebars tags that don't start with # or ^ are single_tags, and so also start and end. 2454 this.is_end_tag = this.is_end_tag || 2455 (this.tag_start_char === '{' && (this.text.length < 3 || (/[^#\^]/.test(this.text.charAt(2))))); 2456 } 2457 }; 2458 2459 Beautifier.prototype._get_tag_open_token = function(raw_token) { //function to get a full tag and parse its type 2460 var parser_token = new TagOpenParserToken(this._tag_stack.get_parser_token(), raw_token); 2461 2462 parser_token.alignment_size = this._options.wrap_attributes_indent_size; 2463 2464 parser_token.is_end_tag = parser_token.is_end_tag || 2465 in_array(parser_token.tag_check, this._options.void_elements); 2466 2467 parser_token.is_empty_element = parser_token.tag_complete || 2468 (parser_token.is_start_tag && parser_token.is_end_tag); 2469 2470 parser_token.is_unformatted = !parser_token.tag_complete && in_array(parser_token.tag_check, this._options.unformatted); 2471 parser_token.is_content_unformatted = !parser_token.is_empty_element && in_array(parser_token.tag_check, this._options.content_unformatted); 2472 parser_token.is_inline_element = in_array(parser_token.tag_name, this._options.inline) || parser_token.tag_start_char === '{'; 2473 2474 return parser_token; 2475 }; 2476 2477 Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_token, last_tag_token, last_token) { 2478 2479 if (!parser_token.is_empty_element) { 2480 if (parser_token.is_end_tag) { //this tag is a double tag so check for tag-ending 2481 parser_token.start_tag_token = this._tag_stack.try_pop(parser_token.tag_name); //remove it and all ancestors 2482 } else { // it's a start-tag 2483 // check if this tag is starting an element that has optional end element 2484 // and do an ending needed 2485 if (this._do_optional_end_element(parser_token)) { 2486 if (!parser_token.is_inline_element) { 2487 printer.print_newline(false); 2488 } 2489 } 2490 2491 this._tag_stack.record_tag(parser_token); //push it on the tag stack 2492 2493 if ((parser_token.tag_name === 'script' || parser_token.tag_name === 'style') && 2494 !(parser_token.is_unformatted || parser_token.is_content_unformatted)) { 2495 parser_token.custom_beautifier_name = get_custom_beautifier_name(parser_token.tag_check, raw_token); 2496 } 2497 } 2498 } 2499 2500 if (in_array(parser_token.tag_check, this._options.extra_liners)) { //check if this double needs an extra line 2501 printer.print_newline(false); 2502 if (!printer._output.just_added_blankline()) { 2503 printer.print_newline(true); 2504 } 2505 } 2506 2507 if (parser_token.is_empty_element) { //if this tag name is a single tag type (either in the list or has a closing /) 2508 2509 // if you hit an else case, reset the indent level if you are inside an: 2510 // 'if', 'unless', or 'each' block. 2511 if (parser_token.tag_start_char === '{' && parser_token.tag_check === 'else') { 2512 this._tag_stack.indent_to_tag(['if', 'unless', 'each']); 2513 parser_token.indent_content = true; 2514 // Don't add a newline if opening {{#if}} tag is on the current line 2515 var foundIfOnCurrentLine = printer.current_line_has_match(/{{#if/); 2516 if (!foundIfOnCurrentLine) { 2517 printer.print_newline(false); 2518 } 2519 } 2520 2521 // Don't add a newline before elements that should remain where they are. 2522 if (parser_token.tag_name === '!--' && last_token.type === TOKEN.TAG_CLOSE && 2523 last_tag_token.is_end_tag && parser_token.text.indexOf('\n') === -1) { 2524 //Do nothing. Leave comments on same line. 2525 } else { 2526 if (!(parser_token.is_inline_element || parser_token.is_unformatted)) { 2527 printer.print_newline(false); 2528 } 2529 this._calcluate_parent_multiline(printer, parser_token); 2530 } 2531 } else if (parser_token.is_end_tag) { //this tag is a double tag so check for tag-ending 2532 var do_end_expand = false; 2533 2534 // deciding whether a block is multiline should not be this hard 2535 do_end_expand = parser_token.start_tag_token && parser_token.start_tag_token.multiline_content; 2536 do_end_expand = do_end_expand || (!parser_token.is_inline_element && 2537 !(last_tag_token.is_inline_element || last_tag_token.is_unformatted) && 2538 !(last_token.type === TOKEN.TAG_CLOSE && parser_token.start_tag_token === last_tag_token) && 2539 last_token.type !== 'TK_CONTENT' 2540 ); 2541 2542 if (parser_token.is_content_unformatted || parser_token.is_unformatted) { 2543 do_end_expand = false; 2544 } 2545 2546 if (do_end_expand) { 2547 printer.print_newline(false); 2548 } 2549 } else { // it's a start-tag 2550 parser_token.indent_content = !parser_token.custom_beautifier_name; 2551 2552 if (parser_token.tag_start_char === '<') { 2553 if (parser_token.tag_name === 'html') { 2554 parser_token.indent_content = this._options.indent_inner_html; 2555 } else if (parser_token.tag_name === 'head') { 2556 parser_token.indent_content = this._options.indent_head_inner_html; 2557 } else if (parser_token.tag_name === 'body') { 2558 parser_token.indent_content = this._options.indent_body_inner_html; 2559 } 2560 } 2561 2562 if (!(parser_token.is_inline_element || parser_token.is_unformatted) && 2563 (last_token.type !== 'TK_CONTENT' || parser_token.is_content_unformatted)) { 2564 printer.print_newline(false); 2565 } 2566 2567 this._calcluate_parent_multiline(printer, parser_token); 2568 } 2569 }; 2570 2571 Beautifier.prototype._calcluate_parent_multiline = function(printer, parser_token) { 2572 if (parser_token.parent && printer._output.just_added_newline() && 2573 !((parser_token.is_inline_element || parser_token.is_unformatted) && parser_token.parent.is_inline_element)) { 2574 parser_token.parent.multiline_content = true; 2575 } 2576 }; 2577 2578 //To be used for <p> tag special case: 2579 var p_closers = ['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul']; 2580 var p_parent_excludes = ['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video']; 2581 2582 Beautifier.prototype._do_optional_end_element = function(parser_token) { 2583 var result = null; 2584 // NOTE: cases of "if there is no more content in the parent element" 2585 // are handled automatically by the beautifier. 2586 // It assumes parent or ancestor close tag closes all children. 2587 // https://www.w3.org/TR/html5/syntax.html#optional-tags 2588 if (parser_token.is_empty_element || !parser_token.is_start_tag || !parser_token.parent) { 2589 return; 2590 2591 } 2592 2593 if (parser_token.tag_name === 'body') { 2594 // A head element’s end tag may be omitted if the head element is not immediately followed by a space character or a comment. 2595 result = result || this._tag_stack.try_pop('head'); 2596 2597 //} else if (parser_token.tag_name === 'body') { 2598 // DONE: A body element’s end tag may be omitted if the body element is not immediately followed by a comment. 2599 2600 } else if (parser_token.tag_name === 'li') { 2601 // An li element’s end tag may be omitted if the li element is immediately followed by another li element or if there is no more content in the parent element. 2602 result = result || this._tag_stack.try_pop('li', ['ol', 'ul']); 2603 2604 } else if (parser_token.tag_name === 'dd' || parser_token.tag_name === 'dt') { 2605 // A dd element’s end tag may be omitted if the dd element is immediately followed by another dd element or a dt element, or if there is no more content in the parent element. 2606 // A dt element’s end tag may be omitted if the dt element is immediately followed by another dt element or a dd element. 2607 result = result || this._tag_stack.try_pop('dt', ['dl']); 2608 result = result || this._tag_stack.try_pop('dd', ['dl']); 2609 2610 2611 } else if (parser_token.parent.tag_name === 'p' && p_closers.indexOf(parser_token.tag_name) !== -1) { 2612 // IMPORTANT: this else-if works because p_closers has no overlap with any other element we look for in this method 2613 // check for the parent element is an HTML element that is not an <a>, <audio>, <del>, <ins>, <map>, <noscript>, or <video> element, or an autonomous custom element. 2614 // To do this right, this needs to be coded as an inclusion of the inverse of the exclusion above. 2615 // But to start with (if we ignore "autonomous custom elements") the exclusion would be fine. 2616 var p_parent = parser_token.parent.parent; 2617 if (!p_parent || p_parent_excludes.indexOf(p_parent.tag_name) === -1) { 2618 result = result || this._tag_stack.try_pop('p'); 2619 } 2620 } else if (parser_token.tag_name === 'rp' || parser_token.tag_name === 'rt') { 2621 // An rt element’s end tag may be omitted if the rt element is immediately followed by an rt or rp element, or if there is no more content in the parent element. 2622 // An rp element’s end tag may be omitted if the rp element is immediately followed by an rt or rp element, or if there is no more content in the parent element. 2623 result = result || this._tag_stack.try_pop('rt', ['ruby', 'rtc']); 2624 result = result || this._tag_stack.try_pop('rp', ['ruby', 'rtc']); 2625 2626 } else if (parser_token.tag_name === 'optgroup') { 2627 // An optgroup element’s end tag may be omitted if the optgroup element is immediately followed by another optgroup element, or if there is no more content in the parent element. 2628 // An option element’s end tag may be omitted if the option element is immediately followed by another option element, or if it is immediately followed by an optgroup element, or if there is no more content in the parent element. 2629 result = result || this._tag_stack.try_pop('optgroup', ['select']); 2630 //result = result || this._tag_stack.try_pop('option', ['select']); 2631 2632 } else if (parser_token.tag_name === 'option') { 2633 // An option element’s end tag may be omitted if the option element is immediately followed by another option element, or if it is immediately followed by an optgroup element, or if there is no more content in the parent element. 2634 result = result || this._tag_stack.try_pop('option', ['select', 'datalist', 'optgroup']); 2635 2636 } else if (parser_token.tag_name === 'colgroup') { 2637 // DONE: A colgroup element’s end tag may be omitted if the colgroup element is not immediately followed by a space character or a comment. 2638 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started. 2639 result = result || this._tag_stack.try_pop('caption', ['table']); 2640 2641 } else if (parser_token.tag_name === 'thead') { 2642 // A colgroup element's end tag may be ommitted if a thead, tfoot, tbody, or tr element is started. 2643 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started. 2644 result = result || this._tag_stack.try_pop('caption', ['table']); 2645 result = result || this._tag_stack.try_pop('colgroup', ['table']); 2646 2647 //} else if (parser_token.tag_name === 'caption') { 2648 // DONE: A caption element’s end tag may be omitted if the caption element is not immediately followed by a space character or a comment. 2649 2650 } else if (parser_token.tag_name === 'tbody' || parser_token.tag_name === 'tfoot') { 2651 // A thead element’s end tag may be omitted if the thead element is immediately followed by a tbody or tfoot element. 2652 // A tbody element’s end tag may be omitted if the tbody element is immediately followed by a tbody or tfoot element, or if there is no more content in the parent element. 2653 // A colgroup element's end tag may be ommitted if a thead, tfoot, tbody, or tr element is started. 2654 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started. 2655 result = result || this._tag_stack.try_pop('caption', ['table']); 2656 result = result || this._tag_stack.try_pop('colgroup', ['table']); 2657 result = result || this._tag_stack.try_pop('thead', ['table']); 2658 result = result || this._tag_stack.try_pop('tbody', ['table']); 2659 2660 //} else if (parser_token.tag_name === 'tfoot') { 2661 // DONE: A tfoot element’s end tag may be omitted if there is no more content in the parent element. 2662 2663 } else if (parser_token.tag_name === 'tr') { 2664 // A tr element’s end tag may be omitted if the tr element is immediately followed by another tr element, or if there is no more content in the parent element. 2665 // A colgroup element's end tag may be ommitted if a thead, tfoot, tbody, or tr element is started. 2666 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started. 2667 result = result || this._tag_stack.try_pop('caption', ['table']); 2668 result = result || this._tag_stack.try_pop('colgroup', ['table']); 2669 result = result || this._tag_stack.try_pop('tr', ['table', 'thead', 'tbody', 'tfoot']); 2670 2671 } else if (parser_token.tag_name === 'th' || parser_token.tag_name === 'td') { 2672 // A td element’s end tag may be omitted if the td element is immediately followed by a td or th element, or if there is no more content in the parent element. 2673 // A th element’s end tag may be omitted if the th element is immediately followed by a td or th element, or if there is no more content in the parent element. 2674 result = result || this._tag_stack.try_pop('td', ['table', 'thead', 'tbody', 'tfoot', 'tr']); 2675 result = result || this._tag_stack.try_pop('th', ['table', 'thead', 'tbody', 'tfoot', 'tr']); 2676 } 2677 2678 // Start element omission not handled currently 2679 // A head element’s start tag may be omitted if the element is empty, or if the first thing inside the head element is an element. 2680 // A tbody element’s start tag may be omitted if the first thing inside the tbody element is a tr element, and if the element is not immediately preceded by a tbody, thead, or tfoot element whose end tag has been omitted. (It can’t be omitted if the element is empty.) 2681 // A colgroup element’s start tag may be omitted if the first thing inside the colgroup element is a col element, and if the element is not immediately preceded by another colgroup element whose end tag has been omitted. (It can’t be omitted if the element is empty.) 2682 2683 // Fix up the parent of the parser token 2684 parser_token.parent = this._tag_stack.get_parser_token(); 2685 2686 return result; 2687 }; 2688 2689 module.exports.Beautifier = Beautifier; 2690 2691 2692 /***/ }), 2693 /* 20 */ 2694 /***/ (function(module, exports, __webpack_require__) { 2695 2696 "use strict"; 2697 /*jshint node:true */ 2698 /* 2699 2700 The MIT License (MIT) 2701 2702 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 2703 2704 Permission is hereby granted, free of charge, to any person 2705 obtaining a copy of this software and associated documentation files 2706 (the "Software"), to deal in the Software without restriction, 2707 including without limitation the rights to use, copy, modify, merge, 2708 publish, distribute, sublicense, and/or sell copies of the Software, 2709 and to permit persons to whom the Software is furnished to do so, 2710 subject to the following conditions: 2711 2712 The above copyright notice and this permission notice shall be 2713 included in all copies or substantial portions of the Software. 2714 2715 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2716 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2717 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2718 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2719 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2720 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2721 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2722 SOFTWARE. 2723 */ 2724 2725 2726 2727 var BaseOptions = __webpack_require__(6).Options; 2728 2729 function Options(options) { 2730 BaseOptions.call(this, options, 'html'); 2731 if (this.templating.length === 1 && this.templating[0] === 'auto') { 2732 this.templating = ['django', 'erb', 'handlebars', 'php']; 2733 } 2734 2735 this.indent_inner_html = this._get_boolean('indent_inner_html'); 2736 this.indent_body_inner_html = this._get_boolean('indent_body_inner_html', true); 2737 this.indent_head_inner_html = this._get_boolean('indent_head_inner_html', true); 2738 2739 this.indent_handlebars = this._get_boolean('indent_handlebars', true); 2740 this.wrap_attributes = this._get_selection('wrap_attributes', 2741 ['auto', 'force', 'force-aligned', 'force-expand-multiline', 'aligned-multiple', 'preserve', 'preserve-aligned']); 2742 this.wrap_attributes_indent_size = this._get_number('wrap_attributes_indent_size', this.indent_size); 2743 this.extra_liners = this._get_array('extra_liners', ['head', 'body', '/html']); 2744 2745 // Block vs inline elements 2746 // https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements 2747 // https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements 2748 // https://www.w3.org/TR/html5/dom.html#phrasing-content 2749 this.inline = this._get_array('inline', [ 2750 'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button', 'canvas', 'cite', 2751 'code', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img', 2752 'input', 'ins', 'kbd', 'keygen', 'label', 'map', 'mark', 'math', 'meter', 'noscript', 2753 'object', 'output', 'progress', 'q', 'ruby', 's', 'samp', /* 'script', */ 'select', 'small', 2754 'span', 'strong', 'sub', 'sup', 'svg', 'template', 'textarea', 'time', 'u', 'var', 2755 'video', 'wbr', 'text', 2756 // obsolete inline tags 2757 'acronym', 'big', 'strike', 'tt' 2758 ]); 2759 this.void_elements = this._get_array('void_elements', [ 2760 // HTLM void elements - aka self-closing tags - aka singletons 2761 // https://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements 2762 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 2763 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr', 2764 // NOTE: Optional tags are too complex for a simple list 2765 // they are hard coded in _do_optional_end_element 2766 2767 // Doctype and xml elements 2768 '!doctype', '?xml', 2769 2770 // obsolete tags 2771 // basefont: https://www.computerhope.com/jargon/h/html-basefont-tag.htm 2772 // isndex: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/isindex 2773 'basefont', 'isindex' 2774 ]); 2775 this.unformatted = this._get_array('unformatted', []); 2776 this.content_unformatted = this._get_array('content_unformatted', [ 2777 'pre', 'textarea' 2778 ]); 2779 this.unformatted_content_delimiter = this._get_characters('unformatted_content_delimiter'); 2780 this.indent_scripts = this._get_selection('indent_scripts', ['normal', 'keep', 'separate']); 2781 2782 } 2783 Options.prototype = new BaseOptions(); 2784 2785 2786 2787 module.exports.Options = Options; 2788 2789 2790 /***/ }), 2791 /* 21 */ 2792 /***/ (function(module, exports, __webpack_require__) { 2793 2794 "use strict"; 2795 /*jshint node:true */ 2796 /* 2797 2798 The MIT License (MIT) 2799 2800 Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 2801 2802 Permission is hereby granted, free of charge, to any person 2803 obtaining a copy of this software and associated documentation files 2804 (the "Software"), to deal in the Software without restriction, 2805 including without limitation the rights to use, copy, modify, merge, 2806 publish, distribute, sublicense, and/or sell copies of the Software, 2807 and to permit persons to whom the Software is furnished to do so, 2808 subject to the following conditions: 2809 2810 The above copyright notice and this permission notice shall be 2811 included in all copies or substantial portions of the Software. 2812 2813 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2814 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2815 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2816 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2817 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2818 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2819 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2820 SOFTWARE. 2821 */ 2822 2823 2824 2825 var BaseTokenizer = __webpack_require__(9).Tokenizer; 2826 var BASETOKEN = __webpack_require__(9).TOKEN; 2827 var Directives = __webpack_require__(13).Directives; 2828 var TemplatablePattern = __webpack_require__(14).TemplatablePattern; 2829 var Pattern = __webpack_require__(12).Pattern; 2830 2831 var TOKEN = { 2832 TAG_OPEN: 'TK_TAG_OPEN', 2833 TAG_CLOSE: 'TK_TAG_CLOSE', 2834 ATTRIBUTE: 'TK_ATTRIBUTE', 2835 EQUALS: 'TK_EQUALS', 2836 VALUE: 'TK_VALUE', 2837 COMMENT: 'TK_COMMENT', 2838 TEXT: 'TK_TEXT', 2839 UNKNOWN: 'TK_UNKNOWN', 2840 START: BASETOKEN.START, 2841 RAW: BASETOKEN.RAW, 2842 EOF: BASETOKEN.EOF 2843 }; 2844 2845 var directives_core = new Directives(/<\!--/, /-->/); 2846 2847 var Tokenizer = function(input_string, options) { 2848 BaseTokenizer.call(this, input_string, options); 2849 this._current_tag_name = ''; 2850 2851 // Words end at whitespace or when a tag starts 2852 // if we are indenting handlebars, they are considered tags 2853 var templatable_reader = new TemplatablePattern(this._input).read_options(this._options); 2854 var pattern_reader = new Pattern(this._input); 2855 2856 this.__patterns = { 2857 word: templatable_reader.until(/[\n\r\t <]/), 2858 single_quote: templatable_reader.until_after(/'/), 2859 double_quote: templatable_reader.until_after(/"/), 2860 attribute: templatable_reader.until(/[\n\r\t =>]|\/>/), 2861 element_name: templatable_reader.until(/[\n\r\t >\/]/), 2862 2863 handlebars_comment: pattern_reader.starting_with(/{{!--/).until_after(/--}}/), 2864 handlebars: pattern_reader.starting_with(/{{/).until_after(/}}/), 2865 handlebars_open: pattern_reader.until(/[\n\r\t }]/), 2866 handlebars_raw_close: pattern_reader.until(/}}/), 2867 comment: pattern_reader.starting_with(/<!--/).until_after(/-->/), 2868 cdata: pattern_reader.starting_with(/<!\[CDATA\[/).until_after(/]]>/), 2869 // https://en.wikipedia.org/wiki/Conditional_comment 2870 conditional_comment: pattern_reader.starting_with(/<!\[/).until_after(/]>/), 2871 processing: pattern_reader.starting_with(/<\?/).until_after(/\?>/) 2872 }; 2873 2874 if (this._options.indent_handlebars) { 2875 this.__patterns.word = this.__patterns.word.exclude('handlebars'); 2876 } 2877 2878 this._unformatted_content_delimiter = null; 2879 2880 if (this._options.unformatted_content_delimiter) { 2881 var literal_regexp = this._input.get_literal_regexp(this._options.unformatted_content_delimiter); 2882 this.__patterns.unformatted_content_delimiter = 2883 pattern_reader.matching(literal_regexp) 2884 .until_after(literal_regexp); 2885 } 2886 }; 2887 Tokenizer.prototype = new BaseTokenizer(); 2888 2889 Tokenizer.prototype._is_comment = function(current_token) { // jshint unused:false 2890 return false; //current_token.type === TOKEN.COMMENT || current_token.type === TOKEN.UNKNOWN; 2891 }; 2892 2893 Tokenizer.prototype._is_opening = function(current_token) { 2894 return current_token.type === TOKEN.TAG_OPEN; 2895 }; 2896 2897 Tokenizer.prototype._is_closing = function(current_token, open_token) { 2898 return current_token.type === TOKEN.TAG_CLOSE && 2899 (open_token && ( 2900 ((current_token.text === '>' || current_token.text === '/>') && open_token.text[0] === '<') || 2901 (current_token.text === '}}' && open_token.text[0] === '{' && open_token.text[1] === '{'))); 2902 }; 2903 2904 Tokenizer.prototype._reset = function() { 2905 this._current_tag_name = ''; 2906 }; 2907 2908 Tokenizer.prototype._get_next_token = function(previous_token, open_token) { // jshint unused:false 2909 var token = null; 2910 this._readWhitespace(); 2911 var c = this._input.peek(); 2912 2913 if (c === null) { 2914 return this._create_token(TOKEN.EOF, ''); 2915 } 2916 2917 token = token || this._read_open_handlebars(c, open_token); 2918 token = token || this._read_attribute(c, previous_token, open_token); 2919 token = token || this._read_close(c, open_token); 2920 token = token || this._read_raw_content(c, previous_token, open_token); 2921 token = token || this._read_content_word(c); 2922 token = token || this._read_comment_or_cdata(c); 2923 token = token || this._read_processing(c); 2924 token = token || this._read_open(c, open_token); 2925 token = token || this._create_token(TOKEN.UNKNOWN, this._input.next()); 2926 2927 return token; 2928 }; 2929 2930 Tokenizer.prototype._read_comment_or_cdata = function(c) { // jshint unused:false 2931 var token = null; 2932 var resulting_string = null; 2933 var directives = null; 2934 2935 if (c === '<') { 2936 var peek1 = this._input.peek(1); 2937 // We treat all comments as literals, even more than preformatted tags 2938 // we only look for the appropriate closing marker 2939 if (peek1 === '!') { 2940 resulting_string = this.__patterns.comment.read(); 2941 2942 // only process directive on html comments 2943 if (resulting_string) { 2944 directives = directives_core.get_directives(resulting_string); 2945 if (directives && directives.ignore === 'start') { 2946 resulting_string += directives_core.readIgnored(this._input); 2947 } 2948 } else { 2949 resulting_string = this.__patterns.cdata.read(); 2950 } 2951 } 2952 2953 if (resulting_string) { 2954 token = this._create_token(TOKEN.COMMENT, resulting_string); 2955 token.directives = directives; 2956 } 2957 } 2958 2959 return token; 2960 }; 2961 2962 Tokenizer.prototype._read_processing = function(c) { // jshint unused:false 2963 var token = null; 2964 var resulting_string = null; 2965 var directives = null; 2966 2967 if (c === '<') { 2968 var peek1 = this._input.peek(1); 2969 if (peek1 === '!' || peek1 === '?') { 2970 resulting_string = this.__patterns.conditional_comment.read(); 2971 resulting_string = resulting_string || this.__patterns.processing.read(); 2972 } 2973 2974 if (resulting_string) { 2975 token = this._create_token(TOKEN.COMMENT, resulting_string); 2976 token.directives = directives; 2977 } 2978 } 2979 2980 return token; 2981 }; 2982 2983 Tokenizer.prototype._read_open = function(c, open_token) { 2984 var resulting_string = null; 2985 var token = null; 2986 if (!open_token) { 2987 if (c === '<') { 2988 2989 resulting_string = this._input.next(); 2990 if (this._input.peek() === '/') { 2991 resulting_string += this._input.next(); 2992 } 2993 resulting_string += this.__patterns.element_name.read(); 2994 token = this._create_token(TOKEN.TAG_OPEN, resulting_string); 2995 } 2996 } 2997 return token; 2998 }; 2999 3000 Tokenizer.prototype._read_open_handlebars = function(c, open_token) { 3001 var resulting_string = null; 3002 var token = null; 3003 if (!open_token) { 3004 if (this._options.indent_handlebars && c === '{' && this._input.peek(1) === '{') { 3005 if (this._input.peek(2) === '!') { 3006 resulting_string = this.__patterns.handlebars_comment.read(); 3007 resulting_string = resulting_string || this.__patterns.handlebars.read(); 3008 token = this._create_token(TOKEN.COMMENT, resulting_string); 3009 } else { 3010 resulting_string = this.__patterns.handlebars_open.read(); 3011 token = this._create_token(TOKEN.TAG_OPEN, resulting_string); 3012 } 3013 } 3014 } 3015 return token; 3016 }; 3017 3018 3019 Tokenizer.prototype._read_close = function(c, open_token) { 3020 var resulting_string = null; 3021 var token = null; 3022 if (open_token) { 3023 if (open_token.text[0] === '<' && (c === '>' || (c === '/' && this._input.peek(1) === '>'))) { 3024 resulting_string = this._input.next(); 3025 if (c === '/') { // for close tag "/>" 3026 resulting_string += this._input.next(); 3027 } 3028 token = this._create_token(TOKEN.TAG_CLOSE, resulting_string); 3029 } else if (open_token.text[0] === '{' && c === '}' && this._input.peek(1) === '}') { 3030 this._input.next(); 3031 this._input.next(); 3032 token = this._create_token(TOKEN.TAG_CLOSE, '}}'); 3033 } 3034 } 3035 3036 return token; 3037 }; 3038 3039 Tokenizer.prototype._read_attribute = function(c, previous_token, open_token) { 3040 var token = null; 3041 var resulting_string = ''; 3042 if (open_token && open_token.text[0] === '<') { 3043 3044 if (c === '=') { 3045 token = this._create_token(TOKEN.EQUALS, this._input.next()); 3046 } else if (c === '"' || c === "'") { 3047 var content = this._input.next(); 3048 if (c === '"') { 3049 content += this.__patterns.double_quote.read(); 3050 } else { 3051 content += this.__patterns.single_quote.read(); 3052 } 3053 token = this._create_token(TOKEN.VALUE, content); 3054 } else { 3055 resulting_string = this.__patterns.attribute.read(); 3056 3057 if (resulting_string) { 3058 if (previous_token.type === TOKEN.EQUALS) { 3059 token = this._create_token(TOKEN.VALUE, resulting_string); 3060 } else { 3061 token = this._create_token(TOKEN.ATTRIBUTE, resulting_string); 3062 } 3063 } 3064 } 3065 } 3066 return token; 3067 }; 3068 3069 Tokenizer.prototype._is_content_unformatted = function(tag_name) { 3070 // void_elements have no content and so cannot have unformatted content 3071 // script and style tags should always be read as unformatted content 3072 // finally content_unformatted and unformatted element contents are unformatted 3073 return this._options.void_elements.indexOf(tag_name) === -1 && 3074 (this._options.content_unformatted.indexOf(tag_name) !== -1 || 3075 this._options.unformatted.indexOf(tag_name) !== -1); 3076 }; 3077 3078 3079 Tokenizer.prototype._read_raw_content = function(c, previous_token, open_token) { // jshint unused:false 3080 var resulting_string = ''; 3081 if (open_token && open_token.text[0] === '{') { 3082 resulting_string = this.__patterns.handlebars_raw_close.read(); 3083 } else if (previous_token.type === TOKEN.TAG_CLOSE && 3084 previous_token.opened.text[0] === '<' && previous_token.text[0] !== '/') { 3085 // ^^ empty tag has no content 3086 var tag_name = previous_token.opened.text.substr(1).toLowerCase(); 3087 if (tag_name === 'script' || tag_name === 'style') { 3088 // Script and style tags are allowed to have comments wrapping their content 3089 // or just have regular content. 3090 var token = this._read_comment_or_cdata(c); 3091 if (token) { 3092 token.type = TOKEN.TEXT; 3093 return token; 3094 } 3095 resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig')); 3096 } else if (this._is_content_unformatted(tag_name)) { 3097 3098 resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig')); 3099 } 3100 } 3101 3102 if (resulting_string) { 3103 return this._create_token(TOKEN.TEXT, resulting_string); 3104 } 3105 3106 return null; 3107 }; 3108 3109 Tokenizer.prototype._read_content_word = function(c) { 3110 var resulting_string = ''; 3111 if (this._options.unformatted_content_delimiter) { 3112 if (c === this._options.unformatted_content_delimiter[0]) { 3113 resulting_string = this.__patterns.unformatted_content_delimiter.read(); 3114 } 3115 } 3116 3117 if (!resulting_string) { 3118 resulting_string = this.__patterns.word.read(); 3119 } 3120 if (resulting_string) { 3121 return this._create_token(TOKEN.TEXT, resulting_string); 3122 } 3123 }; 3124 3125 module.exports.Tokenizer = Tokenizer; 3126 module.exports.TOKEN = TOKEN; 3127 3128 3129 /***/ }) 3130 /******/ ]); 3131 var style_html = legacy_beautify_html; 3132 /* Footer */ 3133 if (typeof define === "function" && define.amd) { 3134 // Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- ) 3135 define(["require", "./beautify", "./beautify-css"], function(requireamd) { 3136 var js_beautify = requireamd("./beautify"); 3137 var css_beautify = requireamd("./beautify-css"); 3138 3139 return { 3140 html_beautify: function(html_source, options) { 3141 return style_html(html_source, options, js_beautify.js_beautify, css_beautify.css_beautify); 3142 } 3143 }; 3144 }); 3145 } else if (typeof exports !== "undefined") { 3146 // Add support for CommonJS. Just put this file somewhere on your require.paths 3147 // and you will be able to `var html_beautify = require("beautify").html_beautify`. 3148 var js_beautify = require('./beautify-js.js'); 3149 var css_beautify = require('./beautify-css.js'); 3150 3151 exports.html_beautify = function(html_source, options) { 3152 return style_html(html_source, options, js_beautify.js_beautify, css_beautify.css_beautify); 3153 }; 3154 } else if (typeof window !== "undefined") { 3155 // If we're running a web page and don't have either of the above, add our one global 3156 window.html_beautify = function(html_source, options) { 3157 return style_html(html_source, options, window.js_beautify, window.css_beautify); 3158 }; 3159 } else if (typeof global !== "undefined") { 3160 // If we don't even have window, try global. 3161 global.html_beautify = function(html_source, options) { 3162 return style_html(html_source, options, global.js_beautify, global.css_beautify); 3163 }; 3164 } 3165 3166 }());