From f8db419595ac792a37445e9a43f9e69f6548453c Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Tue, 19 Jan 2016 16:57:00 +0800 Subject: [PATCH] improve interaction of keepClosingSlash & removeAttributeQuotes --- src/htmlminifier.js | 22 ++++++++++++---------- tests/minifier.js | 6 +++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/htmlminifier.js b/src/htmlminifier.js index 639728f..e91b37e 100644 --- a/src/htmlminifier.js +++ b/src/htmlminifier.js @@ -105,11 +105,9 @@ return (/^on[a-z]+/).test(attrName); } - function canRemoveAttributeQuotes(value, isLast) { + function canRemoveAttributeQuotes(value) { // http://mathiasbynens.be/notes/unquoted-attribute-values - return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value) && - // make sure trailing slash is not interpreted as HTML self-closing tag - !(isLast && (/\/$/).test(value)); + return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value); } function attributesInclude(attributes, attribute) { @@ -386,14 +384,13 @@ return !(/^(?:pre|textarea)$/.test(tag)); } - function normalizeAttribute(attr, attrs, tag, unarySlash, index, options, isLast) { + function normalizeAttribute(attr, attrs, tag, hasUnarySlash, index, options, isLast) { var attrName = options.caseSensitive ? attr.name : attr.name.toLowerCase(), attrValue = options.preventAttributesEscaping ? attr.value : attr.escaped, attrQuote = options.preventAttributesEscaping ? attr.quote : (options.quoteCharacter === '\'' ? '\'' : '"'), attrFragment, - emittedAttrValue, - isTerminalOfUnarySlash = unarySlash && index === attrs.length - 1; + emittedAttrValue; if ((options.removeRedundantAttributes && isAttributeRedundant(tag, attrName, attrValue, attrs)) @@ -409,9 +406,13 @@ attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs); if (attrValue !== undefined && !options.removeAttributeQuotes || - !canRemoveAttributeQuotes(attrValue, isLast) || isTerminalOfUnarySlash) { + !canRemoveAttributeQuotes(attrValue)) { emittedAttrValue = attrQuote + attrValue + attrQuote; } + // make sure trailing slash is not interpreted as HTML self-closing tag + else if (isLast && (hasUnarySlash || /\/$/.test(attrValue))) { + emittedAttrValue = attrValue + ' '; + } else { emittedAttrValue = attrValue; } @@ -651,7 +652,8 @@ } var openTag = '<' + tag; - var closeTag = ((unarySlash && options.keepClosingSlash) ? '/' : '') + '>'; + var hasUnarySlash = unarySlash && options.keepClosingSlash; + var closeTag = (hasUnarySlash ? '/' : '') + '>'; if (attrs.length === 0) { openTag += closeTag; } @@ -668,7 +670,7 @@ if (lint) { lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped); } - token = normalizeAttribute(attrs[i], attrs, tag, unarySlash, i, options, isLast); + token = normalizeAttribute(attrs[i], attrs, tag, hasUnarySlash, i, options, isLast); if (isLast) { token += closeTag; } diff --git a/tests/minifier.js b/tests/minifier.js index d5af244..b9ce4a2 100644 --- a/tests/minifier.js +++ b/tests/minifier.js @@ -508,7 +508,7 @@ equal(minify(input, { removeAttributeQuotes: true }), '\nfoo\n\n'); input = '\nfoo\n\n'; - equal(minify(input, { removeAttributeQuotes: true }), '\nfoo\n\n'); + equal(minify(input, { removeAttributeQuotes: true }), '\nfoo\n\n'); input = '

'; equal(minify(input, { removeAttributeQuotes: true }), '

'); @@ -739,8 +739,8 @@ test('keeping trailing slashes in tags', function() { equal(minify('', { keepClosingSlash: true }), ''); // https://github.com/kangax/html-minifier/issues/233 - equal(minify('', { keepClosingSlash: true, removeAttributeQuotes: true }), ''); - equal(minify('', { keepClosingSlash: true, removeAttributeQuotes: true }), ''); + equal(minify('', { keepClosingSlash: true, removeAttributeQuotes: true }), ''); + equal(minify('', { keepClosingSlash: true, removeAttributeQuotes: true }), ''); }); test('removing optional tags', function() { -- 2.34.1