removeEmptyAttr predicate function
authorsxend <arimitsu.k+github@gmail.com>
Thu, 17 Nov 2016 09:39:37 +0000 (18:39 +0900)
committersxend <arimitsu.k+github@gmail.com>
Thu, 17 Nov 2016 09:39:37 +0000 (18:39 +0900)
README.md
src/htmlminifier.js
tests/minifier.js

index 85db897..af26496 100644 (file)
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@ How does HTMLMinifier compare to other solutions — [HTML Minifier from Will Pe
 | `quoteCharacter`               | Type of quote to use for attribute values (' or ") | |
 | `removeAttributeQuotes`        | [Remove quotes around attributes when possible](http://perfectionkills.com/experimenting-with-html-minifier/#remove_attribute_quotes) | `false` |
 | `removeComments`               | [Strip HTML comments](http://perfectionkills.com/experimenting-with-html-minifier/#remove_comments) | `false` |
-| `removeEmptyAttributes`        | [Remove all attributes with whitespace-only values](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_or_blank_attributes) | `false` |
+| `removeEmptyAttributes`        | [Remove all attributes with whitespace-only values](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_or_blank_attributes) | `false` (could be true, Function(attrName, tag)) |
 | `removeEmptyElements`          | [Remove all elements with empty contents](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_elements) | `false` |
 | `removeOptionalTags`           | [Remove optional tags](http://perfectionkills.com/experimenting-with-html-minifier/#remove_optional_tags) | `false` |
 | `removeRedundantAttributes`    | [Remove attributes when value matches default.](http://perfectionkills.com/experimenting-with-html-minifier/#remove_redundant_attributes) | `false` |
index 6848216..61ade0b 100644 (file)
@@ -455,12 +455,15 @@ var reEmptyAttribute = new RegExp(
   '^(?:class|id|style|title|lang|dir|on(?:focus|blur|change|click|dblclick|mouse(' +
     '?:down|up|over|move|out)|key(?:press|down|up)))$');
 
-function canDeleteEmptyAttribute(tag, attrName, attrValue) {
+function canDeleteEmptyAttribute(tag, attrName, attrValue, options) {
   var isValueEmpty = !attrValue || /^\s*$/.test(attrValue);
-  if (isValueEmpty) {
-    return tag === 'input' && attrName === 'value' || reEmptyAttribute.test(attrName);
+  if (!isValueEmpty) {
+    return false;
   }
-  return false;
+  if (typeof options.removeEmptyAttributes === 'function') {
+    return options.removeEmptyAttributes(attrName, tag);
+  }
+  return tag === 'input' && attrName === 'value' || reEmptyAttribute.test(attrName);
 }
 
 function hasAttrName(name, attrs) {
@@ -530,7 +533,7 @@ function normalizeAttr(attr, attrs, tag, options) {
   attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs);
 
   if (options.removeEmptyAttributes &&
-      canDeleteEmptyAttribute(tag, attrName, attrValue)) {
+      canDeleteEmptyAttribute(tag, attrName, attrValue, options)) {
     return;
   }
 
index 91fe7c3..3c0d41a 100644 (file)
@@ -792,6 +792,10 @@ QUnit.test('empty attributes', function(assert) {
   // remove recognized attrs with unspecified values
   input = '<div data-foo class id style title lang dir onfocus onblur onchange onclick ondblclick onmousedown onmouseup onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup></div>';
   assert.equal(minify(input, { removeEmptyAttributes: true }), '<div data-foo></div>');
+
+  // additional remove attributes
+  input = '<img src="" alt="">';
+  assert.equal(minify(input, { removeEmptyAttributes: function(attrName, tag) { return tag === 'img' && attrName === 'src'; } }), '<img alt="">');
 });
 
 QUnit.test('cleaning class/style attributes', function(assert) {