From de2639de640e84077945834e9682d1aaf7727f58 Mon Sep 17 00:00:00 2001 From: David Thomason Date: Thu, 30 May 2019 16:21:22 -0400 Subject: [PATCH 1/2] Added option ignoreEmptyAttributes: ignores attributes with empty values --- README.md | 33 +++++++++++++++++++ lib/HtmlDiff.js | 1 + lib/defaults.js | 4 ++- lib/index.js | 1 + lib/utils/modify.js | 5 +++ lib/utils/utils.js | 13 ++++++++ .../first/ignore-attributes-empty.html | 2 ++ .../first/ignore-empty-attributes.html | 1 + .../second/ignore-attributes-empty.html | 2 ++ .../second/ignore-empty-attributes.html | 1 + test/differ/isEqual.js | 28 ++++++++++++++++ 11 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 test/differ/fixtures/first/ignore-attributes-empty.html create mode 100644 test/differ/fixtures/first/ignore-empty-attributes.html create mode 100644 test/differ/fixtures/second/ignore-attributes-empty.html create mode 100644 test/differ/fixtures/second/ignore-empty-attributes.html diff --git a/README.md b/README.md index 4b1c4d4..dabc70d 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 cb2ed74..f21a49e 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 3324635..d25582f 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 e5f5d63..be8c69d 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 6789b34..0b027e5 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 a57d2c1..39d24ba 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 0000000..f1109c3 --- /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 0000000..16839de --- /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 0000000..ff39878 --- /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 0000000..7c89b54 --- /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 d495cf5..b69f5cb 100644 --- a/test/differ/isEqual.js +++ b/test/differ/isEqual.js @@ -135,6 +135,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'), From 9b4491ea2e31e3c86c17c433fc07806eb125d43c Mon Sep 17 00:00:00 2001 From: David Thomason Date: Thu, 30 May 2019 16:34:56 -0400 Subject: [PATCH 2/2] Removed trailing whitespaces --- lib/utils/utils.js | 4 ++-- test/differ/isEqual.js | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 39d24ba..74e6b82 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -195,13 +195,13 @@ function removeDuplicateAttributes(attrs) { function removeEmptyAttributes(attrs) { var res = []; - + _.forEach(attrs, function (attr) { if (attr.value !== '') { res.push(attr); } }); - + return res; } diff --git a/test/differ/isEqual.js b/test/differ/isEqual.js index b69f5cb..95e2ca4 100644 --- a/test/differ/isEqual.js +++ b/test/differ/isEqual.js @@ -135,32 +135,32 @@ 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(); });