From: Alex Lam S.L Date: Sun, 20 May 2018 18:18:49 +0000 (+0800) Subject: handle empty `class` attributes (#922) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=9ecabca27bed20391a439a0f0e03514315aff564;p=html-minifier.git handle empty `class` attributes (#922) fixes #921 --- diff --git a/src/htmlminifier.js b/src/htmlminifier.js index e382434..7550c72 100644 --- a/src/htmlminifier.js +++ b/src/htmlminifier.js @@ -9,10 +9,7 @@ var UglifyJS = require('uglify-js'); var utils = require('./utils'); function trimWhitespace(str) { - if (typeof str !== 'string') { - return str; - } - return str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, ''); + return str && str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, ''); } function collapseWhitespaceAll(str) { @@ -258,7 +255,7 @@ function isSrcset(attrName, tag) { } function cleanAttributeValue(tag, attrName, attrValue, options, attrs) { - if (attrValue && isEventAttribute(attrName, options)) { + if (isEventAttribute(attrName, options)) { attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, ''); return options.minifyJS(attrValue, true); } @@ -314,7 +311,7 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) { return (+numString).toString(); }); } - else if (attrValue && options.customAttrCollapse && options.customAttrCollapse.test(attrName)) { + else if (options.customAttrCollapse && options.customAttrCollapse.test(attrName)) { attrValue = attrValue.replace(/\n+|\r+|\s{2,}/g, ''); } else if (tag === 'script' && attrName === 'type') { @@ -522,7 +519,7 @@ function canTrimWhitespace(tag) { } function normalizeAttr(attr, attrs, tag, options) { - var attrName = options.caseSensitive ? attr.name : attr.name.toLowerCase(), + var attrName = options.name(attr.name), attrValue = attr.value; if (options.decodeEntities && attrValue) { @@ -538,7 +535,9 @@ function normalizeAttr(attr, attrs, tag, options) { return; } - attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs); + if (attrValue) { + attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs); + } if (options.removeEmptyAttributes && canDeleteEmptyAttribute(tag, attrName, attrValue, options)) { @@ -615,6 +614,9 @@ function identity(value) { function processOptions(values) { var options = { + name: function(name) { + return name.toLowerCase(); + }, canCollapseWhitespace: canCollapseWhitespace, canTrimWhitespace: canTrimWhitespace, html5: true, @@ -631,7 +633,12 @@ function processOptions(values) { }; Object.keys(values).forEach(function(key) { var value = values[key]; - if (key === 'log') { + if (key === 'caseSensitive') { + if (value) { + options.name = identity; + } + } + else if (key === 'log') { if (typeof value === 'function') { options.log = value; } @@ -732,7 +739,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) { function attrNames(attrs) { return attrs.map(function(attr) { - return options.caseSensitive ? attr.name : attr.name.toLowerCase(); + return options.name(attr.name); }); } @@ -756,7 +763,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) { } for (var i = 0, len = attrs.length; i < len; i++) { var attr = attrs[i]; - if (classChain && (options.caseSensitive ? attr.name : attr.name.toLowerCase()) === 'class') { + if (classChain && attr.value && options.name(attr.name) === 'class') { classChain.add(trimWhitespace(attr.value).split(/[ \t\n\f\r]+/).filter(shouldSkipUIDs)); } else if (options.processScripts && attr.name.toLowerCase() === 'type') { @@ -946,16 +953,13 @@ function minify(value, options, partialMarkup) { html5: options.html5, start: function(tag, attrs, unary, unarySlash, autoGenerated) { - var lowerTag = tag.toLowerCase(); - - if (lowerTag === 'svg') { + if (tag.toLowerCase() === 'svg') { options = Object.create(options); - options.keepClosingSlash = true; options.caseSensitive = true; + options.keepClosingSlash = true; + options.name = identity; } - - tag = options.caseSensitive ? tag : lowerTag; - + tag = options.name(tag); currentTag = tag; charsPrevTag = tag; if (!inlineTextTags(tag)) { @@ -1035,11 +1039,10 @@ function minify(value, options, partialMarkup) { } }, end: function(tag, attrs, autoGenerated) { - var lowerTag = tag.toLowerCase(); - if (lowerTag === 'svg') { + if (tag.toLowerCase() === 'svg') { options = Object.getPrototypeOf(options); } - tag = options.caseSensitive ? tag : lowerTag; + tag = options.name(tag); // check if current tag is in a whitespace stack if (options.collapseWhitespace) { diff --git a/tests/minifier.js b/tests/minifier.js index 233d201..fe425f5 100644 --- a/tests/minifier.js +++ b/tests/minifier.js @@ -3229,6 +3229,10 @@ QUnit.test('sort style classes', function(assert) { removeAttributeQuotes: true, sortClassName: true }), output); + + input = '
'; + assert.equal(minify(input, { sortClassName: false }), input); + assert.equal(minify(input, { sortClassName: true }), input); }); QUnit.test('decode entity characters', function(assert) {