diff --git a/src/transformers/prettify.js b/src/transformers/prettify.js index 8f6a16eb..08f174db 100644 --- a/src/transformers/prettify.js +++ b/src/transformers/prettify.js @@ -7,9 +7,25 @@ module.exports = async (html, config = {}, direct = false) => { const defaultConfig = { parser: 'html', printWidth: 500, - embeddedLanguageFormatting: 'off', htmlWhitespaceSensitivity: 'ignore', - xmlMode: get(config, 'posthtml.options.xmlMode', false) + xmlMode: get(config, 'posthtml.options.xmlMode', false), + rewriteSelfClosing: true, + selfClosingTags: [ + 'area', + 'base', + 'br', + 'col', + 'embed', + 'hr', + 'img', + 'input', + 'link', + 'meta', + 'param', + 'source', + 'track', + 'wbr' + ] } // Don't prettify if not explicitly enabled in config @@ -27,9 +43,27 @@ module.exports = async (html, config = {}, direct = false) => { } const reFormat = (html, config) => { - if (//i.test(html) && !config.xmlMode) { - html = html.replace(/<(.+?)(\s\/)>/g, '<$1>') + if (//i.test(html) && !config.xmlMode && config.rewriteSelfClosing) { + html = html.replace(new RegExp(`<(${config.selfClosingTags.join('|')})\s?([^>]*?)\s?\/>`, 'g'), (match, p1, p2) => { + return `<${p1}${p2.trimEnd()}>` + }) } return html + // Fix style="" attributes broken down on multiple lines + .replace(/(\s+style="\s+)([\s\S]*?)(\s+")/g, (match, p1, p2, p3) => { + return p1.replace(/\n\s+?(style)/g, ' $1').trimEnd() + + p2.replace(/\s+/g, ' ').trim() + + p3.trim() + }) + // Fix closing tags broken down on multiple lines (\n\s+>) + .replace(/(<\/pre)\s+>/g, '$1>') + // Undo escaping of quotes in attribute values + .replace(/="(.*?)"/g, (match, p1) => { + return `="${p1.replace(/"/g, '\'')}"` + }) + // Fix => + .replace(/<([^>]+)\n\s*([^>]+)\n\s*>/g, '<$1 $2>') + // Fix => + .replace(/<([^>]+)\n\s*>/g, '<$1>') } diff --git a/test/expected/transformers/prettify.html b/test/expected/transformers/prettify.html new file mode 100644 index 00000000..07c3991f --- /dev/null +++ b/test/expected/transformers/prettify.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+ + +
+
+
+ + + +
+ + diff --git a/test/fixtures/transformers/prettify.html b/test/fixtures/transformers/prettify.html new file mode 100644 index 00000000..fbc232df --- /dev/null +++ b/test/fixtures/transformers/prettify.html @@ -0,0 +1,31 @@ + + + + + + + +
+
+ + +
+
+
+ + + +
+ + diff --git a/test/test-transformers.js b/test/test-transformers.js index e324c7d7..1a7f5fc3 100644 --- a/test/test-transformers.js +++ b/test/test-transformers.js @@ -240,13 +240,18 @@ test('base URL (object)', async t => { }) test('prettify', async t => { - // With custom object config - const html = await Maizzle.prettify('

with options

', {printWidth: 12}) - t.is(html, '
\n

\n with\n options\n

\n
\n') + const source = await fixture('prettify') + + const html = await Maizzle.prettify(source, { + printWidth: 500, + rewriteSelfClosing: true + }) + + t.is(html.trim(), (await expected('prettify'))) // `prettify: true` - const html2 = await Maizzle.prettify('

prettify: true

', true) - t.is(html2, '\n\n

prettify: true

\n') + const html2 = await Maizzle.prettify('

prettify: true

', true) + t.is(html2, '\n\n\n

prettify: true

\n') // No config const html3 = await Maizzle.prettify('

test

') diff --git a/xo.config.js b/xo.config.js index f5434fed..a71924e0 100644 --- a/xo.config.js +++ b/xo.config.js @@ -6,6 +6,7 @@ module.exports = { 'max-params': 0, 'brace-style': 0, 'no-lonely-if': 0, + 'no-useless-escape': 0, 'unicorn/no-reduce': 0, 'import/extensions': 0, 'operator-linebreak': 0,