Added optional closing of p tags

Fixes #1503
This commit is contained in:
Liam Newman 2020-04-03 17:26:16 -07:00
parent e00d3b2b78
commit 35ed0cd218
3 changed files with 67 additions and 14 deletions

View File

@ -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);
@ -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;
@ -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 elements 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');
@ -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 elements 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 elements 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 elements 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.

View File

@ -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>');
@ -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' +
@ -6795,6 +6796,26 @@ function run_html_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_be
' <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>');
//============================================================
// Unformatted tags

View File

@ -1716,7 +1716,7 @@ exports.test_data = {
' <optgroup>',
' test content',
' <option>',
' test content',
' <p>test content',
' <option>',
' test content',
'</select>'
@ -1779,7 +1779,8 @@ exports.test_data = {
' <thead>',
' <tr>',
' <th>Function',
' <th>Control Unit',
' <th>',
' <p>Control Unit',
' <th>Central Station',
' <tbody>',
' <tr>',
@ -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",