c7fcf6d0190dead65acd602e29b8248f4b23a350
[moodle.git] / lib / editor / atto / plugins / html / yui / src / beautify / js / beautify-html.js
1 /*jshint curly:false, eqeqeq:true, laxbreak:true, noempty:false */
2 /* AUTO-GENERATED. DO NOT MODIFY. */
3 /*
5   The MIT License (MIT)
7   Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
9   Permission is hereby granted, free of charge, to any person
10   obtaining a copy of this software and associated documentation files
11   (the "Software"), to deal in the Software without restriction,
12   including without limitation the rights to use, copy, modify, merge,
13   publish, distribute, sublicense, and/or sell copies of the Software,
14   and to permit persons to whom the Software is furnished to do so,
15   subject to the following conditions:
17   The above copyright notice and this permission notice shall be
18   included in all copies or substantial portions of the Software.
20   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27   SOFTWARE.
30  Style HTML
31 ---------------
33   Written by Nochum Sossonko, (nsossonko@hotmail.com)
35   Based on code initially developed by: Einar Lielmanis, <einar@jsbeautifier.org>
36     http://jsbeautifier.org/
38   Usage:
39     style_html(html_source);
41     style_html(html_source, options);
43   The options are:
44     indent_inner_html (default false)  — indent <head> and <body> sections,
45     indent_size (default 4)          — indentation size,
46     indent_char (default space)      — character to indent with,
47     wrap_line_length (default 250)            -  maximum amount of characters per line (0 = disable)
48     brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "none"
49             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.
50     unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted
51     content_unformatted (defaults to pre tag) - 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() {
76 var legacy_beautify_html =
77 /******/ (function(modules) { // webpackBootstrap
78 /******/        // The module cache
79 /******/        var installedModules = {};
80 /******/
81 /******/        // The require function
82 /******/        function __webpack_require__(moduleId) {
83 /******/
84 /******/                // Check if module is in cache
85 /******/                if(installedModules[moduleId]) {
86 /******/                        return installedModules[moduleId].exports;
87 /******/                }
88 /******/                // Create a new module (and put it into the cache)
89 /******/                var module = installedModules[moduleId] = {
90 /******/                        i: moduleId,
91 /******/                        l: false,
92 /******/                        exports: {}
93 /******/                };
94 /******/
95 /******/                // Execute the module function
96 /******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
97 /******/
98 /******/                // Flag the module as loaded
99 /******/                module.l = true;
100 /******/
101 /******/                // Return the exports of the module
102 /******/                return module.exports;
103 /******/        }
104 /******/
105 /******/
106 /******/        // expose the modules object (__webpack_modules__)
107 /******/        __webpack_require__.m = modules;
108 /******/
109 /******/        // expose the module cache
110 /******/        __webpack_require__.c = installedModules;
111 /******/
112 /******/        // identity function for calling harmony imports with the correct context
113 /******/        __webpack_require__.i = function(value) { return value; };
114 /******/
115 /******/        // define getter function for harmony exports
116 /******/        __webpack_require__.d = function(exports, name, getter) {
117 /******/                if(!__webpack_require__.o(exports, name)) {
118 /******/                        Object.defineProperty(exports, name, {
119 /******/                                configurable: false,
120 /******/                                enumerable: true,
121 /******/                                get: getter
122 /******/                        });
123 /******/                }
124 /******/        };
125 /******/
126 /******/        // getDefaultExport function for compatibility with non-harmony modules
127 /******/        __webpack_require__.n = function(module) {
128 /******/                var getter = module && module.__esModule ?
129 /******/                        function getDefault() { return module['default']; } :
130 /******/                        function getModuleExports() { return module; };
131 /******/                __webpack_require__.d(getter, 'a', getter);
132 /******/                return getter;
133 /******/        };
134 /******/
135 /******/        // Object.prototype.hasOwnProperty.call
136 /******/        __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
137 /******/
138 /******/        // __webpack_public_path__
139 /******/        __webpack_require__.p = "";
140 /******/
141 /******/        // Load entry module and return exports
142 /******/        return __webpack_require__(__webpack_require__.s = 3);
143 /******/ })
144 /************************************************************************/
145 /******/ ([
146 /* 0 */
147 /***/ (function(module, exports, __webpack_require__) {
149 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
150 /*
152   The MIT License (MIT)
154   Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
156   Permission is hereby granted, free of charge, to any person
157   obtaining a copy of this software and associated documentation files
158   (the "Software"), to deal in the Software without restriction,
159   including without limitation the rights to use, copy, modify, merge,
160   publish, distribute, sublicense, and/or sell copies of the Software,
161   and to permit persons to whom the Software is furnished to do so,
162   subject to the following conditions:
164   The above copyright notice and this permission notice shall be
165   included in all copies or substantial portions of the Software.
167   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
168   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
169   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
170   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
171   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
172   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
173   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
174   SOFTWARE.
175 */
177 var mergeOpts = __webpack_require__(2).mergeOpts;
178 var acorn = __webpack_require__(1);
181 var lineBreak = acorn.lineBreak;
182 var allLineBreaks = acorn.allLineBreaks;
184 // function trim(s) {
185 //     return s.replace(/^\s+|\s+$/g, '');
186 // }
188 function ltrim(s) {
189     return s.replace(/^\s+/g, '');
192 function rtrim(s) {
193     return s.replace(/\s+$/g, '');
196 function Beautifier(html_source, options, js_beautify, css_beautify) {
197     //Wrapper function to invoke all the necessary constructors and deal with the output.
198     html_source = html_source || '';
200     var multi_parser,
201         indent_inner_html,
202         indent_body_inner_html,
203         indent_head_inner_html,
204         indent_size,
205         indent_character,
206         wrap_line_length,
207         brace_style,
208         unformatted,
209         content_unformatted,
210         preserve_newlines,
211         max_preserve_newlines,
212         indent_handlebars,
213         wrap_attributes,
214         wrap_attributes_indent_size,
215         is_wrap_attributes_force,
216         is_wrap_attributes_force_expand_multiline,
217         is_wrap_attributes_force_aligned,
218         end_with_newline,
219         extra_liners,
220         eol;
222     options = options || {};
224     // Allow the setting of language/file-type specific options
225     // with inheritance of overall settings
226     options = mergeOpts(options, 'html');
228     // backwards compatibility to 1.3.4
229     if ((options.wrap_line_length === undefined || parseInt(options.wrap_line_length, 10) === 0) &&
230         (options.max_char !== undefined && parseInt(options.max_char, 10) !== 0)) {
231         options.wrap_line_length = options.max_char;
232     }
234     indent_inner_html = (options.indent_inner_html === undefined) ? false : options.indent_inner_html;
235     indent_body_inner_html = (options.indent_body_inner_html === undefined) ? true : options.indent_body_inner_html;
236     indent_head_inner_html = (options.indent_head_inner_html === undefined) ? true : options.indent_head_inner_html;
237     indent_size = (options.indent_size === undefined) ? 4 : parseInt(options.indent_size, 10);
238     indent_character = (options.indent_char === undefined) ? ' ' : options.indent_char;
239     brace_style = (options.brace_style === undefined) ? 'collapse' : options.brace_style;
240     wrap_line_length = parseInt(options.wrap_line_length, 10) === 0 ? 32786 : parseInt(options.wrap_line_length || 250, 10);
241     unformatted = options.unformatted || [
242         // https://www.w3.org/TR/html5/dom.html#phrasing-content
243         'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button', 'canvas', 'cite',
244         'code', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img',
245         'input', 'ins', 'kbd', 'keygen', 'label', 'map', 'mark', 'math', 'meter', 'noscript',
246         'object', 'output', 'progress', 'q', 'ruby', 's', 'samp', /* 'script', */ 'select', 'small',
247         'span', 'strong', 'sub', 'sup', 'svg', 'template', 'textarea', 'time', 'u', 'var',
248         'video', 'wbr', 'text',
249         // prexisting - not sure of full effect of removing, leaving in
250         'acronym', 'address', 'big', 'dt', 'ins', 'strike', 'tt',
251     ];
252     content_unformatted = options.content_unformatted || [
253         'pre',
254     ];
255     preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
256     max_preserve_newlines = preserve_newlines ?
257         (isNaN(parseInt(options.max_preserve_newlines, 10)) ? 32786 : parseInt(options.max_preserve_newlines, 10)) :
258         0;
259     indent_handlebars = (options.indent_handlebars === undefined) ? false : options.indent_handlebars;
260     wrap_attributes = (options.wrap_attributes === undefined) ? 'auto' : options.wrap_attributes;
261     wrap_attributes_indent_size = (isNaN(parseInt(options.wrap_attributes_indent_size, 10))) ? indent_size : parseInt(options.wrap_attributes_indent_size, 10);
262     is_wrap_attributes_force = wrap_attributes.substr(0, 'force'.length) === 'force';
263     is_wrap_attributes_force_expand_multiline = (wrap_attributes === 'force-expand-multiline');
264     is_wrap_attributes_force_aligned = (wrap_attributes === 'force-aligned');
265     end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
266     extra_liners = (typeof options.extra_liners === 'object') && options.extra_liners ?
267         options.extra_liners.concat() : (typeof options.extra_liners === 'string') ?
268         options.extra_liners.split(',') : 'head,body,/html'.split(',');
269     eol = options.eol ? options.eol : 'auto';
271     if (options.indent_with_tabs) {
272         indent_character = '\t';
273         indent_size = 1;
274     }
276     if (eol === 'auto') {
277         eol = '\n';
278         if (html_source && lineBreak.test(html_source || '')) {
279             eol = html_source.match(lineBreak)[0];
280         }
281     }
283     eol = eol.replace(/\\r/, '\r').replace(/\\n/, '\n');
285     // HACK: newline parsing inconsistent. This brute force normalizes the input.
286     html_source = html_source.replace(allLineBreaks, '\n');
288     function Parser() {
290         this.pos = 0; //Parser position
291         this.token = '';
292         this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
293         this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
294             parent: 'parent1',
295             parentcount: 1,
296             parent1: ''
297         };
298         this.tag_type = '';
299         this.token_text = this.last_token = this.last_text = this.token_type = '';
300         this.newlines = 0;
301         this.indent_content = indent_inner_html;
302         this.indent_body_inner_html = indent_body_inner_html;
303         this.indent_head_inner_html = indent_head_inner_html;
305         this.Utils = { //Uilities made available to the various functions
306             whitespace: "\n\r\t ".split(''),
308             single_token: options.void_elements || [
309                 // HTLM void elements - aka self-closing tags - aka singletons
310                 // https://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
311                 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
312                 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr',
313                 // NOTE: Optional tags - are not understood.
314                 // https://www.w3.org/TR/html5/syntax.html#optional-tags
315                 // The rules for optional tags are too complex for a simple list
316                 // Also, the content of these tags should still be indented in many cases.
317                 // 'li' is a good exmple.
319                 // Doctype and xml elements
320                 '!doctype', '?xml',
321                 // ?php tag
322                 '?php',
323                 // other tags that were in this list, keeping just in case
324                 'basefont', 'isindex'
325             ],
326             extra_liners: extra_liners, //for tags that need a line of whitespace before them
327             in_array: function(what, arr) {
328                 for (var i = 0; i < arr.length; i++) {
329                     if (what === arr[i]) {
330                         return true;
331                     }
332                 }
333                 return false;
334             }
335         };
337         // Return true if the given text is composed entirely of whitespace.
338         this.is_whitespace = function(text) {
339             for (var n = 0; n < text.length; n++) {
340                 if (!this.Utils.in_array(text.charAt(n), this.Utils.whitespace)) {
341                     return false;
342                 }
343             }
344             return true;
345         };
347         this.traverse_whitespace = function() {
348             var input_char = '';
350             input_char = this.input.charAt(this.pos);
351             if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
352                 this.newlines = 0;
353                 while (this.Utils.in_array(input_char, this.Utils.whitespace)) {
354                     if (preserve_newlines && input_char === '\n' && this.newlines <= max_preserve_newlines) {
355                         this.newlines += 1;
356                     }
358                     this.pos++;
359                     input_char = this.input.charAt(this.pos);
360                 }
361                 return true;
362             }
363             return false;
364         };
366         // Append a space to the given content (string array) or, if we are
367         // at the wrap_line_length, append a newline/indentation.
368         // return true if a newline was added, false if a space was added
369         this.space_or_wrap = function(content) {
370             if (this.line_char_count >= this.wrap_line_length) { //insert a line when the wrap_line_length is reached
371                 this.print_newline(false, content);
372                 this.print_indentation(content);
373                 return true;
374             } else {
375                 this.line_char_count++;
376                 content.push(' ');
377                 return false;
378             }
379         };
381         this.get_content = function() { //function to capture regular content between tags
382             var input_char = '',
383                 content = [],
384                 handlebarsStarted = 0;
386             while (this.input.charAt(this.pos) !== '<' || handlebarsStarted === 2) {
387                 if (this.pos >= this.input.length) {
388                     return content.length ? content.join('') : ['', 'TK_EOF'];
389                 }
391                 if (handlebarsStarted < 2 && this.traverse_whitespace()) {
392                     this.space_or_wrap(content);
393                     continue;
394                 }
396                 input_char = this.input.charAt(this.pos);
398                 if (indent_handlebars) {
399                     if (input_char === '{') {
400                         handlebarsStarted += 1;
401                     } else if (handlebarsStarted < 2) {
402                         handlebarsStarted = 0;
403                     }
405                     if (input_char === '}' && handlebarsStarted > 0) {
406                         if (handlebarsStarted-- === 0) {
407                             break;
408                         }
409                     }
410                     // Handlebars parsing is complicated.
411                     // {{#foo}} and {{/foo}} are formatted tags.
412                     // {{something}} should get treated as content, except:
413                     // {{else}} specifically behaves like {{#if}} and {{/if}}
414                     var peek3 = this.input.substr(this.pos, 3);
415                     if (peek3 === '{{#' || peek3 === '{{/') {
416                         // These are tags and not content.
417                         break;
418                     } else if (peek3 === '{{!') {
419                         return [this.get_tag(), 'TK_TAG_HANDLEBARS_COMMENT'];
420                     } else if (this.input.substr(this.pos, 2) === '{{') {
421                         if (this.get_tag(true) === '{{else}}') {
422                             break;
423                         }
424                     }
425                 }
427                 this.pos++;
428                 this.line_char_count++;
429                 content.push(input_char); //letter at-a-time (or string) inserted to an array
430             }
431             return content.length ? content.join('') : '';
432         };
434         this.get_contents_to = function(name) { //get the full content of a script or style to pass to js_beautify
435             if (this.pos === this.input.length) {
436                 return ['', 'TK_EOF'];
437             }
438             var content = '';
439             var reg_match = new RegExp('</' + name + '\\s*>', 'igm');
440             reg_match.lastIndex = this.pos;
441             var reg_array = reg_match.exec(this.input);
442             var end_script = reg_array ? reg_array.index : this.input.length; //absolute end of script
443             if (this.pos < end_script) { //get everything in between the script tags
444                 content = this.input.substring(this.pos, end_script);
445                 this.pos = end_script;
446             }
447             return content;
448         };
450         this.record_tag = function(tag) { //function to record a tag and its parent in this.tags Object
451             if (this.tags[tag + 'count']) { //check for the existence of this tag type
452                 this.tags[tag + 'count']++;
453                 this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
454             } else { //otherwise initialize this tag type
455                 this.tags[tag + 'count'] = 1;
456                 this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
457             }
458             this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
459             this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
460         };
462         this.retrieve_tag = function(tag) { //function to retrieve the opening tag to the corresponding closer
463             if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
464                 var temp_parent = this.tags.parent; //check to see if it's a closable tag.
465                 while (temp_parent) { //till we reach '' (the initial value);
466                     if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
467                         break;
468                     }
469                     temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
470                 }
471                 if (temp_parent) { //if we caught something
472                     this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
473                     this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
474                 }
475                 delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
476                 delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
477                 if (this.tags[tag + 'count'] === 1) {
478                     delete this.tags[tag + 'count'];
479                 } else {
480                     this.tags[tag + 'count']--;
481                 }
482             }
483         };
485         this.indent_to_tag = function(tag) {
486             // Match the indentation level to the last use of this tag, but don't remove it.
487             if (!this.tags[tag + 'count']) {
488                 return;
489             }
490             var temp_parent = this.tags.parent;
491             while (temp_parent) {
492                 if (tag + this.tags[tag + 'count'] === temp_parent) {
493                     break;
494                 }
495                 temp_parent = this.tags[temp_parent + 'parent'];
496             }
497             if (temp_parent) {
498                 this.indent_level = this.tags[tag + this.tags[tag + 'count']];
499             }
500         };
502         this.get_tag = function(peek) { //function to get a full tag and parse its type
503             var input_char = '',
504                 content = [],
505                 comment = '',
506                 space = false,
507                 first_attr = true,
508                 has_wrapped_attrs = false,
509                 tag_start, tag_end,
510                 tag_start_char,
511                 orig_pos = this.pos,
512                 orig_line_char_count = this.line_char_count,
513                 is_tag_closed = false,
514                 tail;
516             peek = peek !== undefined ? peek : false;
518             do {
519                 if (this.pos >= this.input.length) {
520                     if (peek) {
521                         this.pos = orig_pos;
522                         this.line_char_count = orig_line_char_count;
523                     }
524                     return content.length ? content.join('') : ['', 'TK_EOF'];
525                 }
527                 input_char = this.input.charAt(this.pos);
528                 this.pos++;
530                 if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
531                     space = true;
532                     continue;
533                 }
535                 if (input_char === "'" || input_char === '"') {
536                     input_char += this.get_unformatted(input_char);
537                     space = true;
538                 }
540                 if (input_char === '=') { //no space before =
541                     space = false;
542                 }
543                 tail = this.input.substr(this.pos - 1);
544                 if (is_wrap_attributes_force_expand_multiline && has_wrapped_attrs && !is_tag_closed && (input_char === '>' || input_char === '/')) {
545                     if (tail.match(/^\/?\s*>/)) {
546                         space = false;
547                         is_tag_closed = true;
548                         this.print_newline(false, content);
549                         this.print_indentation(content);
550                     }
551                 }
552                 if (content.length && content[content.length - 1] !== '=' && input_char !== '>' && space) {
553                     //no space after = or before >
554                     var wrapped = this.space_or_wrap(content);
555                     var indentAttrs = wrapped && input_char !== '/' && !is_wrap_attributes_force;
556                     space = false;
558                     if (is_wrap_attributes_force && input_char !== '/') {
559                         var force_first_attr_wrap = false;
560                         if (is_wrap_attributes_force_expand_multiline && first_attr) {
561                             var is_only_attribute = tail.match(/^\S*(="([^"]|\\")*")?\s*\/?\s*>/) !== null;
562                             force_first_attr_wrap = !is_only_attribute;
563                         }
564                         if (!first_attr || force_first_attr_wrap) {
565                             this.print_newline(false, content);
566                             this.print_indentation(content);
567                             indentAttrs = true;
568                         }
569                     }
570                     if (indentAttrs) {
571                         has_wrapped_attrs = true;
573                         //indent attributes an auto, forced, or forced-align line-wrap
574                         var alignment_size = wrap_attributes_indent_size;
575                         if (is_wrap_attributes_force_aligned) {
576                             alignment_size = content.indexOf(' ') + 1;
577                         }
579                         for (var count = 0; count < alignment_size; count++) {
580                             // only ever further indent with spaces since we're trying to align characters
581                             content.push(' ');
582                         }
583                     }
584                     if (first_attr) {
585                         for (var i = 0; i < content.length; i++) {
586                             if (content[i] === ' ') {
587                                 first_attr = false;
588                                 break;
589                             }
590                         }
591                     }
592                 }
594                 if (indent_handlebars && tag_start_char === '<') {
595                     // When inside an angle-bracket tag, put spaces around
596                     // handlebars not inside of strings.
597                     if ((input_char + this.input.charAt(this.pos)) === '{{') {
598                         input_char += this.get_unformatted('}}');
599                         if (content.length && content[content.length - 1] !== ' ' && content[content.length - 1] !== '<') {
600                             input_char = ' ' + input_char;
601                         }
602                         space = true;
603                     }
604                 }
606                 if (input_char === '<' && !tag_start_char) {
607                     tag_start = this.pos - 1;
608                     tag_start_char = '<';
609                 }
611                 if (indent_handlebars && !tag_start_char) {
612                     if (content.length >= 2 && content[content.length - 1] === '{' && content[content.length - 2] === '{') {
613                         if (input_char === '#' || input_char === '/' || input_char === '!') {
614                             tag_start = this.pos - 3;
615                         } else {
616                             tag_start = this.pos - 2;
617                         }
618                         tag_start_char = '{';
619                     }
620                 }
622                 this.line_char_count++;
623                 content.push(input_char); //inserts character at-a-time (or string)
625                 if (content[1] && (content[1] === '!' || content[1] === '?' || content[1] === '%')) { //if we're in a comment, do something special
626                     // We treat all comments as literals, even more than preformatted tags
627                     // we just look for the appropriate close tag
628                     content = [this.get_comment(tag_start)];
629                     break;
630                 }
632                 if (indent_handlebars && content[1] && content[1] === '{' && content[2] && content[2] === '!') { //if we're in a comment, do something special
633                     // We treat all comments as literals, even more than preformatted tags
634                     // we just look for the appropriate close tag
635                     content = [this.get_comment(tag_start)];
636                     break;
637                 }
639                 if (indent_handlebars && tag_start_char === '{' && content.length > 2 && content[content.length - 2] === '}' && content[content.length - 1] === '}') {
640                     break;
641                 }
642             } while (input_char !== '>');
644             var tag_complete = content.join('');
645             var tag_index;
646             var tag_offset;
648             // must check for space first otherwise the tag could have the first attribute included, and
649             // then not un-indent correctly
650             if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends
651                 tag_index = tag_complete.indexOf(' ');
652             } else if (tag_complete.indexOf('\n') !== -1) { //if there's a line break, thats where the tag name ends
653                 tag_index = tag_complete.indexOf('\n');
654             } else if (tag_complete.charAt(0) === '{') {
655                 tag_index = tag_complete.indexOf('}');
656             } else { //otherwise go with the tag ending
657                 tag_index = tag_complete.indexOf('>');
658             }
659             if (tag_complete.charAt(0) === '<' || !indent_handlebars) {
660                 tag_offset = 1;
661             } else {
662                 tag_offset = tag_complete.charAt(2) === '#' ? 3 : 2;
663             }
664             var tag_check = tag_complete.substring(tag_offset, tag_index).toLowerCase();
665             if (tag_complete.charAt(tag_complete.length - 2) === '/' ||
666                 this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
667                 if (!peek) {
668                     this.tag_type = 'SINGLE';
669                 }
670             } else if (indent_handlebars && tag_complete.charAt(0) === '{' && tag_check === 'else') {
671                 if (!peek) {
672                     this.indent_to_tag('if');
673                     this.tag_type = 'HANDLEBARS_ELSE';
674                     this.indent_content = true;
675                     this.traverse_whitespace();
676                 }
677             } else if (this.is_unformatted(tag_check, unformatted) ||
678                 this.is_unformatted(tag_check, content_unformatted)) {
679                 // do not reformat the "unformatted" or "content_unformatted" tags
680                 comment = this.get_unformatted('</' + tag_check + '>', tag_complete); //...delegate to get_unformatted function
681                 content.push(comment);
682                 tag_end = this.pos - 1;
683                 this.tag_type = 'SINGLE';
684             } else if (tag_check === 'script' &&
685                 (tag_complete.search('type') === -1 ||
686                     (tag_complete.search('type') > -1 &&
687                         tag_complete.search(/\b(text|application|dojo)\/(x-)?(javascript|ecmascript|jscript|livescript|(ld\+)?json|method|aspect)/) > -1))) {
688                 if (!peek) {
689                     this.record_tag(tag_check);
690                     this.tag_type = 'SCRIPT';
691                 }
692             } else if (tag_check === 'style' &&
693                 (tag_complete.search('type') === -1 ||
694                     (tag_complete.search('type') > -1 && tag_complete.search('text/css') > -1))) {
695                 if (!peek) {
696                     this.record_tag(tag_check);
697                     this.tag_type = 'STYLE';
698                 }
699             } else if (tag_check.charAt(0) === '!') { //peek for <! comment
700                 // for comments content is already correct.
701                 if (!peek) {
702                     this.tag_type = 'SINGLE';
703                     this.traverse_whitespace();
704                 }
705             } else if (!peek) {
706                 if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
707                     this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
708                     this.tag_type = 'END';
709                 } else { //otherwise it's a start-tag
710                     this.record_tag(tag_check); //push it on the tag stack
711                     if (tag_check.toLowerCase() !== 'html') {
712                         this.indent_content = true;
713                     }
714                     this.tag_type = 'START';
715                 }
717                 // Allow preserving of newlines after a start or end tag
718                 if (this.traverse_whitespace()) {
719                     this.space_or_wrap(content);
720                 }
722                 if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
723                     this.print_newline(false, this.output);
724                     if (this.output.length && this.output[this.output.length - 2] !== '\n') {
725                         this.print_newline(true, this.output);
726                     }
727                 }
728             }
730             if (peek) {
731                 this.pos = orig_pos;
732                 this.line_char_count = orig_line_char_count;
733             }
735             return content.join(''); //returns fully formatted tag
736         };
738         this.get_comment = function(start_pos) { //function to return comment content in its entirety
739             // this is will have very poor perf, but will work for now.
740             var comment = '',
741                 delimiter = '>',
742                 matched = false;
744             this.pos = start_pos;
745             var input_char = this.input.charAt(this.pos);
746             this.pos++;
748             while (this.pos <= this.input.length) {
749                 comment += input_char;
751                 // only need to check for the delimiter if the last chars match
752                 if (comment.charAt(comment.length - 1) === delimiter.charAt(delimiter.length - 1) &&
753                     comment.indexOf(delimiter) !== -1) {
754                     break;
755                 }
757                 // only need to search for custom delimiter for the first few characters
758                 if (!matched && comment.length < 10) {
759                     if (comment.indexOf('<![if') === 0) { //peek for <![if conditional comment
760                         delimiter = '<![endif]>';
761                         matched = true;
762                     } else if (comment.indexOf('<![cdata[') === 0) { //if it's a <[cdata[ comment...
763                         delimiter = ']]>';
764                         matched = true;
765                     } else if (comment.indexOf('<![') === 0) { // some other ![ comment? ...
766                         delimiter = ']>';
767                         matched = true;
768                     } else if (comment.indexOf('<!--') === 0) { // <!-- comment ...
769                         delimiter = '-->';
770                         matched = true;
771                     } else if (comment.indexOf('{{!--') === 0) { // {{!-- handlebars comment
772                         delimiter = '--}}';
773                         matched = true;
774                     } else if (comment.indexOf('{{!') === 0) { // {{! handlebars comment
775                         if (comment.length === 5 && comment.indexOf('{{!--') === -1) {
776                             delimiter = '}}';
777                             matched = true;
778                         }
779                     } else if (comment.indexOf('<?') === 0) { // {{! handlebars comment
780                         delimiter = '?>';
781                         matched = true;
782                     } else if (comment.indexOf('<%') === 0) { // {{! handlebars comment
783                         delimiter = '%>';
784                         matched = true;
785                     }
786                 }
788                 input_char = this.input.charAt(this.pos);
789                 this.pos++;
790             }
792             return comment;
793         };
795         function tokenMatcher(delimiter) {
796             var token = '';
798             var add = function(str) {
799                 var newToken = token + str.toLowerCase();
800                 token = newToken.length <= delimiter.length ? newToken : newToken.substr(newToken.length - delimiter.length, delimiter.length);
801             };
803             var doesNotMatch = function() {
804                 return token.indexOf(delimiter) === -1;
805             };
807             return {
808                 add: add,
809                 doesNotMatch: doesNotMatch
810             };
811         }
813         this.get_unformatted = function(delimiter, orig_tag) { //function to return unformatted content in its entirety
814             if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) {
815                 return '';
816             }
817             var input_char = '';
818             var content = '';
819             var space = true;
821             var delimiterMatcher = tokenMatcher(delimiter);
823             do {
825                 if (this.pos >= this.input.length) {
826                     return content;
827                 }
829                 input_char = this.input.charAt(this.pos);
830                 this.pos++;
832                 if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
833                     if (!space) {
834                         this.line_char_count--;
835                         continue;
836                     }
837                     if (input_char === '\n' || input_char === '\r') {
838                         content += '\n';
839                         /*  Don't change tab indention for unformatted blocks.  If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'
840             for (var i=0; i<this.indent_level; i++) {
841               content += this.indent_string;
842             }
843             space = false; //...and make sure other indentation is erased
844             */
845                         this.line_char_count = 0;
846                         continue;
847                     }
848                 }
849                 content += input_char;
850                 delimiterMatcher.add(input_char);
851                 this.line_char_count++;
852                 space = true;
854                 if (indent_handlebars && input_char === '{' && content.length && content.charAt(content.length - 2) === '{') {
855                     // Handlebars expressions in strings should also be unformatted.
856                     content += this.get_unformatted('}}');
857                     // Don't consider when stopping for delimiters.
858                 }
859             } while (delimiterMatcher.doesNotMatch());
861             return content;
862         };
864         this.get_token = function() { //initial handler for token-retrieval
865             var token;
867             if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
868                 var type = this.last_token.substr(7);
869                 token = this.get_contents_to(type);
870                 if (typeof token !== 'string') {
871                     return token;
872                 }
873                 return [token, 'TK_' + type];
874             }
875             if (this.current_mode === 'CONTENT') {
876                 token = this.get_content();
877                 if (typeof token !== 'string') {
878                     return token;
879                 } else {
880                     return [token, 'TK_CONTENT'];
881                 }
882             }
884             if (this.current_mode === 'TAG') {
885                 token = this.get_tag();
886                 if (typeof token !== 'string') {
887                     return token;
888                 } else {
889                     var tag_name_type = 'TK_TAG_' + this.tag_type;
890                     return [token, tag_name_type];
891                 }
892             }
893         };
895         this.get_full_indent = function(level) {
896             level = this.indent_level + level || 0;
897             if (level < 1) {
898                 return '';
899             }
901             return Array(level + 1).join(this.indent_string);
902         };
904         this.is_unformatted = function(tag_check, unformatted) {
905             //is this an HTML5 block-level link?
906             if (!this.Utils.in_array(tag_check, unformatted)) {
907                 return false;
908             }
910             if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)) {
911                 return true;
912             }
914             //at this point we have an  tag; is its first child something we want to remain
915             //unformatted?
916             var next_tag = this.get_tag(true /* peek. */ );
918             // test next_tag to see if it is just html tag (no external content)
919             var tag = (next_tag || "").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/);
921             // if next_tag comes back but is not an isolated tag, then
922             // let's treat the 'a' tag as having content
923             // and respect the unformatted option
924             if (!tag || this.Utils.in_array(tag[1], unformatted)) {
925                 return true;
926             } else {
927                 return false;
928             }
929         };
931         this.printer = function(js_source, indent_character, indent_size, wrap_line_length, brace_style) { //handles input/output and some other printing functions
933             this.input = js_source || ''; //gets the input for the Parser
935             // HACK: newline parsing inconsistent. This brute force normalizes the input.
936             this.input = this.input.replace(/\r\n|[\r\u2028\u2029]/g, '\n');
938             this.output = [];
939             this.indent_character = indent_character;
940             this.indent_string = '';
941             this.indent_size = indent_size;
942             this.brace_style = brace_style;
943             this.indent_level = 0;
944             this.wrap_line_length = wrap_line_length;
945             this.line_char_count = 0; //count to see if wrap_line_length was exceeded
947             for (var i = 0; i < this.indent_size; i++) {
948                 this.indent_string += this.indent_character;
949             }
951             this.print_newline = function(force, arr) {
952                 this.line_char_count = 0;
953                 if (!arr || !arr.length) {
954                     return;
955                 }
956                 if (force || (arr[arr.length - 1] !== '\n')) { //we might want the extra line
957                     if ((arr[arr.length - 1] !== '\n')) {
958                         arr[arr.length - 1] = rtrim(arr[arr.length - 1]);
959                     }
960                     arr.push('\n');
961                 }
962             };
964             this.print_indentation = function(arr) {
965                 for (var i = 0; i < this.indent_level; i++) {
966                     arr.push(this.indent_string);
967                     this.line_char_count += this.indent_string.length;
968                 }
969             };
971             this.print_token = function(text) {
972                 // Avoid printing initial whitespace.
973                 if (this.is_whitespace(text) && !this.output.length) {
974                     return;
975                 }
976                 if (text || text !== '') {
977                     if (this.output.length && this.output[this.output.length - 1] === '\n') {
978                         this.print_indentation(this.output);
979                         text = ltrim(text);
980                     }
981                 }
982                 this.print_token_raw(text);
983             };
985             this.print_token_raw = function(text) {
986                 // If we are going to print newlines, truncate trailing
987                 // whitespace, as the newlines will represent the space.
988                 if (this.newlines > 0) {
989                     text = rtrim(text);
990                 }
992                 if (text && text !== '') {
993                     if (text.length > 1 && text.charAt(text.length - 1) === '\n') {
994                         // unformatted tags can grab newlines as their last character
995                         this.output.push(text.slice(0, -1));
996                         this.print_newline(false, this.output);
997                     } else {
998                         this.output.push(text);
999                     }
1000                 }
1002                 for (var n = 0; n < this.newlines; n++) {
1003                     this.print_newline(n > 0, this.output);
1004                 }
1005                 this.newlines = 0;
1006             };
1008             this.indent = function() {
1009                 this.indent_level++;
1010             };
1012             this.unindent = function() {
1013                 if (this.indent_level > 0) {
1014                     this.indent_level--;
1015                 }
1016             };
1017         };
1018         return this;
1019     }
1021     /*_____________________--------------------_____________________*/
1023     this.beautify = function() {
1024         multi_parser = new Parser(); //wrapping functions Parser
1025         multi_parser.printer(html_source, indent_character, indent_size, wrap_line_length, brace_style); //initialize starting values
1026         while (true) {
1027             var t = multi_parser.get_token();
1028             multi_parser.token_text = t[0];
1029             multi_parser.token_type = t[1];
1031             if (multi_parser.token_type === 'TK_EOF') {
1032                 break;
1033             }
1035             switch (multi_parser.token_type) {
1036                 case 'TK_TAG_START':
1037                     multi_parser.print_newline(false, multi_parser.output);
1038                     multi_parser.print_token(multi_parser.token_text);
1039                     if (multi_parser.indent_content) {
1040                         if ((multi_parser.indent_body_inner_html || !multi_parser.token_text.match(/<body(?:.*)>/)) &&
1041                             (multi_parser.indent_head_inner_html || !multi_parser.token_text.match(/<head(?:.*)>/))) {
1043                             multi_parser.indent();
1044                         }
1046                         multi_parser.indent_content = false;
1047                     }
1048                     multi_parser.current_mode = 'CONTENT';
1049                     break;
1050                 case 'TK_TAG_STYLE':
1051                 case 'TK_TAG_SCRIPT':
1052                     multi_parser.print_newline(false, multi_parser.output);
1053                     multi_parser.print_token(multi_parser.token_text);
1054                     multi_parser.current_mode = 'CONTENT';
1055                     break;
1056                 case 'TK_TAG_END':
1057                     //Print new line only if the tag has no content and has child
1058                     if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
1059                         var tag_name = (multi_parser.token_text.match(/\w+/) || [])[0];
1060                         var tag_extracted_from_last_output = null;
1061                         if (multi_parser.output.length) {
1062                             tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length - 1].match(/(?:<|{{#)\s*(\w+)/);
1063                         }
1064                         if (tag_extracted_from_last_output === null ||
1065                             (tag_extracted_from_last_output[1] !== tag_name && !multi_parser.Utils.in_array(tag_extracted_from_last_output[1], unformatted))) {
1066                             multi_parser.print_newline(false, multi_parser.output);
1067                         }
1068                     }
1069                     multi_parser.print_token(multi_parser.token_text);
1070                     multi_parser.current_mode = 'CONTENT';
1071                     break;
1072                 case 'TK_TAG_SINGLE':
1073                     // Don't add a newline before elements that should remain unformatted.
1074                     var tag_check = multi_parser.token_text.match(/^\s*<([a-z-]+)/i);
1075                     if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)) {
1076                         multi_parser.print_newline(false, multi_parser.output);
1077                     }
1078                     multi_parser.print_token(multi_parser.token_text);
1079                     multi_parser.current_mode = 'CONTENT';
1080                     break;
1081                 case 'TK_TAG_HANDLEBARS_ELSE':
1082                     // Don't add a newline if opening {{#if}} tag is on the current line
1083                     var foundIfOnCurrentLine = false;
1084                     for (var lastCheckedOutput = multi_parser.output.length - 1; lastCheckedOutput >= 0; lastCheckedOutput--) {
1085                         if (multi_parser.output[lastCheckedOutput] === '\n') {
1086                             break;
1087                         } else {
1088                             if (multi_parser.output[lastCheckedOutput].match(/{{#if/)) {
1089                                 foundIfOnCurrentLine = true;
1090                                 break;
1091                             }
1092                         }
1093                     }
1094                     if (!foundIfOnCurrentLine) {
1095                         multi_parser.print_newline(false, multi_parser.output);
1096                     }
1097                     multi_parser.print_token(multi_parser.token_text);
1098                     if (multi_parser.indent_content) {
1099                         multi_parser.indent();
1100                         multi_parser.indent_content = false;
1101                     }
1102                     multi_parser.current_mode = 'CONTENT';
1103                     break;
1104                 case 'TK_TAG_HANDLEBARS_COMMENT':
1105                     multi_parser.print_token(multi_parser.token_text);
1106                     multi_parser.current_mode = 'TAG';
1107                     break;
1108                 case 'TK_CONTENT':
1109                     multi_parser.print_token(multi_parser.token_text);
1110                     multi_parser.current_mode = 'TAG';
1111                     break;
1112                 case 'TK_STYLE':
1113                 case 'TK_SCRIPT':
1114                     if (multi_parser.token_text !== '') {
1115                         multi_parser.print_newline(false, multi_parser.output);
1116                         var text = multi_parser.token_text,
1117                             _beautifier,
1118                             script_indent_level = 1;
1119                         if (multi_parser.token_type === 'TK_SCRIPT') {
1120                             _beautifier = typeof js_beautify === 'function' && js_beautify;
1121                         } else if (multi_parser.token_type === 'TK_STYLE') {
1122                             _beautifier = typeof css_beautify === 'function' && css_beautify;
1123                         }
1125                         if (options.indent_scripts === "keep") {
1126                             script_indent_level = 0;
1127                         } else if (options.indent_scripts === "separate") {
1128                             script_indent_level = -multi_parser.indent_level;
1129                         }
1131                         var indentation = multi_parser.get_full_indent(script_indent_level);
1132                         if (_beautifier) {
1134                             // call the Beautifier if avaliable
1135                             var Child_options = function() {
1136                                 this.eol = '\n';
1137                             };
1138                             Child_options.prototype = options;
1139                             var child_options = new Child_options();
1140                             text = _beautifier(text.replace(/^\s*/, indentation), child_options);
1141                         } else {
1142                             // simply indent the string otherwise
1143                             var white = text.match(/^\s*/)[0];
1144                             var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
1145                             var reindent = multi_parser.get_full_indent(script_indent_level - _level);
1146                             text = text.replace(/^\s*/, indentation)
1147                                 .replace(/\r\n|\r|\n/g, '\n' + reindent)
1148                                 .replace(/\s+$/, '');
1149                         }
1150                         if (text) {
1151                             multi_parser.print_token_raw(text);
1152                             multi_parser.print_newline(true, multi_parser.output);
1153                         }
1154                     }
1155                     multi_parser.current_mode = 'TAG';
1156                     break;
1157                 default:
1158                     // We should not be getting here but we don't want to drop input on the floor
1159                     // Just output the text and move on
1160                     if (multi_parser.token_text !== '') {
1161                         multi_parser.print_token(multi_parser.token_text);
1162                     }
1163                     break;
1164             }
1165             multi_parser.last_token = multi_parser.token_type;
1166             multi_parser.last_text = multi_parser.token_text;
1167         }
1168         var sweet_code = multi_parser.output.join('').replace(/[\r\n\t ]+$/, '');
1170         // establish end_with_newline
1171         if (end_with_newline) {
1172             sweet_code += '\n';
1173         }
1175         if (eol !== '\n') {
1176             sweet_code = sweet_code.replace(/[\n]/g, eol);
1177         }
1179         return sweet_code;
1180     };
1183 module.exports.Beautifier = Beautifier;
1186 /***/ }),
1187 /* 1 */
1188 /***/ (function(module, exports) {
1190 /* jshint curly: false */
1191 // This section of code is taken from acorn.
1192 //
1193 // Acorn was written by Marijn Haverbeke and released under an MIT
1194 // license. The Unicode regexps (for identifiers and whitespace) were
1195 // taken from [Esprima](http://esprima.org) by Ariya Hidayat.
1196 //
1197 // Git repositories for Acorn are available at
1198 //
1199 //     http://marijnhaverbeke.nl/git/acorn
1200 //     https://github.com/marijnh/acorn.git
1202 // ## Character categories
1204 // Big ugly regular expressions that match characters in the
1205 // whitespace, identifier, and identifier-start categories. These
1206 // are only applied when a character is found to actually have a
1207 // code point above 128.
1209 var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; // jshint ignore:line
1210 var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
1211 var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
1212 var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
1213 var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
1215 // Whether a single character denotes a newline.
1217 exports.newline = /[\n\r\u2028\u2029]/;
1219 // Matches a whole line break (where CRLF is considered a single
1220 // line break). Used to count lines.
1222 // in javascript, these two differ
1223 // in python they are the same, different methods are called on them
1224 exports.lineBreak = new RegExp('\r\n|' + exports.newline.source);
1225 exports.allLineBreaks = new RegExp(exports.lineBreak.source, 'g');
1228 // Test whether a given character code starts an identifier.
1230 exports.isIdentifierStart = function(code) {
1231     // permit $ (36) and @ (64). @ is used in ES7 decorators.
1232     if (code < 65) return code === 36 || code === 64;
1233     // 65 through 91 are uppercase letters.
1234     if (code < 91) return true;
1235     // permit _ (95).
1236     if (code < 97) return code === 95;
1237     // 97 through 123 are lowercase letters.
1238     if (code < 123) return true;
1239     return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
1240 };
1242 // Test whether a given character is part of an identifier.
1244 exports.isIdentifierChar = function(code) {
1245     if (code < 48) return code === 36;
1246     if (code < 58) return true;
1247     if (code < 65) return false;
1248     if (code < 91) return true;
1249     if (code < 97) return code === 95;
1250     if (code < 123) return true;
1251     return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
1252 };
1255 /***/ }),
1256 /* 2 */
1257 /***/ (function(module, exports) {
1259 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
1260 /*
1262     The MIT License (MIT)
1264     Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
1266     Permission is hereby granted, free of charge, to any person
1267     obtaining a copy of this software and associated documentation files
1268     (the "Software"), to deal in the Software without restriction,
1269     including without limitation the rights to use, copy, modify, merge,
1270     publish, distribute, sublicense, and/or sell copies of the Software,
1271     and to permit persons to whom the Software is furnished to do so,
1272     subject to the following conditions:
1274     The above copyright notice and this permission notice shall be
1275     included in all copies or substantial portions of the Software.
1277     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1278     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1279     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1280     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1281     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1282     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1283     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1284     SOFTWARE.
1285 */
1287 function mergeOpts(allOptions, targetType) {
1288     var finalOpts = {};
1289     var name;
1291     for (name in allOptions) {
1292         if (name !== targetType) {
1293             finalOpts[name] = allOptions[name];
1294         }
1295     }
1297     //merge in the per type settings for the targetType
1298     if (targetType in allOptions) {
1299         for (name in allOptions[targetType]) {
1300             finalOpts[name] = allOptions[targetType][name];
1301         }
1302     }
1303     return finalOpts;
1306 module.exports.mergeOpts = mergeOpts;
1309 /***/ }),
1310 /* 3 */
1311 /***/ (function(module, exports, __webpack_require__) {
1313 /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
1314 /*
1316     The MIT License (MIT)
1318     Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
1320     Permission is hereby granted, free of charge, to any person
1321     obtaining a copy of this software and associated documentation files
1322     (the "Software"), to deal in the Software without restriction,
1323     including without limitation the rights to use, copy, modify, merge,
1324     publish, distribute, sublicense, and/or sell copies of the Software,
1325     and to permit persons to whom the Software is furnished to do so,
1326     subject to the following conditions:
1328     The above copyright notice and this permission notice shall be
1329     included in all copies or substantial portions of the Software.
1331     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1332     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1333     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1334     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1335     BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1336     ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1337     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1338     SOFTWARE.
1339 */
1341 var Beautifier = __webpack_require__(0).Beautifier;
1343 function style_html(html_source, options, js_beautify, css_beautify) {
1344     var beautifier = new Beautifier(html_source, options, js_beautify, css_beautify);
1345     return beautifier.beautify();
1348 module.exports = style_html;
1350 /***/ })
1351 /******/ ]);
1352 var style_html = legacy_beautify_html;
1353 /* Footer */
1354 if (typeof define === "function" && define.amd) {
1355     // Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
1356     define(["require", "./beautify", "./beautify-css"], function(requireamd) {
1357         var js_beautify = requireamd("./beautify");
1358         var css_beautify = requireamd("./beautify-css");
1360         return {
1361             html_beautify: function(html_source, options) {
1362                 return style_html(html_source, options, js_beautify.js_beautify, css_beautify.css_beautify);
1363             }
1364         };
1365     });
1366 } else if (typeof exports !== "undefined") {
1367     // Add support for CommonJS. Just put this file somewhere on your require.paths
1368     // and you will be able to `var html_beautify = require("beautify").html_beautify`.
1369     var js_beautify = require('./beautify.js');
1370     var css_beautify = require('./beautify-css.js');
1372     exports.html_beautify = function(html_source, options) {
1373         return style_html(html_source, options, js_beautify.js_beautify, css_beautify.css_beautify);
1374     };
1375 } else if (typeof window !== "undefined") {
1376     // If we're running a web page and don't have either of the above, add our one global
1377     window.html_beautify = function(html_source, options) {
1378         return style_html(html_source, options, window.js_beautify, window.css_beautify);
1379     };
1380 } else if (typeof global !== "undefined") {
1381     // If we don't even have window, try global.
1382     global.html_beautify = function(html_source, options) {
1383         return style_html(html_source, options, global.js_beautify, global.css_beautify);
1384     };
1387 }());