js-beautify 1.9.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -601,7 +601,7 @@ Beautifier.prototype.print_token_line_indentation = function(current_token) {
601
601
  }
602
602
  };
603
603
 
604
- Beautifier.prototype.print_token = function(current_token, printable_token) {
604
+ Beautifier.prototype.print_token = function(current_token) {
605
605
  if (this._output.raw) {
606
606
  this._output.add_raw_token(current_token);
607
607
  return;
@@ -627,10 +627,9 @@ Beautifier.prototype.print_token = function(current_token, printable_token) {
627
627
  }
628
628
  }
629
629
 
630
- printable_token = printable_token || current_token.text;
631
630
  this.print_token_line_indentation(current_token);
632
631
  this._output.non_breaking_space = true;
633
- this._output.add_token(printable_token);
632
+ this._output.add_token(current_token.text);
634
633
  if (this._output.previous_token_wrapped) {
635
634
  this._flags.multiline_frame = true;
636
635
  }
@@ -884,6 +883,8 @@ Beautifier.prototype.handle_start_block = function(current_token) {
884
883
  if (this._flags.last_word === 'switch' && this._flags.last_token.type === TOKEN.END_EXPR) {
885
884
  this.set_mode(MODE.BlockStatement);
886
885
  this._flags.in_case_statement = true;
886
+ } else if (this._flags.case_body) {
887
+ this.set_mode(MODE.BlockStatement);
887
888
  } else if (second_token && (
888
889
  (in_array(second_token.text, [':', ',']) && in_array(next_token.type, [TOKEN.STRING, TOKEN.WORD, TOKEN.RESERVED])) ||
889
890
  (in_array(next_token.text, ['get', 'set', '...']) && in_array(second_token.type, [TOKEN.WORD, TOKEN.RESERVED]))
@@ -1069,11 +1070,12 @@ Beautifier.prototype.handle_word = function(current_token) {
1069
1070
 
1070
1071
  if (this._flags.in_case_statement && reserved_array(current_token, ['case', 'default'])) {
1071
1072
  this.print_newline();
1072
- if (this._flags.case_body || this._options.jslint_happy) {
1073
+ if (this._flags.last_token.type !== TOKEN.END_BLOCK && (this._flags.case_body || this._options.jslint_happy)) {
1073
1074
  // switch cases following one another
1074
1075
  this.deindent();
1075
- this._flags.case_body = false;
1076
1076
  }
1077
+ this._flags.case_body = false;
1078
+
1077
1079
  this.print_token(current_token);
1078
1080
  this._flags.in_case = true;
1079
1081
  return;
@@ -1371,11 +1373,16 @@ Beautifier.prototype.handle_operator = function(current_token) {
1371
1373
  }
1372
1374
 
1373
1375
  if (current_token.text === ':' && this._flags.in_case) {
1374
- this._flags.case_body = true;
1375
- this.indent();
1376
1376
  this.print_token(current_token);
1377
- this.print_newline();
1377
+
1378
1378
  this._flags.in_case = false;
1379
+ this._flags.case_body = true;
1380
+ if (this._tokens.peek().type !== TOKEN.START_BLOCK) {
1381
+ this.indent();
1382
+ this.print_newline();
1383
+ } else {
1384
+ this._output.space_before_token = true;
1385
+ }
1379
1386
  return;
1380
1387
  }
1381
1388
 
@@ -1538,8 +1545,12 @@ Beautifier.prototype.handle_block_comment = function(current_token, preserve_sta
1538
1545
  this.print_token(current_token);
1539
1546
  this._output.space_before_token = true;
1540
1547
  return;
1548
+ } else {
1549
+ this.print_block_commment(current_token, preserve_statement_flags);
1541
1550
  }
1551
+ };
1542
1552
 
1553
+ Beautifier.prototype.print_block_commment = function(current_token, preserve_statement_flags) {
1543
1554
  var lines = split_linebreaks(current_token.text);
1544
1555
  var j; // iterator for this case
1545
1556
  var javadoc = false;
@@ -1551,7 +1562,8 @@ Beautifier.prototype.handle_block_comment = function(current_token, preserve_sta
1551
1562
  this.print_newline(false, preserve_statement_flags);
1552
1563
 
1553
1564
  // first line always indented
1554
- this.print_token(current_token, lines[0]);
1565
+ this.print_token_line_indentation(current_token);
1566
+ this._output.add_token(lines[0]);
1555
1567
  this.print_newline(false, preserve_statement_flags);
1556
1568
 
1557
1569
 
@@ -1567,10 +1579,12 @@ Beautifier.prototype.handle_block_comment = function(current_token, preserve_sta
1567
1579
  for (j = 0; j < lines.length; j++) {
1568
1580
  if (javadoc) {
1569
1581
  // javadoc: reformat and re-indent
1570
- this.print_token(current_token, ltrim(lines[j]));
1582
+ this.print_token_line_indentation(current_token);
1583
+ this._output.add_token(ltrim(lines[j]));
1571
1584
  } else if (starless && lines[j]) {
1572
1585
  // starless: re-indent non-empty content, avoiding trim
1573
- this.print_token(current_token, lines[j].substring(lastIndentLength));
1586
+ this.print_token_line_indentation(current_token);
1587
+ this._output.add_token(lines[j].substring(lastIndentLength));
1574
1588
  } else {
1575
1589
  // normal comments output raw
1576
1590
  this._output.current_line.set_indent(-1);
@@ -1585,6 +1599,7 @@ Beautifier.prototype.handle_block_comment = function(current_token, preserve_sta
1585
1599
  }
1586
1600
  };
1587
1601
 
1602
+
1588
1603
  Beautifier.prototype.handle_comment = function(current_token, preserve_statement_flags) {
1589
1604
  if (current_token.newlines) {
1590
1605
  this.print_newline(false, preserve_statement_flags);
@@ -1808,7 +1823,11 @@ OutputLine.prototype.trim = function() {
1808
1823
 
1809
1824
  OutputLine.prototype.toString = function() {
1810
1825
  var result = '';
1811
- if (!this.is_empty()) {
1826
+ if (this.is_empty()) {
1827
+ if (this.__parent.indent_empty_lines) {
1828
+ result = this.__parent.get_indent_string(this.__indent_count);
1829
+ }
1830
+ } else {
1812
1831
  result = this.__parent.get_indent_string(this.__indent_count, this.__alignment_count);
1813
1832
  result += this.__items.join('');
1814
1833
  }
@@ -1885,6 +1904,7 @@ function Output(options, baseIndentString) {
1885
1904
  this._end_with_newline = options.end_with_newline;
1886
1905
  this.indent_size = options.indent_size;
1887
1906
  this.wrap_line_length = options.wrap_line_length;
1907
+ this.indent_empty_lines = options.indent_empty_lines;
1888
1908
  this.__lines = [];
1889
1909
  this.previous_line = null;
1890
1910
  this.current_line = null;
@@ -2359,6 +2379,12 @@ function Options(options, merge_child_field) {
2359
2379
  // Backwards compat with 1.3.x
2360
2380
  this.wrap_line_length = this._get_number('wrap_line_length', this._get_number('max_char'));
2361
2381
 
2382
+ this.indent_empty_lines = this._get_boolean('indent_empty_lines');
2383
+
2384
+ // valid templating languages ['django', 'erb', 'handlebars', 'php']
2385
+ // For now, 'auto' = all off for javascript, all on for html (and inline javascript).
2386
+ // other values ignored
2387
+ this.templating = this._get_selection_list('templating', ['auto', 'none', 'django', 'erb', 'handlebars', 'php'], ['auto']);
2362
2388
  }
2363
2389
 
2364
2390
  Options.prototype._get_array = function(name, default_value) {
@@ -2596,10 +2622,8 @@ var Tokenizer = function(input_string, options) {
2596
2622
  /\u2028\u2029/.source);
2597
2623
 
2598
2624
  var pattern_reader = new Pattern(this._input);
2599
- var templatable = new TemplatablePattern(this._input);
2600
- templatable = templatable.disable('handlebars');
2601
- templatable = templatable.disable('django');
2602
-
2625
+ var templatable = new TemplatablePattern(this._input)
2626
+ .read_options(this._options);
2603
2627
 
2604
2628
  this.__patterns = {
2605
2629
  template: templatable,
@@ -2768,7 +2792,7 @@ Tokenizer.prototype._read_non_javascript = function(c) {
2768
2792
 
2769
2793
  this._input.back();
2770
2794
 
2771
- } else if (c === '<') {
2795
+ } else if (c === '<' && this._is_first_token()) {
2772
2796
  resulting_string = this.__patterns.html_comment_start.read();
2773
2797
  if (resulting_string) {
2774
2798
  while (this._input.hasNext() && !this._input.testChar(acorn.newline)) {
@@ -3852,6 +3876,15 @@ TemplatablePattern.prototype.disable = function(language) {
3852
3876
  return result;
3853
3877
  };
3854
3878
 
3879
+ TemplatablePattern.prototype.read_options = function(options) {
3880
+ var result = this._create();
3881
+ for (var language in template_names) {
3882
+ result._disabled[language] = options.templating.indexOf(language) === -1;
3883
+ }
3884
+ result._update();
3885
+ return result;
3886
+ };
3887
+
3855
3888
  TemplatablePattern.prototype.exclude = function(language) {
3856
3889
  var result = this._create();
3857
3890
  result._excluded[language] = true;
@@ -4209,6 +4242,9 @@ Beautifier.prototype.beautify = function() {
4209
4242
  isAfterSpace = whitespace !== '';
4210
4243
  previous_ch = topCharacter;
4211
4244
  this._ch = this._input.next();
4245
+ if (this._ch === '\\' && this._input.hasNext()) {
4246
+ this._ch += this._input.next();
4247
+ }
4212
4248
  topCharacter = this._ch;
4213
4249
 
4214
4250
  if (!this._ch) {
@@ -4341,7 +4377,7 @@ Beautifier.prototype.beautify = function() {
4341
4377
  }
4342
4378
  }
4343
4379
  } else if (this._ch === ":") {
4344
- if ((insideRule || enteringConditionalGroup) && !(this._input.lookBack("&") || this.foundNestedPseudoClass()) && !this._input.lookBack("(") && !insideAtExtend) {
4380
+ if ((insideRule || enteringConditionalGroup) && !(this._input.lookBack("&") || this.foundNestedPseudoClass()) && !this._input.lookBack("(") && !insideAtExtend && parenLevel === 0) {
4345
4381
  // 'property: value' delimiter
4346
4382
  // which could be in a conditional group query
4347
4383
  this.print_string(':');
@@ -4373,51 +4409,66 @@ Beautifier.prototype.beautify = function() {
4373
4409
  this.print_string(this._ch + this.eatString(this._ch));
4374
4410
  this.eatWhitespace(true);
4375
4411
  } else if (this._ch === ';') {
4376
- if (insidePropertyValue) {
4377
- this.outdent();
4378
- insidePropertyValue = false;
4379
- }
4380
- insideAtExtend = false;
4381
- insideAtImport = false;
4382
- this.print_string(this._ch);
4383
- this.eatWhitespace(true);
4384
-
4385
- // This maintains single line comments on the same
4386
- // line. Block comments are also affected, but
4387
- // a new line is always output before one inside
4388
- // that section
4389
- if (this._input.peek() !== '/') {
4390
- this._output.add_new_line();
4412
+ if (parenLevel === 0) {
4413
+ if (insidePropertyValue) {
4414
+ this.outdent();
4415
+ insidePropertyValue = false;
4416
+ }
4417
+ insideAtExtend = false;
4418
+ insideAtImport = false;
4419
+ this.print_string(this._ch);
4420
+ this.eatWhitespace(true);
4421
+
4422
+ // This maintains single line comments on the same
4423
+ // line. Block comments are also affected, but
4424
+ // a new line is always output before one inside
4425
+ // that section
4426
+ if (this._input.peek() !== '/') {
4427
+ this._output.add_new_line();
4428
+ }
4429
+ } else {
4430
+ this.print_string(this._ch);
4431
+ this.eatWhitespace(true);
4432
+ this._output.space_before_token = true;
4391
4433
  }
4392
4434
  } else if (this._ch === '(') { // may be a url
4393
4435
  if (this._input.lookBack("url")) {
4394
4436
  this.print_string(this._ch);
4395
4437
  this.eatWhitespace();
4438
+ parenLevel++;
4439
+ this.indent();
4396
4440
  this._ch = this._input.next();
4397
4441
  if (this._ch === ')' || this._ch === '"' || this._ch === '\'') {
4398
4442
  this._input.back();
4399
- parenLevel++;
4400
4443
  } else if (this._ch) {
4401
4444
  this.print_string(this._ch + this.eatString(')'));
4445
+ if (parenLevel) {
4446
+ parenLevel--;
4447
+ this.outdent();
4448
+ }
4402
4449
  }
4403
4450
  } else {
4404
- parenLevel++;
4405
4451
  this.preserveSingleSpace(isAfterSpace);
4406
4452
  this.print_string(this._ch);
4407
4453
  this.eatWhitespace();
4454
+ parenLevel++;
4455
+ this.indent();
4408
4456
  }
4409
4457
  } else if (this._ch === ')') {
4458
+ if (parenLevel) {
4459
+ parenLevel--;
4460
+ this.outdent();
4461
+ }
4410
4462
  this.print_string(this._ch);
4411
- parenLevel--;
4412
4463
  } else if (this._ch === ',') {
4413
4464
  this.print_string(this._ch);
4414
4465
  this.eatWhitespace(true);
4415
- if (this._options.selector_separator_newline && !insidePropertyValue && parenLevel < 1 && !insideAtImport) {
4466
+ if (this._options.selector_separator_newline && !insidePropertyValue && parenLevel === 0 && !insideAtImport) {
4416
4467
  this._output.add_new_line();
4417
4468
  } else {
4418
4469
  this._output.space_before_token = true;
4419
4470
  }
4420
- } else if ((this._ch === '>' || this._ch === '+' || this._ch === '~') && !insidePropertyValue && parenLevel < 1) {
4471
+ } else if ((this._ch === '>' || this._ch === '+' || this._ch === '~') && !insidePropertyValue && parenLevel === 0) {
4421
4472
  //handle combinator spacing
4422
4473
  if (this._options.space_around_combinator) {
4423
4474
  this._output.space_before_token = true;
@@ -4442,7 +4493,7 @@ Beautifier.prototype.beautify = function() {
4442
4493
  if (whitespaceChar.test(this._ch)) {
4443
4494
  this._ch = '';
4444
4495
  }
4445
- } else if (this._ch === '!') { // !important
4496
+ } else if (this._ch === '!' && !this._input.lookBack("\\")) { // !important
4446
4497
  this.print_string(' ');
4447
4498
  this.print_string(this._ch);
4448
4499
  } else {
@@ -5010,10 +5061,12 @@ Beautifier.prototype._handle_text = function(printer, raw_token, last_tag_token)
5010
5061
  Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token, last_tag_token) {
5011
5062
  var local = this;
5012
5063
  if (raw_token.text !== '') {
5013
- printer.print_newline(false);
5064
+
5014
5065
  var text = raw_token.text,
5015
5066
  _beautifier,
5016
- script_indent_level = 1;
5067
+ script_indent_level = 1,
5068
+ pre = '',
5069
+ post = '';
5017
5070
  if (last_tag_token.custom_beautifier_name === 'javascript' && typeof this._js_beautify === 'function') {
5018
5071
  _beautifier = this._js_beautify;
5019
5072
  } else if (last_tag_token.custom_beautifier_name === 'css' && typeof this._css_beautify === 'function') {
@@ -5025,7 +5078,6 @@ Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token,
5025
5078
  };
5026
5079
  }
5027
5080
 
5028
-
5029
5081
  if (this._options.indent_scripts === "keep") {
5030
5082
  script_indent_level = 0;
5031
5083
  } else if (this._options.indent_scripts === "separate") {
@@ -5038,24 +5090,67 @@ Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token,
5038
5090
  // we'll be adding one back after the text but before the containing tag.
5039
5091
  text = text.replace(/\n[ \t]*$/, '');
5040
5092
 
5041
- if (_beautifier) {
5093
+ // Handle the case where content is wrapped in a comment or cdata.
5094
+ if (last_tag_token.custom_beautifier_name !== 'html' &&
5095
+ text[0] === '<' && text.match(/^(<!--|<!\[CDATA\[)/)) {
5096
+ var matched = /^(<!--[^\n]*|<!\[CDATA\[)(\n?)([ \t\n]*)([\s\S]*)(-->|]]>)$/.exec(text);
5042
5097
 
5043
- // call the Beautifier if avaliable
5044
- var Child_options = function() {
5045
- this.eol = '\n';
5046
- };
5047
- Child_options.prototype = this._options.raw_options;
5048
- var child_options = new Child_options();
5049
- text = _beautifier(indentation + text, child_options);
5050
- } else {
5051
- // simply indent the string otherwise
5052
- var white = raw_token.whitespace_before;
5053
- if (white) {
5054
- text = text.replace(new RegExp('\n(' + white + ')?', 'g'), '\n');
5098
+ // if we start to wrap but don't finish, print raw
5099
+ if (!matched) {
5100
+ printer.add_raw_token(raw_token);
5101
+ return;
5102
+ }
5103
+
5104
+ pre = indentation + matched[1] + '\n';
5105
+ text = matched[4];
5106
+ if (matched[5]) {
5107
+ post = indentation + matched[5];
5055
5108
  }
5056
5109
 
5057
- text = indentation + text.replace(/\n/g, '\n' + indentation);
5110
+ // if there is at least one empty line at the end of this text, strip it
5111
+ // we'll be adding one back after the text but before the containing tag.
5112
+ text = text.replace(/\n[ \t]*$/, '');
5113
+
5114
+ if (matched[2] || matched[3].indexOf('\n') !== -1) {
5115
+ // if the first line of the non-comment text has spaces
5116
+ // use that as the basis for indenting in null case.
5117
+ matched = matched[3].match(/[ \t]+$/);
5118
+ if (matched) {
5119
+ raw_token.whitespace_before = matched[0];
5120
+ }
5121
+ }
5058
5122
  }
5123
+
5124
+ if (text) {
5125
+ if (_beautifier) {
5126
+
5127
+ // call the Beautifier if avaliable
5128
+ var Child_options = function() {
5129
+ this.eol = '\n';
5130
+ };
5131
+ Child_options.prototype = this._options.raw_options;
5132
+ var child_options = new Child_options();
5133
+ text = _beautifier(indentation + text, child_options);
5134
+ } else {
5135
+ // simply indent the string otherwise
5136
+ var white = raw_token.whitespace_before;
5137
+ if (white) {
5138
+ text = text.replace(new RegExp('\n(' + white + ')?', 'g'), '\n');
5139
+ }
5140
+
5141
+ text = indentation + text.replace(/\n/g, '\n' + indentation);
5142
+ }
5143
+ }
5144
+
5145
+ if (pre) {
5146
+ if (!text) {
5147
+ text = pre + post;
5148
+ } else {
5149
+ text = pre + text + '\n' + post;
5150
+ }
5151
+ }
5152
+
5153
+ printer.print_newline(false);
5059
5154
  if (text) {
5060
5155
  raw_token.text = text;
5061
5156
  raw_token.whitespace_before = '';
@@ -5346,8 +5441,8 @@ Beautifier.prototype._do_optional_end_element = function(parser_token) {
5346
5441
  } else if (parser_token.tag_name === 'th' || parser_token.tag_name === 'td') {
5347
5442
  // 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.
5348
5443
  // 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.
5349
- result = result || this._tag_stack.try_pop('td', ['tr']);
5350
- result = result || this._tag_stack.try_pop('th', ['tr']);
5444
+ result = result || this._tag_stack.try_pop('td', ['table', 'thead', 'tbody', 'tfoot', 'tr']);
5445
+ result = result || this._tag_stack.try_pop('th', ['table', 'thead', 'tbody', 'tfoot', 'tr']);
5351
5446
  }
5352
5447
 
5353
5448
  // Start element omission not handled currently
@@ -5403,6 +5498,9 @@ var BaseOptions = __webpack_require__(7).Options;
5403
5498
 
5404
5499
  function Options(options) {
5405
5500
  BaseOptions.call(this, options, 'html');
5501
+ if (this.templating.length === 1 && this.templating[0] === 'auto') {
5502
+ this.templating = ['django', 'erb', 'handlebars', 'php'];
5503
+ }
5406
5504
 
5407
5505
  this.indent_inner_html = this._get_boolean('indent_inner_html');
5408
5506
  this.indent_body_inner_html = this._get_boolean('indent_body_inner_html', true);
@@ -5450,6 +5548,7 @@ function Options(options) {
5450
5548
  ]);
5451
5549
  this.unformatted_content_delimiter = this._get_characters('unformatted_content_delimiter');
5452
5550
  this.indent_scripts = this._get_selection('indent_scripts', ['normal', 'keep', 'separate']);
5551
+
5453
5552
  }
5454
5553
  Options.prototype = new BaseOptions();
5455
5554
 
@@ -5521,7 +5620,7 @@ var Tokenizer = function(input_string, options) {
5521
5620
 
5522
5621
  // Words end at whitespace or when a tag starts
5523
5622
  // if we are indenting handlebars, they are considered tags
5524
- var templatable_reader = new TemplatablePattern(this._input);
5623
+ var templatable_reader = new TemplatablePattern(this._input).read_options(this._options);
5525
5624
  var pattern_reader = new Pattern(this._input);
5526
5625
 
5527
5626
  this.__patterns = {
@@ -5536,7 +5635,7 @@ var Tokenizer = function(input_string, options) {
5536
5635
  handlebars_open: pattern_reader.until(/[\n\r\t }]/),
5537
5636
  handlebars_raw_close: pattern_reader.until(/}}/),
5538
5637
  comment: pattern_reader.starting_with(/<!--/).until_after(/-->/),
5539
- cdata: pattern_reader.starting_with(/<!\[cdata\[/).until_after(/]]>/),
5638
+ cdata: pattern_reader.starting_with(/<!\[CDATA\[/).until_after(/]]>/),
5540
5639
  // https://en.wikipedia.org/wiki/Conditional_comment
5541
5640
  conditional_comment: pattern_reader.starting_with(/<!\[/).until_after(/]>/),
5542
5641
  processing: pattern_reader.starting_with(/<\?/).until_after(/\?>/)
@@ -5587,27 +5686,27 @@ Tokenizer.prototype._get_next_token = function(previous_token, open_token) { //
5587
5686
 
5588
5687
  token = token || this._read_open_handlebars(c, open_token);
5589
5688
  token = token || this._read_attribute(c, previous_token, open_token);
5590
- token = token || this._read_raw_content(previous_token, open_token);
5689
+ token = token || this._read_raw_content(c, previous_token, open_token);
5591
5690
  token = token || this._read_close(c, open_token);
5592
5691
  token = token || this._read_content_word(c);
5593
- token = token || this._read_comment(c);
5692
+ token = token || this._read_comment_or_cdata(c);
5693
+ token = token || this._read_processing(c);
5594
5694
  token = token || this._read_open(c, open_token);
5595
5695
  token = token || this._create_token(TOKEN.UNKNOWN, this._input.next());
5596
5696
 
5597
5697
  return token;
5598
5698
  };
5599
5699
 
5600
- Tokenizer.prototype._read_comment = function(c) { // jshint unused:false
5700
+ Tokenizer.prototype._read_comment_or_cdata = function(c) { // jshint unused:false
5601
5701
  var token = null;
5602
5702
  var resulting_string = null;
5603
5703
  var directives = null;
5604
5704
 
5605
5705
  if (c === '<') {
5606
5706
  var peek1 = this._input.peek(1);
5607
- //if we're in a comment, do something special
5608
5707
  // We treat all comments as literals, even more than preformatted tags
5609
- // we just look for the appropriate close tag
5610
- if (c === '<' && (peek1 === '!' || peek1 === '?')) {
5708
+ // we only look for the appropriate closing marker
5709
+ if (peek1 === '!') {
5611
5710
  resulting_string = this.__patterns.comment.read();
5612
5711
 
5613
5712
  // only process directive on html comments
@@ -5618,8 +5717,6 @@ Tokenizer.prototype._read_comment = function(c) { // jshint unused:false
5618
5717
  }
5619
5718
  } else {
5620
5719
  resulting_string = this.__patterns.cdata.read();
5621
- resulting_string = resulting_string || this.__patterns.conditional_comment.read();
5622
- resulting_string = resulting_string || this.__patterns.processing.read();
5623
5720
  }
5624
5721
  }
5625
5722
 
@@ -5632,6 +5729,27 @@ Tokenizer.prototype._read_comment = function(c) { // jshint unused:false
5632
5729
  return token;
5633
5730
  };
5634
5731
 
5732
+ Tokenizer.prototype._read_processing = function(c) { // jshint unused:false
5733
+ var token = null;
5734
+ var resulting_string = null;
5735
+ var directives = null;
5736
+
5737
+ if (c === '<') {
5738
+ var peek1 = this._input.peek(1);
5739
+ if (peek1 === '!' || peek1 === '?') {
5740
+ resulting_string = this.__patterns.conditional_comment.read();
5741
+ resulting_string = resulting_string || this.__patterns.processing.read();
5742
+ }
5743
+
5744
+ if (resulting_string) {
5745
+ token = this._create_token(TOKEN.COMMENT, resulting_string);
5746
+ token.directives = directives;
5747
+ }
5748
+ }
5749
+
5750
+ return token;
5751
+ };
5752
+
5635
5753
  Tokenizer.prototype._read_open = function(c, open_token) {
5636
5754
  var resulting_string = null;
5637
5755
  var token = null;
@@ -5723,19 +5841,27 @@ Tokenizer.prototype._is_content_unformatted = function(tag_name) {
5723
5841
  // script and style tags should always be read as unformatted content
5724
5842
  // finally content_unformatted and unformatted element contents are unformatted
5725
5843
  return this._options.void_elements.indexOf(tag_name) === -1 &&
5726
- (tag_name === 'script' || tag_name === 'style' ||
5727
- this._options.content_unformatted.indexOf(tag_name) !== -1 ||
5844
+ (this._options.content_unformatted.indexOf(tag_name) !== -1 ||
5728
5845
  this._options.unformatted.indexOf(tag_name) !== -1);
5729
5846
  };
5730
5847
 
5731
5848
 
5732
- Tokenizer.prototype._read_raw_content = function(previous_token, open_token) { // jshint unused:false
5849
+ Tokenizer.prototype._read_raw_content = function(c, previous_token, open_token) { // jshint unused:false
5733
5850
  var resulting_string = '';
5734
5851
  if (open_token && open_token.text[0] === '{') {
5735
5852
  resulting_string = this.__patterns.handlebars_raw_close.read();
5736
5853
  } else if (previous_token.type === TOKEN.TAG_CLOSE && (previous_token.opened.text[0] === '<')) {
5737
5854
  var tag_name = previous_token.opened.text.substr(1).toLowerCase();
5738
- if (this._is_content_unformatted(tag_name)) {
5855
+ if (tag_name === 'script' || tag_name === 'style') {
5856
+ // Script and style tags are allowed to have comments wrapping their content
5857
+ // or just have regular content.
5858
+ var token = this._read_comment_or_cdata(c);
5859
+ if (token) {
5860
+ token.type = TOKEN.TEXT;
5861
+ return token;
5862
+ }
5863
+ resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
5864
+ } else if (this._is_content_unformatted(tag_name)) {
5739
5865
  resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
5740
5866
  }
5741
5867
  }