js-beautify 1.9.1 → 1.10.0

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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,30 @@
1
1
  # Changelog
2
+ ## v1.10.0
3
+
4
+ ### Description
5
+ # Description
6
+ * Added `templating` setting to control when template languages are recognized. All languages are off by default in Javascript and on by default in HTML.
7
+ * Thanks to @HanabishiRecca, @averydev, @kalbasit, @asteinha for contributions
8
+
9
+ https://github.com/beautify-web/js-beautify/compare/v1.9.1...v1.10.0
10
+
11
+
12
+
13
+ ### Closed Issues
14
+ * beautifying scss selector with colon in it adds space ([#1667](https://github.com/beautify-web/js-beautify/issues/1667))
15
+ * Javascript multiline comments duplicates ([#1663](https://github.com/beautify-web/js-beautify/issues/1663))
16
+ * Tokenizer crashes if the input terminates with a dot character. ([#1658](https://github.com/beautify-web/js-beautify/issues/1658))
17
+ * stop reformatting valid css \\! into invalid \\ ! ([#1656](https://github.com/beautify-web/js-beautify/pull/1656))
18
+ * wrong indent for unclosed <? - need to support disabling templating ([#1647](https://github.com/beautify-web/js-beautify/issues/1647))
19
+ * Beautify inserts space before exclamation mark in comment <!-- in css <style> ([#1641](https://github.com/beautify-web/js-beautify/issues/1641))
20
+ * 'less' mixins parameter formatting problem ([#1582](https://github.com/beautify-web/js-beautify/issues/1582))
21
+ * Change css tests to use 4 space indenting instead of tabs ([#1527](https://github.com/beautify-web/js-beautify/issues/1527))
22
+ * Braces after case get pushed onto new line ([#1357](https://github.com/beautify-web/js-beautify/issues/1357))
23
+ * Extra space in pseudo-elements and pseudo-classes selectors ([#1233](https://github.com/beautify-web/js-beautify/issues/1233))
24
+ * LESS formatting - mixins with multiple variables ([#1018](https://github.com/beautify-web/js-beautify/issues/1018))
25
+ * Bug in less format ([#842](https://github.com/beautify-web/js-beautify/issues/842))
26
+
27
+
2
28
  ## v1.9.1
3
29
 
4
30
  ### Description
package/README.md CHANGED
@@ -61,17 +61,17 @@ JS Beautifier is hosted on two CDN services: [cdnjs](https://cdnjs.com/libraries
61
61
 
62
62
  To pull the latest version from one of these services include one set of the script tags below in your document:
63
63
  ```html
64
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.1/beautify.js"></script>
65
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.1/beautify-css.js"></script>
66
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.1/beautify-html.js"></script>
64
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.0/beautify.js"></script>
65
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.0/beautify-css.js"></script>
66
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.0/beautify-html.js"></script>
67
67
 
68
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.1/beautify.min.js"></script>
69
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.1/beautify-css.min.js"></script>
70
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.1/beautify-html.min.js"></script>
68
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.0/beautify.min.js"></script>
69
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.0/beautify-css.min.js"></script>
70
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.0/beautify-html.min.js"></script>
71
71
 
72
- <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.9.1/js/lib/beautify.js"></script>
73
- <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.9.1/js/lib/beautify-css.js"></script>
74
- <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.9.1/js/lib/beautify-html.js"></script>
72
+ <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.10.0/js/lib/beautify.js"></script>
73
+ <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.10.0/js/lib/beautify-css.js"></script>
74
+ <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.10.0/js/lib/beautify-html.js"></script>
75
75
  ```
76
76
 
77
77
  Older versions are available by changing the version number.
@@ -191,6 +191,7 @@ Beautifier Options:
191
191
  -C, --comma-first Put commas at the beginning of new line instead of end
192
192
  -O, --operator-position Set operator position (before-newline|after-newline|preserve-newline) [before-newline]
193
193
  --indent-empty-lines Keep indentation on empty lines
194
+ --templating List of templating languages (auto,django,erb,handlebars,php) ["auto"] auto = none in JavaScript, all in html
194
195
  ```
195
196
 
196
197
  Which correspond to the underscored option keys for both library interfaces
@@ -221,7 +222,8 @@ Which correspond to the underscored option keys for both library interfaces
221
222
  "e4x": false,
222
223
  "comma_first": false,
223
224
  "operator_position": "before-newline",
224
- "indent_empty_lines": false
225
+ "indent_empty_lines": false,
226
+ "templating": ["auto"]
225
227
  }
226
228
  ```
227
229
 
@@ -342,15 +344,16 @@ HTML Beautifier Options:
342
344
  --indent_scripts Sets indent level inside script tags ("normal", "keep", "separate")
343
345
  --unformatted_content_delimiter Keep text content together between this string [""]
344
346
  --indent-empty-lines Keep indentation on empty lines
347
+ --templating List of templating languages (auto,none,django,erb,handlebars,php) ["auto"] auto = none in JavaScript, all in html
345
348
  ```
346
349
 
347
350
  ## Directives
348
351
 
349
- Directives let you control the behavior of the Beautifier from within your source files. Directives are placed in comments inside the file. Directives are in the format `/* beautify {name}:{value} */` in CSS and JavaScript. In HTML they are formatted as `<!-- beautify {name}:{value} -->`.
352
+ Directives let you control the behavior of the Beautifier from within your source files. Directives are placed in comments inside the file. Directives are in the format `/* beautify {name}:{value} */` in CSS and JavaScript. In HTML they are formatted as `<!-- beautify {name}:{value} -->`.
350
353
 
351
354
  ### Ignore directive
352
355
 
353
- The `ignore` directive makes the beautifier completely ignore part of a file, treating it as literal text that is not parsed.
356
+ The `ignore` directive makes the beautifier completely ignore part of a file, treating it as literal text that is not parsed.
354
357
  The input below will remain unchanged after beautification:
355
358
 
356
359
  ```js
@@ -361,9 +364,9 @@ var a = 1;
361
364
  /* beautify ignore:end */
362
365
  ```
363
366
 
364
- ### Preserve directive
367
+ ### Preserve directive
365
368
 
366
- NOTE: this directive only works in HTML and JavaScript, not CSS.
369
+ NOTE: this directive only works in HTML and JavaScript, not CSS.
367
370
 
368
371
  The `preserve` directive makes the Beautifier parse and then keep the existing formatting of a section of code.
369
372
 
@@ -396,4 +399,4 @@ Thanks also to Jason Diamond, Patrick Hof, Nochum Sossonko, Andreas Schneider, D
396
399
  Vasilevsky, Vital Batmanov, Ron Baldwin, Gabriel Harrison, Chris J. Shull,
397
400
  Mathias Bynens, Vittorio Gambaletta and others.
398
401
 
399
- (README.md: js-beautify@1.9.1)
402
+ (README.md: js-beautify@1.10.0)
@@ -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);
@@ -2365,6 +2380,11 @@ function Options(options, merge_child_field) {
2365
2380
  this.wrap_line_length = this._get_number('wrap_line_length', this._get_number('max_char'));
2366
2381
 
2367
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']);
2368
2388
  }
2369
2389
 
2370
2390
  Options.prototype._get_array = function(name, default_value) {
@@ -2602,10 +2622,8 @@ var Tokenizer = function(input_string, options) {
2602
2622
  /\u2028\u2029/.source);
2603
2623
 
2604
2624
  var pattern_reader = new Pattern(this._input);
2605
- var templatable = new TemplatablePattern(this._input);
2606
- templatable = templatable.disable('handlebars');
2607
- templatable = templatable.disable('django');
2608
-
2625
+ var templatable = new TemplatablePattern(this._input)
2626
+ .read_options(this._options);
2609
2627
 
2610
2628
  this.__patterns = {
2611
2629
  template: templatable,
@@ -2774,7 +2792,7 @@ Tokenizer.prototype._read_non_javascript = function(c) {
2774
2792
 
2775
2793
  this._input.back();
2776
2794
 
2777
- } else if (c === '<') {
2795
+ } else if (c === '<' && this._is_first_token()) {
2778
2796
  resulting_string = this.__patterns.html_comment_start.read();
2779
2797
  if (resulting_string) {
2780
2798
  while (this._input.hasNext() && !this._input.testChar(acorn.newline)) {
@@ -3858,6 +3876,15 @@ TemplatablePattern.prototype.disable = function(language) {
3858
3876
  return result;
3859
3877
  };
3860
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
+
3861
3888
  TemplatablePattern.prototype.exclude = function(language) {
3862
3889
  var result = this._create();
3863
3890
  result._excluded[language] = true;
@@ -4215,6 +4242,9 @@ Beautifier.prototype.beautify = function() {
4215
4242
  isAfterSpace = whitespace !== '';
4216
4243
  previous_ch = topCharacter;
4217
4244
  this._ch = this._input.next();
4245
+ if (this._ch === '\\' && this._input.hasNext()) {
4246
+ this._ch += this._input.next();
4247
+ }
4218
4248
  topCharacter = this._ch;
4219
4249
 
4220
4250
  if (!this._ch) {
@@ -4347,7 +4377,7 @@ Beautifier.prototype.beautify = function() {
4347
4377
  }
4348
4378
  }
4349
4379
  } else if (this._ch === ":") {
4350
- 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) {
4351
4381
  // 'property: value' delimiter
4352
4382
  // which could be in a conditional group query
4353
4383
  this.print_string(':');
@@ -4379,51 +4409,66 @@ Beautifier.prototype.beautify = function() {
4379
4409
  this.print_string(this._ch + this.eatString(this._ch));
4380
4410
  this.eatWhitespace(true);
4381
4411
  } else if (this._ch === ';') {
4382
- if (insidePropertyValue) {
4383
- this.outdent();
4384
- insidePropertyValue = false;
4385
- }
4386
- insideAtExtend = false;
4387
- insideAtImport = false;
4388
- this.print_string(this._ch);
4389
- this.eatWhitespace(true);
4390
-
4391
- // This maintains single line comments on the same
4392
- // line. Block comments are also affected, but
4393
- // a new line is always output before one inside
4394
- // that section
4395
- if (this._input.peek() !== '/') {
4396
- 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;
4397
4433
  }
4398
4434
  } else if (this._ch === '(') { // may be a url
4399
4435
  if (this._input.lookBack("url")) {
4400
4436
  this.print_string(this._ch);
4401
4437
  this.eatWhitespace();
4438
+ parenLevel++;
4439
+ this.indent();
4402
4440
  this._ch = this._input.next();
4403
4441
  if (this._ch === ')' || this._ch === '"' || this._ch === '\'') {
4404
4442
  this._input.back();
4405
- parenLevel++;
4406
4443
  } else if (this._ch) {
4407
4444
  this.print_string(this._ch + this.eatString(')'));
4445
+ if (parenLevel) {
4446
+ parenLevel--;
4447
+ this.outdent();
4448
+ }
4408
4449
  }
4409
4450
  } else {
4410
- parenLevel++;
4411
4451
  this.preserveSingleSpace(isAfterSpace);
4412
4452
  this.print_string(this._ch);
4413
4453
  this.eatWhitespace();
4454
+ parenLevel++;
4455
+ this.indent();
4414
4456
  }
4415
4457
  } else if (this._ch === ')') {
4458
+ if (parenLevel) {
4459
+ parenLevel--;
4460
+ this.outdent();
4461
+ }
4416
4462
  this.print_string(this._ch);
4417
- parenLevel--;
4418
4463
  } else if (this._ch === ',') {
4419
4464
  this.print_string(this._ch);
4420
4465
  this.eatWhitespace(true);
4421
- if (this._options.selector_separator_newline && !insidePropertyValue && parenLevel < 1 && !insideAtImport) {
4466
+ if (this._options.selector_separator_newline && !insidePropertyValue && parenLevel === 0 && !insideAtImport) {
4422
4467
  this._output.add_new_line();
4423
4468
  } else {
4424
4469
  this._output.space_before_token = true;
4425
4470
  }
4426
- } else if ((this._ch === '>' || this._ch === '+' || this._ch === '~') && !insidePropertyValue && parenLevel < 1) {
4471
+ } else if ((this._ch === '>' || this._ch === '+' || this._ch === '~') && !insidePropertyValue && parenLevel === 0) {
4427
4472
  //handle combinator spacing
4428
4473
  if (this._options.space_around_combinator) {
4429
4474
  this._output.space_before_token = true;
@@ -4448,7 +4493,7 @@ Beautifier.prototype.beautify = function() {
4448
4493
  if (whitespaceChar.test(this._ch)) {
4449
4494
  this._ch = '';
4450
4495
  }
4451
- } else if (this._ch === '!') { // !important
4496
+ } else if (this._ch === '!' && !this._input.lookBack("\\")) { // !important
4452
4497
  this.print_string(' ');
4453
4498
  this.print_string(this._ch);
4454
4499
  } else {
@@ -5016,10 +5061,12 @@ Beautifier.prototype._handle_text = function(printer, raw_token, last_tag_token)
5016
5061
  Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token, last_tag_token) {
5017
5062
  var local = this;
5018
5063
  if (raw_token.text !== '') {
5019
- printer.print_newline(false);
5064
+
5020
5065
  var text = raw_token.text,
5021
5066
  _beautifier,
5022
- script_indent_level = 1;
5067
+ script_indent_level = 1,
5068
+ pre = '',
5069
+ post = '';
5023
5070
  if (last_tag_token.custom_beautifier_name === 'javascript' && typeof this._js_beautify === 'function') {
5024
5071
  _beautifier = this._js_beautify;
5025
5072
  } else if (last_tag_token.custom_beautifier_name === 'css' && typeof this._css_beautify === 'function') {
@@ -5031,7 +5078,6 @@ Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token,
5031
5078
  };
5032
5079
  }
5033
5080
 
5034
-
5035
5081
  if (this._options.indent_scripts === "keep") {
5036
5082
  script_indent_level = 0;
5037
5083
  } else if (this._options.indent_scripts === "separate") {
@@ -5044,24 +5090,67 @@ Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token,
5044
5090
  // we'll be adding one back after the text but before the containing tag.
5045
5091
  text = text.replace(/\n[ \t]*$/, '');
5046
5092
 
5047
- 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);
5048
5097
 
5049
- // call the Beautifier if avaliable
5050
- var Child_options = function() {
5051
- this.eol = '\n';
5052
- };
5053
- Child_options.prototype = this._options.raw_options;
5054
- var child_options = new Child_options();
5055
- text = _beautifier(indentation + text, child_options);
5056
- } else {
5057
- // simply indent the string otherwise
5058
- var white = raw_token.whitespace_before;
5059
- if (white) {
5060
- 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];
5108
+ }
5109
+
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
+ }
5061
5121
  }
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
+ }
5062
5140
 
5063
- text = indentation + text.replace(/\n/g, '\n' + indentation);
5141
+ text = indentation + text.replace(/\n/g, '\n' + indentation);
5142
+ }
5064
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);
5065
5154
  if (text) {
5066
5155
  raw_token.text = text;
5067
5156
  raw_token.whitespace_before = '';
@@ -5409,6 +5498,9 @@ var BaseOptions = __webpack_require__(7).Options;
5409
5498
 
5410
5499
  function Options(options) {
5411
5500
  BaseOptions.call(this, options, 'html');
5501
+ if (this.templating.length === 1 && this.templating[0] === 'auto') {
5502
+ this.templating = ['django', 'erb', 'handlebars', 'php'];
5503
+ }
5412
5504
 
5413
5505
  this.indent_inner_html = this._get_boolean('indent_inner_html');
5414
5506
  this.indent_body_inner_html = this._get_boolean('indent_body_inner_html', true);
@@ -5456,6 +5548,7 @@ function Options(options) {
5456
5548
  ]);
5457
5549
  this.unformatted_content_delimiter = this._get_characters('unformatted_content_delimiter');
5458
5550
  this.indent_scripts = this._get_selection('indent_scripts', ['normal', 'keep', 'separate']);
5551
+
5459
5552
  }
5460
5553
  Options.prototype = new BaseOptions();
5461
5554
 
@@ -5527,7 +5620,7 @@ var Tokenizer = function(input_string, options) {
5527
5620
 
5528
5621
  // Words end at whitespace or when a tag starts
5529
5622
  // if we are indenting handlebars, they are considered tags
5530
- var templatable_reader = new TemplatablePattern(this._input);
5623
+ var templatable_reader = new TemplatablePattern(this._input).read_options(this._options);
5531
5624
  var pattern_reader = new Pattern(this._input);
5532
5625
 
5533
5626
  this.__patterns = {
@@ -5593,7 +5686,7 @@ Tokenizer.prototype._get_next_token = function(previous_token, open_token) { //
5593
5686
 
5594
5687
  token = token || this._read_open_handlebars(c, open_token);
5595
5688
  token = token || this._read_attribute(c, previous_token, open_token);
5596
- token = token || this._read_raw_content(previous_token, open_token);
5689
+ token = token || this._read_raw_content(c, previous_token, open_token);
5597
5690
  token = token || this._read_close(c, open_token);
5598
5691
  token = token || this._read_content_word(c);
5599
5692
  token = token || this._read_comment(c);
@@ -5729,19 +5822,27 @@ Tokenizer.prototype._is_content_unformatted = function(tag_name) {
5729
5822
  // script and style tags should always be read as unformatted content
5730
5823
  // finally content_unformatted and unformatted element contents are unformatted
5731
5824
  return this._options.void_elements.indexOf(tag_name) === -1 &&
5732
- (tag_name === 'script' || tag_name === 'style' ||
5733
- this._options.content_unformatted.indexOf(tag_name) !== -1 ||
5825
+ (this._options.content_unformatted.indexOf(tag_name) !== -1 ||
5734
5826
  this._options.unformatted.indexOf(tag_name) !== -1);
5735
5827
  };
5736
5828
 
5737
5829
 
5738
- Tokenizer.prototype._read_raw_content = function(previous_token, open_token) { // jshint unused:false
5830
+ Tokenizer.prototype._read_raw_content = function(c, previous_token, open_token) { // jshint unused:false
5739
5831
  var resulting_string = '';
5740
5832
  if (open_token && open_token.text[0] === '{') {
5741
5833
  resulting_string = this.__patterns.handlebars_raw_close.read();
5742
5834
  } else if (previous_token.type === TOKEN.TAG_CLOSE && (previous_token.opened.text[0] === '<')) {
5743
5835
  var tag_name = previous_token.opened.text.substr(1).toLowerCase();
5744
- if (this._is_content_unformatted(tag_name)) {
5836
+ if (tag_name === 'script' || tag_name === 'style') {
5837
+ // Script and style tags are allowed to have comments wrapping their content
5838
+ // or just have regular content.
5839
+ var token = this._read_comment(c);
5840
+ if (token) {
5841
+ token.type = TOKEN.TEXT;
5842
+ return token;
5843
+ }
5844
+ resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
5845
+ } else if (this._is_content_unformatted(tag_name)) {
5745
5846
  resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
5746
5847
  }
5747
5848
  }