js-beautify 1.10.2 → 1.13.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,63 @@
1
1
  # Changelog
2
+ ## v1.13.0
3
+
4
+ ### Description
5
+ This release truly fixes the python cssbeautifier installation and updates cssbeautifier cli to use the same general code as jsbeautifier.
6
+
7
+ Also, as of this release Node.js 8.x is no longer guaranteed to work. Node.js 8.x LTS reached end-of-life in January 2020.
8
+ Parts of our test infrastructure no longer support Node.js 8.x. The js-beautifier should still run on Node.js 8.x, but it is not part of the CI system and so not guaranteed to work.
9
+
10
+
11
+ ### Closed Issues
12
+ * (internal) Refactor python cssbeautifier to reuse jsbeautifier CLI methods ([#1832](https://github.com/beautify-web/js-beautify/pull/1832))
13
+ * (internal) Switch from node-static to serve ([#1831](https://github.com/beautify-web/js-beautify/pull/1831))
14
+ * Fixed pip install cssbeautifier ([#1830](https://github.com/beautify-web/js-beautify/pull/1830))
15
+
16
+
17
+ ## v1.12.0
18
+
19
+ ### Description
20
+
21
+
22
+ ### Closed Issues
23
+ * Python jsbeautifier fails for special chars ([#1809](https://github.com/beautify-web/js-beautify/issues/1809))
24
+ * pip install cssbeautifier fails ([#1808](https://github.com/beautify-web/js-beautify/issues/1808))
25
+ * Add expand brace-style option to css beautifier ([#1796](https://github.com/beautify-web/js-beautify/pull/1796))
26
+ * Support nullish-coalescing ([#1794](https://github.com/beautify-web/js-beautify/issues/1794))
27
+ * Upgrade ga.js to analytics.js ([#1777](https://github.com/beautify-web/js-beautify/issues/1777))
28
+ * Newline rule not working with css-like files ([#1776](https://github.com/beautify-web/js-beautify/issues/1776))
29
+ * no new line after self closing tag ([#1718](https://github.com/beautify-web/js-beautify/issues/1718))
30
+ * HTML format, no break after <label>? ([#1365](https://github.com/beautify-web/js-beautify/issues/1365))
31
+ * Does this extension still supports applying Allman style to CSS? ([#1353](https://github.com/beautify-web/js-beautify/issues/1353))
32
+ * Add brace_style option for CSS ([#1259](https://github.com/beautify-web/js-beautify/issues/1259))
33
+
34
+
35
+ ## v1.11.0
36
+
37
+ ### Description
38
+
39
+
40
+ ### Closed Issues
41
+ * Please bump mkdirp to fix mkdirp@0.5.1 vulnerability ([#1768](https://github.com/beautify-web/js-beautify/issues/1768))
42
+ * Incorrect indentation of Handlebars inline partials ([#1756](https://github.com/beautify-web/js-beautify/issues/1756))
43
+ * Support optional-chaining ([#1727](https://github.com/beautify-web/js-beautify/issues/1727))
44
+ * Please support es module ([#1706](https://github.com/beautify-web/js-beautify/issues/1706))
45
+ * Support new js proposals: optional-chaining & pipeline-operator ([#1530](https://github.com/beautify-web/js-beautify/issues/1530))
46
+ * Optional <p> closing not implemented ([#1503](https://github.com/beautify-web/js-beautify/issues/1503))
47
+
48
+
49
+ ## v1.10.3
50
+
51
+ ### Description
52
+
53
+
54
+ ### Closed Issues
55
+ * Unquoted href causes wrong indentation ([#1736](https://github.com/beautify-web/js-beautify/issues/1736))
56
+ * Broken private fields in classes (JS) ([#1734](https://github.com/beautify-web/js-beautify/issues/1734))
57
+ * Fix for python 2.7 and cli parameters ([#1712](https://github.com/beautify-web/js-beautify/pull/1712))
58
+ * Search (ctrl+f) works only in view field in CodeMirror ([#1696](https://github.com/beautify-web/js-beautify/issues/1696))
59
+
60
+
2
61
  ## v1.10.2
3
62
 
4
63
  ### 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.10.2/beautify.js"></script>
65
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.2/beautify-css.js"></script>
66
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.2/beautify-html.js"></script>
64
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify.js"></script>
65
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify-css.js"></script>
66
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify-html.js"></script>
67
67
 
68
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.2/beautify.min.js"></script>
69
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.2/beautify-css.min.js"></script>
70
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.2/beautify-html.min.js"></script>
68
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify.min.js"></script>
69
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify-css.min.js"></script>
70
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.13.0/beautify-html.min.js"></script>
71
71
 
72
- <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.10.2/js/lib/beautify.js"></script>
73
- <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.10.2/js/lib/beautify-css.js"></script>
74
- <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.10.2/js/lib/beautify-html.js"></script>
72
+ <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.13.0/js/lib/beautify.js"></script>
73
+ <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.13.0/js/lib/beautify-css.js"></script>
74
+ <script src="https://cdn.rawgit.com/beautify-web/js-beautify/v1.13.0/js/lib/beautify-html.js"></script>
75
75
  ```
76
76
 
77
77
  Older versions are available by changing the version number.
@@ -85,7 +85,11 @@ To install the Python version of the beautifier:
85
85
  ```bash
86
86
  $ pip install jsbeautifier
87
87
  ```
88
+ Unlike the JavaScript version, the Python version can only reformat JavaScript. It does not work against HTML or CSS files, but you can install _css-beautify_ for CSS:
88
89
 
90
+ ```bash
91
+ $ pip install cssbeautifier
92
+ ```
89
93
 
90
94
  # Usage
91
95
  You can beautify javascript using JS Beautifier in your web browser, or on the command-line using node.js or python.
@@ -318,6 +322,7 @@ CSS Beautifier Options:
318
322
  -t, --indent-with-tabs Indent with tabs, overrides -s and -c
319
323
  -e, --eol Character(s) to use as line terminators. (default newline - "\\n")
320
324
  -n, --end-with-newline End output with newline
325
+ -b, --brace-style [collapse|expand] ["collapse"]
321
326
  -L, --selector-separator-newline Add a newline between multiple selectors
322
327
  -N, --newline-between-rules Add a newline between CSS rules
323
328
  --indent-empty-lines Keep indentation on empty lines
@@ -399,4 +404,4 @@ Thanks also to Jason Diamond, Patrick Hof, Nochum Sossonko, Andreas Schneider, D
399
404
  Vasilevsky, Vital Batmanov, Ron Baldwin, Gabriel Harrison, Chris J. Shull,
400
405
  Mathias Bynens, Vittorio Gambaletta and others.
401
406
 
402
- (README.md: js-beautify@1.10.2)
407
+ (README.md: js-beautify@1.13.0)
@@ -2167,11 +2167,11 @@ module.exports.Token = Token;
2167
2167
 
2168
2168
  // acorn used char codes to squeeze the last bit of performance out
2169
2169
  // Beautifier is okay without that, so we're using regex
2170
- // permit $ (36) and @ (64). @ is used in ES7 decorators.
2170
+ // permit # (23), $ (36), and @ (64). @ is used in ES7 decorators.
2171
2171
  // 65 through 91 are uppercase letters.
2172
2172
  // permit _ (95).
2173
2173
  // 97 through 123 are lowercase letters.
2174
- var baseASCIIidentifierStartChars = "\\x24\\x40\\x41-\\x5a\\x5f\\x61-\\x7a";
2174
+ var baseASCIIidentifierStartChars = "\\x23\\x24\\x40\\x41-\\x5a\\x5f\\x61-\\x7a";
2175
2175
 
2176
2176
  // inside an identifier @ is not allowed but 0-9 are.
2177
2177
  var baseASCIIidentifierChars = "\\x24\\x30-\\x39\\x41-\\x5a\\x5f\\x61-\\x7a";
@@ -2589,7 +2589,7 @@ var dot_pattern = /[^\d\.]/;
2589
2589
 
2590
2590
  var positionable_operators = (
2591
2591
  ">>> === !== " +
2592
- "<< && >= ** != == <= >> || " +
2592
+ "<< && >= ** != == <= >> || ?? |> " +
2593
2593
  "< / - + > : & % ? ^ | *").split(' ');
2594
2594
 
2595
2595
  // IMPORTANT: this must be sorted longest to shortest or tokenizing many not work.
@@ -2597,10 +2597,12 @@ var positionable_operators = (
2597
2597
  var punct =
2598
2598
  ">>>= " +
2599
2599
  "... >>= <<= === >>> !== **= " +
2600
- "=> ^= :: /= << <= == && -= >= >> != -- += ** || ++ %= &= *= |= " +
2600
+ "=> ^= :: /= << <= == && -= >= >> != -- += ** || ?? ++ %= &= *= |= |> " +
2601
2601
  "= ! ? > < : / ^ - + * & % ~ |";
2602
2602
 
2603
2603
  punct = punct.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&");
2604
+ // ?. but not if followed by a number
2605
+ punct = '\\?\\.(?!\\d) ' + punct;
2604
2606
  punct = punct.replace(/ /g, '|');
2605
2607
 
2606
2608
  var punct_pattern = new RegExp(punct);
@@ -2677,13 +2679,13 @@ Tokenizer.prototype._get_next_token = function(previous_token, open_token) { //
2677
2679
  return this._create_token(TOKEN.EOF, '');
2678
2680
  }
2679
2681
 
2682
+ token = token || this._read_non_javascript(c);
2680
2683
  token = token || this._read_string(c);
2681
2684
  token = token || this._read_word(previous_token);
2682
2685
  token = token || this._read_singles(c);
2683
2686
  token = token || this._read_comment(c);
2684
2687
  token = token || this._read_regexp(c, previous_token);
2685
2688
  token = token || this._read_xml(c, previous_token);
2686
- token = token || this._read_non_javascript(c);
2687
2689
  token = token || this._read_punctuation();
2688
2690
  token = token || this._create_token(TOKEN.UNKNOWN, this._input.next());
2689
2691
 
@@ -2742,6 +2744,8 @@ Tokenizer.prototype._read_punctuation = function() {
2742
2744
  if (resulting_string !== '') {
2743
2745
  if (resulting_string === '=') {
2744
2746
  return this._create_token(TOKEN.EQUALS, resulting_string);
2747
+ } else if (resulting_string === '?.') {
2748
+ return this._create_token(TOKEN.DOT, resulting_string);
2745
2749
  } else {
2746
2750
  return this._create_token(TOKEN.OPERATOR, resulting_string);
2747
2751
  }
@@ -4334,23 +4338,34 @@ Beautifier.prototype.beautify = function() {
4334
4338
  insidePropertyValue = false;
4335
4339
  this.outdent();
4336
4340
  }
4337
- this.indent();
4338
- this._output.space_before_token = true;
4339
- this.print_string(this._ch);
4340
4341
 
4341
4342
  // when entering conditional groups, only rulesets are allowed
4342
4343
  if (enteringConditionalGroup) {
4343
4344
  enteringConditionalGroup = false;
4344
- insideRule = (this._indentLevel > this._nestedLevel);
4345
+ insideRule = (this._indentLevel >= this._nestedLevel);
4345
4346
  } else {
4346
4347
  // otherwise, declarations are also allowed
4347
- insideRule = (this._indentLevel >= this._nestedLevel);
4348
+ insideRule = (this._indentLevel >= this._nestedLevel - 1);
4348
4349
  }
4349
4350
  if (this._options.newline_between_rules && insideRule) {
4350
4351
  if (this._output.previous_line && this._output.previous_line.item(-1) !== '{') {
4351
4352
  this._output.ensure_empty_line_above('/', ',');
4352
4353
  }
4353
4354
  }
4355
+
4356
+ this._output.space_before_token = true;
4357
+
4358
+ // The difference in print_string and indent order is necessary to indent the '{' correctly
4359
+ if (this._options.brace_style === 'expand') {
4360
+ this._output.add_new_line();
4361
+ this.print_string(this._ch);
4362
+ this.indent();
4363
+ this._output.set_indent(this._indentLevel);
4364
+ } else {
4365
+ this.indent();
4366
+ this.print_string(this._ch);
4367
+ }
4368
+
4354
4369
  this.eatWhitespace(true);
4355
4370
  this._output.add_new_line();
4356
4371
  } else if (this._ch === '}') {
@@ -4558,6 +4573,16 @@ function Options(options) {
4558
4573
  var space_around_selector_separator = this._get_boolean('space_around_selector_separator');
4559
4574
  this.space_around_combinator = this._get_boolean('space_around_combinator') || space_around_selector_separator;
4560
4575
 
4576
+ var brace_style_split = this._get_selection_list('brace_style', ['collapse', 'expand', 'end-expand', 'none', 'preserve-inline']);
4577
+ this.brace_style = 'collapse';
4578
+ for (var bs = 0; bs < brace_style_split.length; bs++) {
4579
+ if (brace_style_split[bs] !== 'expand') {
4580
+ // default to collapse, as only collapse|expand is implemented for now
4581
+ this.brace_style = 'collapse';
4582
+ } else {
4583
+ this.brace_style = brace_style_split[bs];
4584
+ }
4585
+ }
4561
4586
  }
4562
4587
  Options.prototype = new BaseOptions();
4563
4588
 
@@ -4781,7 +4806,7 @@ var get_custom_beautifier_name = function(tag_check, raw_token) {
4781
4806
  // For those without a type attribute use default;
4782
4807
  if (typeAttribute.search('text/css') > -1) {
4783
4808
  result = 'css';
4784
- } else if (typeAttribute.search(/(text|application|dojo)\/(x-)?(javascript|ecmascript|jscript|livescript|(ld\+)?json|method|aspect)/) > -1) {
4809
+ } else if (typeAttribute.search(/module|((text|application|dojo)\/(x-)?(javascript|ecmascript|jscript|livescript|(ld\+)?json|method|aspect))/) > -1) {
4785
4810
  result = 'javascript';
4786
4811
  } else if (typeAttribute.search(/(text|application|dojo)\/(x-)?(html)/) > -1) {
4787
4812
  result = 'html';
@@ -5168,10 +5193,12 @@ Beautifier.prototype._handle_tag_open = function(printer, raw_token, last_tag_to
5168
5193
  var parser_token = this._get_tag_open_token(raw_token);
5169
5194
 
5170
5195
  if ((last_tag_token.is_unformatted || last_tag_token.is_content_unformatted) &&
5196
+ !last_tag_token.is_empty_element &&
5171
5197
  raw_token.type === TOKEN.TAG_OPEN && raw_token.text.indexOf('</') === 0) {
5172
5198
  // End element tags for unformatted or content_unformatted elements
5173
5199
  // are printed raw to keep any newlines inside them exactly the same.
5174
5200
  printer.add_raw_token(raw_token);
5201
+ parser_token.start_tag_token = this._tag_stack.try_pop(parser_token.tag_name);
5175
5202
  } else {
5176
5203
  printer.traverse_whitespace(raw_token);
5177
5204
  this._set_tag_position(printer, raw_token, parser_token, last_tag_token, last_token);
@@ -5227,8 +5254,13 @@ var TagOpenParserToken = function(parent, raw_token) {
5227
5254
  tag_check_match = raw_token.text.match(/^<([^\s>]*)/);
5228
5255
  this.tag_check = tag_check_match ? tag_check_match[1] : '';
5229
5256
  } else {
5230
- tag_check_match = raw_token.text.match(/^{{[#\^]?([^\s}]+)/);
5257
+ tag_check_match = raw_token.text.match(/^{{(?:[\^]|#\*?)?([^\s}]+)/);
5231
5258
  this.tag_check = tag_check_match ? tag_check_match[1] : '';
5259
+
5260
+ // handle "{{#> myPartial}}
5261
+ if (raw_token.text === '{{#>' && this.tag_check === '>' && raw_token.next !== null) {
5262
+ this.tag_check = raw_token.next.text;
5263
+ }
5232
5264
  }
5233
5265
  this.tag_check = this.tag_check.toLowerCase();
5234
5266
 
@@ -5275,12 +5307,8 @@ Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_tok
5275
5307
  // and do an ending needed
5276
5308
  if (this._do_optional_end_element(parser_token)) {
5277
5309
  if (!parser_token.is_inline_element) {
5278
- if (parser_token.parent) {
5279
- parser_token.parent.multiline_content = true;
5280
- }
5281
5310
  printer.print_newline(false);
5282
5311
  }
5283
-
5284
5312
  }
5285
5313
 
5286
5314
  this._tag_stack.record_tag(parser_token); //push it on the tag stack
@@ -5317,21 +5345,28 @@ Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_tok
5317
5345
  if (parser_token.tag_name === '!--' && last_token.type === TOKEN.TAG_CLOSE &&
5318
5346
  last_tag_token.is_end_tag && parser_token.text.indexOf('\n') === -1) {
5319
5347
  //Do nothing. Leave comments on same line.
5320
- } else if (!parser_token.is_inline_element && !parser_token.is_unformatted) {
5321
- printer.print_newline(false);
5322
- }
5323
- } else if (parser_token.is_unformatted || parser_token.is_content_unformatted) {
5324
- if (!parser_token.is_inline_element && !parser_token.is_unformatted) {
5325
- printer.print_newline(false);
5348
+ } else {
5349
+ if (!(parser_token.is_inline_element || parser_token.is_unformatted)) {
5350
+ printer.print_newline(false);
5351
+ }
5352
+ this._calcluate_parent_multiline(printer, parser_token);
5326
5353
  }
5327
5354
  } else if (parser_token.is_end_tag) { //this tag is a double tag so check for tag-ending
5328
- if ((parser_token.start_tag_token && parser_token.start_tag_token.multiline_content) ||
5329
- !(parser_token.is_inline_element ||
5330
- (last_tag_token.is_inline_element) ||
5331
- (last_token.type === TOKEN.TAG_CLOSE &&
5332
- parser_token.start_tag_token === last_tag_token) ||
5333
- (last_token.type === 'TK_CONTENT')
5334
- )) {
5355
+ var do_end_expand = false;
5356
+
5357
+ // deciding whether a block is multiline should not be this hard
5358
+ do_end_expand = parser_token.start_tag_token && parser_token.start_tag_token.multiline_content;
5359
+ do_end_expand = do_end_expand || (!parser_token.is_inline_element &&
5360
+ !(last_tag_token.is_inline_element || last_tag_token.is_unformatted) &&
5361
+ !(last_token.type === TOKEN.TAG_CLOSE && parser_token.start_tag_token === last_tag_token) &&
5362
+ last_token.type !== 'TK_CONTENT'
5363
+ );
5364
+
5365
+ if (parser_token.is_content_unformatted || parser_token.is_unformatted) {
5366
+ do_end_expand = false;
5367
+ }
5368
+
5369
+ if (do_end_expand) {
5335
5370
  printer.print_newline(false);
5336
5371
  }
5337
5372
  } else { // it's a start-tag
@@ -5347,17 +5382,25 @@ Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_tok
5347
5382
  }
5348
5383
  }
5349
5384
 
5350
- if (!parser_token.is_inline_element && last_token.type !== 'TK_CONTENT') {
5351
- if (parser_token.parent) {
5352
- parser_token.parent.multiline_content = true;
5353
- }
5385
+ if (!(parser_token.is_inline_element || parser_token.is_unformatted) &&
5386
+ (last_token.type !== 'TK_CONTENT' || parser_token.is_content_unformatted)) {
5354
5387
  printer.print_newline(false);
5355
5388
  }
5389
+
5390
+ this._calcluate_parent_multiline(printer, parser_token);
5391
+ }
5392
+ };
5393
+
5394
+ Beautifier.prototype._calcluate_parent_multiline = function(printer, parser_token) {
5395
+ if (parser_token.parent && printer._output.just_added_newline() &&
5396
+ !((parser_token.is_inline_element || parser_token.is_unformatted) && parser_token.parent.is_inline_element)) {
5397
+ parser_token.parent.multiline_content = true;
5356
5398
  }
5357
5399
  };
5358
5400
 
5359
5401
  //To be used for <p> tag special case:
5360
- //var p_closers = ['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'];
5402
+ var p_closers = ['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'];
5403
+ var p_parent_excludes = ['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video'];
5361
5404
 
5362
5405
  Beautifier.prototype._do_optional_end_element = function(parser_token) {
5363
5406
  var result = null;
@@ -5368,7 +5411,9 @@ Beautifier.prototype._do_optional_end_element = function(parser_token) {
5368
5411
  if (parser_token.is_empty_element || !parser_token.is_start_tag || !parser_token.parent) {
5369
5412
  return;
5370
5413
 
5371
- } else if (parser_token.tag_name === 'body') {
5414
+ }
5415
+
5416
+ if (parser_token.tag_name === 'body') {
5372
5417
  // A head element’s end tag may be omitted if the head element is not immediately followed by a space character or a comment.
5373
5418
  result = result || this._tag_stack.try_pop('head');
5374
5419
 
@@ -5385,11 +5430,16 @@ Beautifier.prototype._do_optional_end_element = function(parser_token) {
5385
5430
  result = result || this._tag_stack.try_pop('dt', ['dl']);
5386
5431
  result = result || this._tag_stack.try_pop('dd', ['dl']);
5387
5432
 
5388
- //} else if (p_closers.indexOf(parser_token.tag_name) !== -1) {
5389
- //TODO: THIS IS A BUG FARM. We are not putting this into 1.8.0 as it is likely to blow up.
5390
- //A p element’s end tag may be omitted if the p element is immediately followed by an address, article, aside, blockquote, details, div, dl, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hr, main, nav, ol, p, pre, section, table, or ul element, or if there is no more content in the parent element and the parent element is an HTML element that is not an a, audio, del, ins, map, noscript, or video element, or an autonomous custom element.
5391
- //result = result || this._tag_stack.try_pop('p', ['body']);
5392
5433
 
5434
+ } else if (parser_token.parent.tag_name === 'p' && p_closers.indexOf(parser_token.tag_name) !== -1) {
5435
+ // IMPORTANT: this else-if works because p_closers has no overlap with any other element we look for in this method
5436
+ // check for the parent element is an HTML element that is not an <a>, <audio>, <del>, <ins>, <map>, <noscript>, or <video> element, or an autonomous custom element.
5437
+ // To do this right, this needs to be coded as an inclusion of the inverse of the exclusion above.
5438
+ // But to start with (if we ignore "autonomous custom elements") the exclusion would be fine.
5439
+ var p_parent = parser_token.parent.parent;
5440
+ if (!p_parent || p_parent_excludes.indexOf(p_parent.tag_name) === -1) {
5441
+ result = result || this._tag_stack.try_pop('p');
5442
+ }
5393
5443
  } else if (parser_token.tag_name === 'rp' || parser_token.tag_name === 'rt') {
5394
5444
  // An rt element’s end tag may be omitted if the rt element is immediately followed by an rt or rp element, or if there is no more content in the parent element.
5395
5445
  // An rp element’s end tag may be omitted if the rp element is immediately followed by an rt or rp element, or if there is no more content in the parent element.
@@ -5630,7 +5680,7 @@ var Tokenizer = function(input_string, options) {
5630
5680
  word: templatable_reader.until(/[\n\r\t <]/),
5631
5681
  single_quote: templatable_reader.until_after(/'/),
5632
5682
  double_quote: templatable_reader.until_after(/"/),
5633
- attribute: templatable_reader.until(/[\n\r\t =\/>]/),
5683
+ attribute: templatable_reader.until(/[\n\r\t =>]|\/>/),
5634
5684
  element_name: templatable_reader.until(/[\n\r\t >\/]/),
5635
5685
 
5636
5686
  handlebars_comment: pattern_reader.starting_with(/{{!--/).until_after(/--}}/),
@@ -5689,8 +5739,8 @@ Tokenizer.prototype._get_next_token = function(previous_token, open_token) { //
5689
5739
 
5690
5740
  token = token || this._read_open_handlebars(c, open_token);
5691
5741
  token = token || this._read_attribute(c, previous_token, open_token);
5692
- token = token || this._read_raw_content(c, previous_token, open_token);
5693
5742
  token = token || this._read_close(c, open_token);
5743
+ token = token || this._read_raw_content(c, previous_token, open_token);
5694
5744
  token = token || this._read_content_word(c);
5695
5745
  token = token || this._read_comment_or_cdata(c);
5696
5746
  token = token || this._read_processing(c);
@@ -5853,7 +5903,9 @@ Tokenizer.prototype._read_raw_content = function(c, previous_token, open_token)
5853
5903
  var resulting_string = '';
5854
5904
  if (open_token && open_token.text[0] === '{') {
5855
5905
  resulting_string = this.__patterns.handlebars_raw_close.read();
5856
- } else if (previous_token.type === TOKEN.TAG_CLOSE && (previous_token.opened.text[0] === '<')) {
5906
+ } else if (previous_token.type === TOKEN.TAG_CLOSE &&
5907
+ previous_token.opened.text[0] === '<' && previous_token.text[0] !== '/') {
5908
+ // ^^ empty tag has no content
5857
5909
  var tag_name = previous_token.opened.text.substr(1).toLowerCase();
5858
5910
  if (tag_name === 'script' || tag_name === 'style') {
5859
5911
  // Script and style tags are allowed to have comments wrapping their content
@@ -5865,6 +5917,7 @@ Tokenizer.prototype._read_raw_content = function(c, previous_token, open_token)
5865
5917
  }
5866
5918
  resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
5867
5919
  } else if (this._is_content_unformatted(tag_name)) {
5920
+
5868
5921
  resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
5869
5922
  }
5870
5923
  }