MDL-65776 libraries: Upgrade jsbeautify to 1.13
[moodle.git] / lib / editor / atto / plugins / html / yui / src / beautify / js / beautify-html.js
1 /* AUTO-GENERATED. DO NOT MODIFY. */
2 /*
4   The MIT License (MIT)
6   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
16   The above copyright notice and this permission notice shall be
17   included in all copies or substantial portions of the Software.
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.
29  Style HTML
30 ---------------
32   Written by Nochum Sossonko, (nsossonko@hotmail.com)
34   Based on code initially developed by: Einar Lielmanis, <einar@beautifier.io>
35     https://beautifier.io/
37   Usage:
38     style_html(html_source);
40     style_html(html_source, options);
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.
60     e.g.
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 */
75 (function() {
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__) {
171 "use strict";
172 /*jshint node:true */
173 /*
174   The MIT License (MIT)
176   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
186   The above copyright notice and this permission notice shall be
187   included in all copies or substantial portions of the Software.
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 */
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;
212   this.__items = [];
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 };
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 };
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 };
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 };
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 };
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 };
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);
269     next.__character_count += this.__character_count - this.__wrap_point_character_count;
270     this.__character_count = this.__wrap_point_character_count;
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 };
281 OutputLine.prototype.is_empty = function() {
282   return this.__items.length === 0;
283 };
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 };
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 };
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 };
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 };
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 };
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 };
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   }
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   }
359   this.__base_string = baseIndentString;
360   this.__base_string_length = baseIndentString.length;
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 };
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 };
387 IndentStringCache.prototype.__ensure_cache = function(column) {
388   while (column >= this.__cache.length) {
389     this.__add_column();
390   }
391 };
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   }
406   this.__cache.push(result);
407 };
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();
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 };
433 Output.prototype.get_line_number = function() {
434   return this.__lines.length;
435 };
437 Output.prototype.get_indent_string = function(indent, column) {
438   return this.__indent_cache.get_indent_string(indent, column);
439 };
441 Output.prototype.get_indent_size = function(indent, column) {
442   return this.__indent_cache.get_indent_size(indent, column);
443 };
445 Output.prototype.is_empty = function() {
446   return !this.previous_line && this.current_line.is_empty();
447 };
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   }
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 };
465 Output.prototype.get_code = function(eol) {
466   this.trim(true);
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   }
478   if (this._end_with_newline) {
479     this.__add_outputline();
480   }
482   var sweet_code = this.__lines.join('\n');
484   if (eol !== '\n') {
485     sweet_code = sweet_code.replace(/[\n]/g, eol);
486   }
487   return sweet_code;
488 };
490 Output.prototype.set_wrap_point = function() {
491   this.current_line._set_wrap_point();
492 };
494 Output.prototype.set_indent = function(indent, alignment) {
495   indent = indent || 0;
496   alignment = alignment || 0;
498   // Next line stores alignment values
499   this.next_line.set_indent(indent, alignment);
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   }
507   this.current_line.set_indent();
508   return false;
509 };
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 };
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 };
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 };
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 };
549 Output.prototype.trim = function(eat_newlines) {
550   eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;
552   this.current_line.trim();
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   }
561   this.previous_line = this.__lines.length > 1 ?
562     this.__lines[this.__lines.length - 2] : null;
563 };
565 Output.prototype.just_added_newline = function() {
566   return this.current_line.is_empty();
567 };
569 Output.prototype.just_added_blankline = function() {
570   return this.is_empty() ||
571     (this.current_line.is_empty() && this.previous_line.is_empty());
572 };
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 };
590 module.exports.Output = Output;
593 /***/ }),
594 /* 3 */
595 /***/ (function(module, exports, __webpack_require__) {
597 "use strict";
598 /*jshint node:true */
599 /*
601   The MIT License (MIT)
603   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
613   The above copyright notice and this permission notice shall be
614   included in all copies or substantial portions of the Software.
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 */
628 function Token(type, text, newlines, whitespace_before) {
629   this.type = type;
630   this.text = text;
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*/
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;
651 module.exports.Token = Token;
654 /***/ }),
655 /* 4 */,
656 /* 5 */,
657 /* 6 */
658 /***/ (function(module, exports, __webpack_require__) {
660 "use strict";
661 /*jshint node:true */
662 /*
664   The MIT License (MIT)
666   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
676   The above copyright notice and this permission notice shall be
677   included in all copies or substantial portions of the Software.
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 */
691 function Options(options, merge_child_field) {
692   this.raw_options = _mergeOpts(options, merge_child_field);
694   // Support passing the source text back with no change
695   this.disabled = this._get_boolean('disabled');
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');
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   }
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';
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   }
725   // Backwards compat with 1.3.x
726   this.wrap_line_length = this._get_number('wrap_line_length', this._get_number('max_char'));
728   this.indent_empty_lines = this._get_boolean('indent_empty_lines');
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']);
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 };
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 };
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 };
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 };
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   }
785   return result[0];
786 };
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   }
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   }
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   }
806   return result;
807 };
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 };
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;
825   for (name in allOptions) {
826     if (name !== childFieldName) {
827       finalOpts[name] = allOptions[name];
828     }
829   }
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;
840 function _normalizeOpts(options) {
841   var convertedOpts = {};
842   var key;
844   for (key in options) {
845     var newKey = key.replace(/-/g, "_");
846     convertedOpts[newKey] = options[key];
847   }
848   return convertedOpts;
851 module.exports.Options = Options;
852 module.exports.normalizeOpts = _normalizeOpts;
853 module.exports.mergeOpts = _mergeOpts;
856 /***/ }),
857 /* 7 */,
858 /* 8 */
859 /***/ (function(module, exports, __webpack_require__) {
861 "use strict";
862 /*jshint node:true */
863 /*
865   The MIT License (MIT)
867   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
877   The above copyright notice and this permission notice shall be
878   included in all copies or substantial portions of the Software.
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 */
892 var regexp_has_sticky = RegExp.prototype.hasOwnProperty('sticky');
894 function InputScanner(input_string) {
895   this.__input = input_string || '';
896   this.__input_length = this.__input.length;
897   this.__position = 0;
900 InputScanner.prototype.restart = function() {
901   this.__position = 0;
902 };
904 InputScanner.prototype.back = function() {
905   if (this.__position > 0) {
906     this.__position -= 1;
907   }
908 };
910 InputScanner.prototype.hasNext = function() {
911   return this.__position < this.__input_length;
912 };
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 };
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 };
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);
944   if (pattern_match && !(regexp_has_sticky && pattern.sticky)) {
945     if (pattern_match.index !== index) {
946       pattern_match = null;
947     }
948   }
950   return pattern_match;
951 };
953 InputScanner.prototype.test = function(pattern, index) {
954   index = index || 0;
955   index += this.__position;
957   if (index >= 0 && index < this.__input_length) {
958     return !!this.__match(pattern, index);
959   } else {
960     return false;
961   }
962 };
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 };
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 };
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 };
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   }
1010   val = this.__input.substring(this.__position, match_index);
1011   this.__position = match_index;
1012   return val;
1013 };
1015 InputScanner.prototype.readUntilAfter = function(pattern) {
1016   return this.readUntil(pattern, true);
1017 };
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 };
1035 InputScanner.prototype.get_literal_regexp = function(literal_string) {
1036   return RegExp(literal_string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
1037 };
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 };
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 };
1053 module.exports.InputScanner = InputScanner;
1056 /***/ }),
1057 /* 9 */
1058 /***/ (function(module, exports, __webpack_require__) {
1060 "use strict";
1061 /*jshint node:true */
1062 /*
1064   The MIT License (MIT)
1066   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1076   The above copyright notice and this permission notice shall be
1077   included in all copies or substantial portions of the Software.
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 */
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;
1096 var TOKEN = {
1097   START: 'TK_START',
1098   RAW: 'TK_RAW',
1099   EOF: 'TK_EOF'
1100 };
1102 var Tokenizer = function(input_string, options) {
1103   this._input = new InputScanner(input_string);
1104   this._options = options || {};
1105   this.__tokens = null;
1107   this._patterns = {};
1108   this._patterns.whitespace = new WhitespacePattern(this._input);
1109 };
1111 Tokenizer.prototype.tokenize = function() {
1112   this._input.restart();
1113   this.__tokens = new TokenStream();
1115   this._reset();
1117   var current;
1118   var previous = new Token(TOKEN.START, '');
1119   var open_token = null;
1120   var open_stack = [];
1121   var comments = new TokenStream();
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     }
1130     if (!comments.isEmpty()) {
1131       current.comments_before = comments;
1132       comments = new TokenStream();
1133     }
1135     current.parent = open_token;
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     }
1147     current.previous = previous;
1148     previous.next = current;
1150     this.__tokens.add(current);
1151     previous = current;
1152   }
1154   return this.__tokens;
1155 };
1158 Tokenizer.prototype._is_first_token = function() {
1159   return this.__tokens.isEmpty();
1160 };
1162 Tokenizer.prototype._reset = function() {};
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 };
1174 Tokenizer.prototype._is_comment = function(current_token) { // jshint unused:false
1175   return false;
1176 };
1178 Tokenizer.prototype._is_opening = function(current_token) { // jshint unused:false
1179   return false;
1180 };
1182 Tokenizer.prototype._is_closing = function(current_token, open_token) { // jshint unused:false
1183   return false;
1184 };
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 };
1193 Tokenizer.prototype._readWhitespace = function() {
1194   return this._patterns.whitespace.read();
1195 };
1199 module.exports.Tokenizer = Tokenizer;
1200 module.exports.TOKEN = TOKEN;
1203 /***/ }),
1204 /* 10 */
1205 /***/ (function(module, exports, __webpack_require__) {
1207 "use strict";
1208 /*jshint node:true */
1209 /*
1211   The MIT License (MIT)
1213   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1223   The above copyright notice and this permission notice shall be
1224   included in all copies or substantial portions of the Software.
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 */
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;
1246 TokenStream.prototype.restart = function() {
1247   this.__position = 0;
1248 };
1250 TokenStream.prototype.isEmpty = function() {
1251   return this.__tokens_length === 0;
1252 };
1254 TokenStream.prototype.hasNext = function() {
1255   return this.__position < this.__tokens_length;
1256 };
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 };
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 };
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 };
1285 module.exports.TokenStream = TokenStream;
1288 /***/ }),
1289 /* 11 */
1290 /***/ (function(module, exports, __webpack_require__) {
1292 "use strict";
1293 /*jshint node:true */
1294 /*
1296   The MIT License (MIT)
1298   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1308   The above copyright notice and this permission notice shall be
1309   included in all copies or substantial portions of the Software.
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 */
1323 var Pattern = __webpack_require__(12).Pattern;
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   }
1333   this.newline_count = 0;
1334   this.whitespace_before_token = '';
1336 WhitespacePattern.prototype = new Pattern();
1338 WhitespacePattern.prototype.__set_whitespace_patterns = function(whitespace_chars, newline_chars) {
1339   whitespace_chars += '\\t ';
1340   newline_chars += '\\n\\r';
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 };
1348 WhitespacePattern.prototype.read = function() {
1349   this.newline_count = 0;
1350   this.whitespace_before_token = '';
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   }
1361   return resulting_string;
1362 };
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 };
1371 WhitespacePattern.prototype._create = function() {
1372   return new WhitespacePattern(this._input, this);
1373 };
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   }
1386   if (start_index < input_string.length) {
1387     result.push(input_string.substring(start_index, input_string.length));
1388   } else {
1389     result.push('');
1390   }
1392   return result;
1393 };
1397 module.exports.WhitespacePattern = WhitespacePattern;
1400 /***/ }),
1401 /* 12 */
1402 /***/ (function(module, exports, __webpack_require__) {
1404 "use strict";
1405 /*jshint node:true */
1406 /*
1408   The MIT License (MIT)
1410   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1420   The above copyright notice and this permission notice shall be
1421   included in all copies or substantial portions of the Software.
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 */
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;
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   }
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 };
1458 Pattern.prototype.read_match = function() {
1459   return this._input.match(this._match_pattern);
1460 };
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 };
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 };
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 };
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 };
1492 Pattern.prototype._create = function() {
1493   return new Pattern(this._input, this);
1494 };
1496 Pattern.prototype._update = function() {};
1498 module.exports.Pattern = Pattern;
1501 /***/ }),
1502 /* 13 */
1503 /***/ (function(module, exports, __webpack_require__) {
1505 "use strict";
1506 /*jshint node:true */
1507 /*
1509   The MIT License (MIT)
1511   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1521   The above copyright notice and this permission notice shall be
1522   included in all copies or substantial portions of the Software.
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 */
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;
1542   this.__directives_end_ignore_pattern = new RegExp(start_block_pattern + /\sbeautify\signore:end\s/.source + end_block_pattern, 'g');
1545 Directives.prototype.get_directives = function(text) {
1546   if (!text.match(this.__directives_block_pattern)) {
1547     return null;
1548   }
1550   var directives = {};
1551   this.__directive_pattern.lastIndex = 0;
1552   var directive_match = this.__directive_pattern.exec(text);
1554   while (directive_match) {
1555     directives[directive_match[1]] = directive_match[2];
1556     directive_match = this.__directive_pattern.exec(text);
1557   }
1559   return directives;
1560 };
1562 Directives.prototype.readIgnored = function(input) {
1563   return input.readUntilAfter(this.__directives_end_ignore_pattern);
1564 };
1567 module.exports.Directives = Directives;
1570 /***/ }),
1571 /* 14 */
1572 /***/ (function(module, exports, __webpack_require__) {
1574 "use strict";
1575 /*jshint node:true */
1576 /*
1578   The MIT License (MIT)
1580   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1590   The above copyright notice and this permission notice shall be
1591   included in all copies or substantial portions of the Software.
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 */
1605 var Pattern = __webpack_require__(12).Pattern;
1608 var template_names = {
1609   django: false,
1610   erb: false,
1611   handlebars: false,
1612   php: false
1613 };
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);
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   };
1641 TemplatablePattern.prototype = new Pattern();
1643 TemplatablePattern.prototype._create = function() {
1644   return new TemplatablePattern(this._input, this);
1645 };
1647 TemplatablePattern.prototype._update = function() {
1648   this.__set_templated_pattern();
1649 };
1651 TemplatablePattern.prototype.disable = function(language) {
1652   var result = this._create();
1653   result._disabled[language] = true;
1654   result._update();
1655   return result;
1656 };
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 };
1667 TemplatablePattern.prototype.exclude = function(language) {
1668   var result = this._create();
1669   result._excluded[language] = true;
1670   result._update();
1671   return result;
1672 };
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   }
1692   if (this._until_after) {
1693     result += this._input.readUntilAfter(this._until_pattern);
1694   }
1695   return result;
1696 };
1698 TemplatablePattern.prototype.__set_templated_pattern = function() {
1699   var items = [];
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   }
1716   if (this._until_pattern) {
1717     items.push(this._until_pattern.source);
1718   }
1719   this.__template_pattern = this._input.get_regexp('(?:' + items.join('|') + ')');
1720 };
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 };
1765 module.exports.TemplatablePattern = TemplatablePattern;
1768 /***/ }),
1769 /* 15 */,
1770 /* 16 */,
1771 /* 17 */,
1772 /* 18 */
1773 /***/ (function(module, exports, __webpack_require__) {
1775 "use strict";
1776 /*jshint node:true */
1777 /*
1779   The MIT License (MIT)
1781   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1791   The above copyright notice and this permission notice shall be
1792   included in all copies or substantial portions of the Software.
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 */
1806 var Beautifier = __webpack_require__(19).Beautifier,
1807   Options = __webpack_require__(20).Options;
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();
1814 module.exports = style_html;
1815 module.exports.defaultOptions = function() {
1816   return new Options();
1817 };
1820 /***/ }),
1821 /* 19 */
1822 /***/ (function(module, exports, __webpack_require__) {
1824 "use strict";
1825 /*jshint node:true */
1826 /*
1828   The MIT License (MIT)
1830   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
1840   The above copyright notice and this permission notice shall be
1841   included in all copies or substantial portions of the Software.
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 */
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;
1860 var lineBreak = /\r\n|[\r\n]/;
1861 var allLineBreaks = /\r\n|[\r\n]/g;
1863 var Printer = function(options, base_indent_string) { //handles input/output and some other printing functions
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;
1870   this._output = new Output(options, base_indent_string);
1872 };
1874 Printer.prototype.current_line_has_match = function(pattern) {
1875   return this._output.current_line.has_match(pattern);
1876 };
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 };
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 };
1889 Printer.prototype.add_raw_token = function(token) {
1890   this._output.add_raw_token(token);
1891 };
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   }
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   }
1906   return newlines !== 0;
1907 };
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 };
1919 Printer.prototype.previous_token_wrapped = function() {
1920   return this._output.previous_token_wrapped;
1921 };
1923 Printer.prototype.print_newline = function(force) {
1924   this._output.add_new_line(force);
1925 };
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 };
1934 Printer.prototype.indent = function() {
1935   this.indent_level++;
1936 };
1938 Printer.prototype.get_full_indent = function(level) {
1939   level = this.indent_level + (level || 0);
1940   if (level < 1) {
1941     return '';
1942   }
1944   return this._output.get_indent_string(level);
1945 };
1947 var get_type_attribute = function(start_token) {
1948   var result = null;
1949   var raw_token = start_token.next;
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   }
1963   return result;
1964 };
1966 var get_custom_beautifier_name = function(tag_check, raw_token) {
1967   var typeAttribute = null;
1968   var result = null;
1970   if (!raw_token.closed) {
1971     return null;
1972   }
1974   if (tag_check === 'script') {
1975     typeAttribute = 'text/javascript';
1976   } else if (tag_check === 'style') {
1977     typeAttribute = 'text/css';
1978   }
1980   typeAttribute = get_type_attribute(raw_token) || typeAttribute;
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   }
1995   return result;
1996 };
1998 function in_array(what, arr) {
1999   return arr.indexOf(what) !== -1;
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;
2009 function TagStack(printer) {
2010   this._printer = printer;
2011   this._current_frame = null;
2014 TagStack.prototype.get_parser_token = function() {
2015   return this._current_frame ? this._current_frame.parser_token : null;
2016 };
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 };
2023 TagStack.prototype._try_pop_frame = function(frame) { //function to retrieve the opening tag to the corresponding closer
2024   var parser_token = null;
2026   if (frame) {
2027     parser_token = frame.parser_token;
2028     this._printer.indent_level = frame.indent_level;
2029     this._current_frame = frame.parent;
2030   }
2032   return parser_token;
2033 };
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;
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   }
2048   return frame;
2049 };
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 };
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 };
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;
2071   // Allow the setting of language/file-type specific options
2072   // with inheritance of overall settings
2073   var optionHtml = new Options(options, 'html');
2075   this._options = optionHtml;
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');
2085 Beautifier.prototype.beautify = function() {
2087   // if disabled, return the input unchanged.
2088   if (this._options.disabled) {
2089     return this._source_text;
2090   }
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   }
2101   // HACK: newline parsing inconsistent. This brute force normalizes the input.
2102   source_text = source_text.replace(allLineBreaks, '\n');
2104   var baseIndentString = source_text.match(/^[\t ]*/)[0];
2106   var last_token = {
2107     text: '',
2108     type: ''
2109   };
2111   var last_tag_token = new TagOpenParserToken();
2113   var printer = new Printer(this._options, baseIndentString);
2114   var tokens = new Tokenizer(source_text, this._options).tokenize();
2116   this._tag_stack = new TagStack(printer);
2118   var parser_token = null;
2119   var raw_token = tokens.next();
2120   while (raw_token.type !== TOKEN.EOF) {
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     }
2137     last_token = parser_token;
2139     raw_token = tokens.next();
2140   }
2141   var sweet_code = printer._output.get_code(eol);
2143   return sweet_code;
2144 };
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;
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);
2166   }
2168   if (last_tag_token.indent_content &&
2169     !(last_tag_token.is_unformatted || last_tag_token.is_content_unformatted)) {
2170     printer.indent();
2172     // only indent once per opened tag
2173     last_tag_token.indent_content = false;
2174   }
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   }
2181   return parser_token;
2182 };
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   };
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     }
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       }
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);
2234           force_attr_wrap = !is_only_attribute;
2235         }
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 };
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 };
2266 Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token, last_tag_token) {
2267   var local = this;
2268   if (raw_token.text !== '') {
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     }
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     }
2292     var indentation = printer.get_full_indent(script_indent_level);
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]*$/, '');
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);
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       }
2309       pre = indentation + matched[1] + '\n';
2310       text = matched[4];
2311       if (matched[5]) {
2312         post = indentation + matched[5];
2313       }
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]*$/, '');
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     }
2329     if (text) {
2330       if (_beautifier) {
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         }
2346         text = indentation + text.replace(/\n/g, '\n' + indentation);
2347       }
2348     }
2350     if (pre) {
2351       if (!text) {
2352         text = pre + post;
2353       } else {
2354         text = pre + text + '\n' + post;
2355       }
2356     }
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 };
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);
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   }
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   }
2393   if (!parser_token.tag_complete && !parser_token.is_unformatted) {
2394     printer.alignment_size = parser_token.alignment_size;
2395   }
2397   return parser_token;
2398 };
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 = '';
2422   if (!raw_token) {
2423     this.tag_complete = true;
2424   } else {
2425     var tag_check_match;
2427     this.tag_start_char = raw_token.text[0];
2428     this.text = raw_token.text;
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] : '';
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();
2444     if (raw_token.type === TOKEN.COMMENT) {
2445       this.tag_complete = true;
2446     }
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 === '/>');
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 };
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);
2462   parser_token.alignment_size = this._options.wrap_attributes_indent_size;
2464   parser_token.is_end_tag = parser_token.is_end_tag ||
2465     in_array(parser_token.tag_check, this._options.void_elements);
2467   parser_token.is_empty_element = parser_token.tag_complete ||
2468     (parser_token.is_start_tag && parser_token.is_end_tag);
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 === '{';
2474   return parser_token;
2475 };
2477 Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_token, last_tag_token, last_token) {
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       }
2491       this._tag_stack.record_tag(parser_token); //push it on the tag stack
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   }
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   }
2507   if (parser_token.is_empty_element) { //if this tag name is a single tag type (either in the list or has a closing /)
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     }
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;
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     );
2542     if (parser_token.is_content_unformatted || parser_token.is_unformatted) {
2543       do_end_expand = false;
2544     }
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;
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     }
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     }
2567     this._calcluate_parent_multiline(printer, parser_token);
2568   }
2569 };
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 };
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'];
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;
2591   }
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');
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.
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']);
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']);
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']);
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']);
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']);
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']);
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']);
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.
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']);
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.
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']);
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   }
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.)
2683   // Fix up the parent of the parser token
2684   parser_token.parent = this._tag_stack.get_parser_token();
2686   return result;
2687 };
2689 module.exports.Beautifier = Beautifier;
2692 /***/ }),
2693 /* 20 */
2694 /***/ (function(module, exports, __webpack_require__) {
2696 "use strict";
2697 /*jshint node:true */
2698 /*
2700   The MIT License (MIT)
2702   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
2712   The above copyright notice and this permission notice shall be
2713   included in all copies or substantial portions of the Software.
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 */
2727 var BaseOptions = __webpack_require__(6).Options;
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   }
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);
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']);
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
2767     // Doctype and xml elements
2768     '!doctype', '?xml',
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']);
2783 Options.prototype = new BaseOptions();
2787 module.exports.Options = Options;
2790 /***/ }),
2791 /* 21 */
2792 /***/ (function(module, exports, __webpack_require__) {
2794 "use strict";
2795 /*jshint node:true */
2796 /*
2798   The MIT License (MIT)
2800   Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
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:
2810   The above copyright notice and this permission notice shall be
2811   included in all copies or substantial portions of the Software.
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 */
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;
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 };
2845 var directives_core = new Directives(/<\!--/, /-->/);
2847 var Tokenizer = function(input_string, options) {
2848   BaseTokenizer.call(this, input_string, options);
2849   this._current_tag_name = '';
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);
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 >\/]/),
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   };
2874   if (this._options.indent_handlebars) {
2875     this.__patterns.word = this.__patterns.word.exclude('handlebars');
2876   }
2878   this._unformatted_content_delimiter = null;
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();
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 };
2893 Tokenizer.prototype._is_opening = function(current_token) {
2894   return current_token.type === TOKEN.TAG_OPEN;
2895 };
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 };
2904 Tokenizer.prototype._reset = function() {
2905   this._current_tag_name = '';
2906 };
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();
2913   if (c === null) {
2914     return this._create_token(TOKEN.EOF, '');
2915   }
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());
2927   return token;
2928 };
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;
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();
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     }
2953     if (resulting_string) {
2954       token = this._create_token(TOKEN.COMMENT, resulting_string);
2955       token.directives = directives;
2956     }
2957   }
2959   return token;
2960 };
2962 Tokenizer.prototype._read_processing = function(c) { // jshint unused:false
2963   var token = null;
2964   var resulting_string = null;
2965   var directives = null;
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     }
2974     if (resulting_string) {
2975       token = this._create_token(TOKEN.COMMENT, resulting_string);
2976       token.directives = directives;
2977     }
2978   }
2980   return token;
2981 };
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 === '<') {
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 };
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 };
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   }
3036   return token;
3037 };
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] === '<') {
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();
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 };
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 };
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)) {
3098       resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
3099     }
3100   }
3102   if (resulting_string) {
3103     return this._create_token(TOKEN.TEXT, resulting_string);
3104   }
3106   return null;
3107 };
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   }
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 };
3125 module.exports.Tokenizer = Tokenizer;
3126 module.exports.TOKEN = TOKEN;
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");
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');
3149     var css_beautify = require('./beautify-css.js');
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     };
3166 }());