diff --git a/README.md b/README.md index 4b1c4d4d..dabc70dd 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Compares two HTML. - [ignoreComments](#ignorecomments-boolean) - [ignoreEndTags](#ignoreendtags-boolean) - [ignoreDuplicateAttributes](#ignoreduplicateattributes-boolean) + - [ignoreEmptyAttributes](#ignoreemptyattributes-boolean) - [Presets](#presets) - [Usage](#usage) - [Methods](#methods) @@ -269,6 +270,38 @@ For example, the following two code samples will be considered to be equivalent: Text ``` + +##### ignoreEmptyAttributes: Boolean + +Makes **html-differ** ignore tags' attributes with empty values during the comparison.
+From the list of the same tag's attributes, the attributes which have empty values will be ignored (default: `false`). + +**Example**: `true`
+For example, the following two code samples will be considered to be equivalent: + +```html +
+``` + +```html +
+``` + +This option can also be used to completely ignore attributes specified by the `ignoreAttributes` option, even if they are present in one example, but not in the other. + +**Example**: `ignoreAttributes: ['id', 'for'], ignoreEmptyAttributes: true`
+For example, the following two code samples will be considered to be equivalent: + +```html + + +``` + +```html + + +``` + #### Presets * [bem](https://github.com/bem/html-differ/blob/master/presets/bem.json) - sets predefined options for [BEM](http://bem.info/). diff --git a/lib/HtmlDiff.js b/lib/HtmlDiff.js index cb2ed74b..f21a49e9 100644 --- a/lib/HtmlDiff.js +++ b/lib/HtmlDiff.js @@ -13,6 +13,7 @@ var diff = require('diff'), * @param {Boolean} [options.ignoreComments] * @param {Boolean} [options.ignoreEndTags=false] * @param {Boolean} [options.ignoreDuplicateAttributes=false] + * @param {Boolean} [options.ignoreEmptyAttributes=false] */ var HtmlDiff = function (options) { this.options = defaults(options); diff --git a/lib/defaults.js b/lib/defaults.js index 33246355..d25582fe 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -14,6 +14,7 @@ var presets = { * @param {Boolean} [options.ignoreComments=true] * @param {Boolean} [options.ignoreEndTags=false] * @param {Boolean} [options.ignoreDuplicateAttributes=false] + * @param {Boolean} [options.ignoreEmptyAttributes=false] * returns {Object} */ module.exports = function (options) { @@ -39,7 +40,8 @@ var presets = { ignoreComments: true, ignoreEndTags: false, - ignoreDuplicateAttributes: false + ignoreDuplicateAttributes: false, + ignoreEmptyAttributes: false }); }; diff --git a/lib/index.js b/lib/index.js index e5f5d63a..be8c69db 100644 --- a/lib/index.js +++ b/lib/index.js @@ -25,6 +25,7 @@ HtmlDiff.prototype.tokenize = function (html) { * @param {Boolean} [options.ignoreComments=true] * @param {Boolean} [options.ignoreEndTags=false] * @param {Boolean} [options.ignoreDuplicateAttributes=false] + * @param {Boolean} [options.ignoreEmptyAttributes=false] */ var HtmlDiffer = function (options) { options = defaults(options); diff --git a/lib/utils/modify.js b/lib/utils/modify.js index 6789b347..0b027e5f 100644 --- a/lib/utils/modify.js +++ b/lib/utils/modify.js @@ -12,6 +12,7 @@ var SimpleApiParser = require('parse5').SimpleApiParser, * @param {Boolean} [options.ignoreComments=true] * @param {Boolean} [options.ignoreEndTags=false] * @param {Boolean} [options.ignoreDuplicateAttributes=false] + * @param {Boolean} [options.ignoreEmptyAttributes=false] * returns {String} */ function modify(value, options) { @@ -42,6 +43,10 @@ function modify(value, options) { utils.sortAttrsValues(attrs, options.compareAttributesAsJSON) && utils.removeAttrsValues(attrs, options.ignoreAttributes); + if (options.ignoreEmptyAttributes) { + attrs = utils.removeEmptyAttributes(attrs); + } + modifiedValue += serialize.startTag(tagName, attrs, selfClosing); }, /** diff --git a/lib/utils/utils.js b/lib/utils/utils.js index a57d2c14..74e6b82f 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -193,6 +193,18 @@ function removeDuplicateAttributes(attrs) { return res; } +function removeEmptyAttributes(attrs) { + var res = []; + + _.forEach(attrs, function (attr) { + if (attr.value !== '') { + res.push(attr); + } + }); + + return res; +} + /** * Processes a conditional comment * @param {String} comment @@ -228,6 +240,7 @@ module.exports = { removeAttrsValues: removeAttrsValues, removeWhitespaces: removeWhitespaces, removeDuplicateAttributes: removeDuplicateAttributes, + removeEmptyAttributes: removeEmptyAttributes, getConditionalComment: getConditionalComment }; diff --git a/test/differ/fixtures/first/ignore-attributes-empty.html b/test/differ/fixtures/first/ignore-attributes-empty.html new file mode 100644 index 00000000..f1109c3f --- /dev/null +++ b/test/differ/fixtures/first/ignore-attributes-empty.html @@ -0,0 +1,2 @@ + + diff --git a/test/differ/fixtures/first/ignore-empty-attributes.html b/test/differ/fixtures/first/ignore-empty-attributes.html new file mode 100644 index 00000000..16839deb --- /dev/null +++ b/test/differ/fixtures/first/ignore-empty-attributes.html @@ -0,0 +1 @@ +
diff --git a/test/differ/fixtures/second/ignore-attributes-empty.html b/test/differ/fixtures/second/ignore-attributes-empty.html new file mode 100644 index 00000000..ff39878d --- /dev/null +++ b/test/differ/fixtures/second/ignore-attributes-empty.html @@ -0,0 +1,2 @@ + + diff --git a/test/differ/fixtures/second/ignore-empty-attributes.html b/test/differ/fixtures/second/ignore-empty-attributes.html new file mode 100644 index 00000000..7c89b545 --- /dev/null +++ b/test/differ/fixtures/second/ignore-empty-attributes.html @@ -0,0 +1 @@ +
diff --git a/test/differ/isEqual.js b/test/differ/isEqual.js index d495cf5a..95e2ca44 100644 --- a/test/differ/isEqual.js +++ b/test/differ/isEqual.js @@ -136,6 +136,34 @@ describe('\'isEqual\'', function () { htmlDiffer.isEqual(files.html1, files.html2).must.be.false(); }); + it('must work option \'ignoreEmptyAttributes\'', function () { + var htmlDiffer = new HtmlDiffer({ ignoreEmptyAttributes: true }), + files = readFiles('ignore-empty-attributes'); + + htmlDiffer.isEqual(files.html1, files.html2).must.be.true(); + }); + + it('must not ignore empty attributes', function () { + var htmlDiffer = new HtmlDiffer({ ignoreEmptyAttributes: false }), + files = readFiles('ignore-empty-attributes'); + + htmlDiffer.isEqual(files.html1, files.html2).must.be.false(); + }); + + it('must work options \'ignoreAttributes\' and \'ignoreEmptyAttributes\'', function () { + var htmlDiffer = new HtmlDiffer({ ignoreAttributes: ['id', 'for'], ignoreEmptyAttributes: true }), + files = readFiles('ignore-attributes-empty'); + + htmlDiffer.isEqual(files.html1, files.html2).must.be.true(); + }); + + it('must not ignore attributes', function () { + var htmlDiffer = new HtmlDiffer({ }), + files = readFiles('ignore-attributes-empty'); + + htmlDiffer.isEqual(files.html1, files.html2).must.be.false(); + }); + it('must work \'bem\' preset', function () { var htmlDiffer = new HtmlDiffer('bem'), files = readFiles('bem-preset');