Skip to content

Commit

Permalink
Added optional closing of p tags
Browse files Browse the repository at this point in the history
  • Loading branch information
bitwiseman committed Apr 4, 2020
1 parent e00d3b2 commit 35ed0cd
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 14 deletions.
21 changes: 15 additions & 6 deletions js/src/html/beautifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ Beautifier.prototype._handle_tag_open = function(printer, raw_token, last_tag_to
// End element tags for unformatted or content_unformatted elements
// are printed raw to keep any newlines inside them exactly the same.
printer.add_raw_token(raw_token);
parser_token.start_tag_token = this._tag_stack.try_pop(parser_token.tag_name);
} else {
printer.traverse_whitespace(raw_token);
this._set_tag_position(printer, raw_token, parser_token, last_tag_token, last_token);
Expand Down Expand Up @@ -735,7 +736,8 @@ Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_tok
};

//To be used for <p> tag special case:
//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'];
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'];
var p_parent_excludes = ['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video'];

Beautifier.prototype._do_optional_end_element = function(parser_token) {
var result = null;
Expand All @@ -746,7 +748,9 @@ Beautifier.prototype._do_optional_end_element = function(parser_token) {
if (parser_token.is_empty_element || !parser_token.is_start_tag || !parser_token.parent) {
return;

} else if (parser_token.tag_name === 'body') {
}

if (parser_token.tag_name === 'body') {
// A head element’s end tag may be omitted if the head element is not immediately followed by a space character or a comment.
result = result || this._tag_stack.try_pop('head');

Expand All @@ -763,11 +767,16 @@ Beautifier.prototype._do_optional_end_element = function(parser_token) {
result = result || this._tag_stack.try_pop('dt', ['dl']);
result = result || this._tag_stack.try_pop('dd', ['dl']);

//} else if (p_closers.indexOf(parser_token.tag_name) !== -1) {
//TODO: THIS IS A BUG FARM. We are not putting this into 1.8.0 as it is likely to blow up.
//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.
//result = result || this._tag_stack.try_pop('p', ['body']);

} else if (parser_token.parent.tag_name === 'p' && p_closers.indexOf(parser_token.tag_name) !== -1) {
// IMPORTANT: this else-if works because p_closers has no overlap with any other element we look for in this method
// 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.
// To do this right, this needs to be coded as an inclusion of the inverse of the exclusion above.
// But to start with (if we ignore "autonomous custom elements") the exclusion would be fine.
var p_parent = parser_token.parent.parent;
if (!p_parent || p_parent_excludes.indexOf(p_parent.tag_name) === -1) {
result = result || this._tag_stack.try_pop('p');
}
} else if (parser_token.tag_name === 'rp' || parser_token.tag_name === 'rt') {
// 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.
// 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.
Expand Down
29 changes: 25 additions & 4 deletions js/test/generated/beautify-html-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -6664,7 +6664,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
' <optgroup>\n' +
' test content\n' +
' <option>\n' +
' test content\n' +
' <p>test content\n' +
' <option>\n' +
' test content\n' +
'</select>');
Expand Down Expand Up @@ -6724,7 +6724,8 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
' <thead>\n' +
' <tr>\n' +
' <th>Function\n' +
' <th>Control Unit\n' +
' <th>\n' +
' <p>Control Unit\n' +
' <th>Central Station\n' +
' <tbody>\n' +
' <tr>\n' +
Expand Down Expand Up @@ -6794,6 +6795,26 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
' <dt>gh\n' +
' <dt>gh</dt>\n' +
'</dl>');

// P element optional closing tag - #1503
bth(
'<p><p><dl><dt>ef<dt><p>gh</dt><dt>gh</dt></dl><p><h3>headers are outside paragraphs</h3>\n' +
'<p>.<textarea><p><p>.</textarea><textarea><p><p>.</textarea><p>.<p>.</p>',
// -- output --
'<p>\n' +
'<p>\n' +
'<dl>\n' +
' <dt>ef\n' +
' <dt>\n' +
' <p>gh\n' +
' </dt>\n' +
' <dt>gh</dt>\n' +
'</dl>\n' +
'<p>\n' +
'<h3>headers are outside paragraphs</h3>\n' +
'<p>.<textarea><p><p>.</textarea><textarea><p><p>.</textarea>\n' +
'<p>.\n' +
'<p>.</p>');


//============================================================
Expand Down Expand Up @@ -8535,7 +8556,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
' <p>Beautify me</p>\n' +
'</div>\n' +
'<p>\n' +
' <p>But not me</p>\n' +
'<p>But not me</p>\n' +
'</p>');
bth(
'<div><p\n' +
Expand All @@ -8548,7 +8569,7 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
' <p class="beauty-me">Beautify me</p>\n' +
'</div>\n' +
'<p>\n' +
' <p class="iamalreadybeauty">But not me</p>\n' +
'<p class="iamalreadybeauty">But not me</p>\n' +
'</p>');
bth('<div><span>blabla<div>something here</div></span></div>');
bth('<div><br /></div>');
Expand Down
31 changes: 27 additions & 4 deletions test/data/html/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1716,7 +1716,7 @@ exports.test_data = {
' <optgroup>',
' test content',
' <option>',
' test content',
' <p>test content',
' <option>',
' test content',
'</select>'
Expand Down Expand Up @@ -1779,7 +1779,8 @@ exports.test_data = {
' <thead>',
' <tr>',
' <th>Function',
' <th>Control Unit',
' <th>',
' <p>Control Unit',
' <th>Central Station',
' <tbody>',
' <tr>',
Expand Down Expand Up @@ -1852,6 +1853,28 @@ exports.test_data = {
' <dt>gh</dt>',
'</dl>'
]
}, {
comment: 'P element optional closing tag - #1503',
input: [
'<p><p><dl><dt>ef<dt><p>gh</dt><dt>gh</dt></dl><p><h3>headers are outside paragraphs</h3>',
'<p>.<textarea><p><p>.</textarea><textarea><p><p>.</textarea><p>.<p>.</p>'
],
output: [
'<p>',
'<p>',
'<dl>',
' <dt>ef',
' <dt>',
' <p>gh',
' </dt>',
' <dt>gh</dt>',
'</dl>',
'<p>',
'<h3>headers are outside paragraphs</h3>',
'<p>.<textarea><p><p>.</textarea><textarea><p><p>.</textarea>',
'<p>.',
'<p>.</p>'
]
}]
}, {
name: "Unformatted tags",
Expand Down Expand Up @@ -3125,7 +3148,7 @@ exports.test_data = {
' <p>Beautify me</p>',
'</div>',
'<p>',
' <p>But not me</p>',
'<p>But not me</p>',
'</p>'
]
}, {
Expand All @@ -3135,7 +3158,7 @@ exports.test_data = {
' <p class="beauty-me">Beautify me</p>',
'</div>',
'<p>',
' <p class="iamalreadybeauty">But not me</p>',
'<p class="iamalreadybeauty">But not me</p>',
'</p>'
]
}, {
Expand Down

0 comments on commit 35ed0cd

Please sign in to comment.