Skip to content

Commit 9592407

Browse files
author
Phillip Clark
authored
Merge pull request #149 from saveman71/master
Add "normalize" documentation/sample in README.md. I appreciate the contribution.
2 parents 5133f9c + 73666ba commit 9592407

File tree

2 files changed

+120
-3
lines changed

2 files changed

+120
-3
lines changed

Readme.md

+52-3
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ var rhs = {
154154
it: 'has',
155155
an: 'array',
156156
with: ['a', 'few', 'more', 'elements', { than: 'before' }]
157+
}
157158
};
158159

159160
observableDiff(lhs, rhs, function (d) {
@@ -168,8 +169,8 @@ observableDiff(lhs, rhs, function (d) {
168169

169170
A standard import of `var diff = require('deep-diff')` is assumed in all of the code examples. The import results in an object having the following public properties:
170171

171-
* `diff(lhs, rhs, prefilter, acc)` — calculates the differences between two objects, optionally prefiltering elements for comparison, and optionally using the specified accumulator.
172-
* `observableDiff(lhs, rhs, observer, prefilter)` — calculates the differences between two objects and reports each to an observer function, optionally, prefiltering elements for comparison.
172+
* `diff(lhs, rhs[, options, acc])` — calculates the differences between two objects, optionally using the specified accumulator.
173+
* `observableDiff(lhs, rhs, observer[, options])` — calculates the differences between two objects and reports each to an observer function.
173174
* `applyDiff(target, source, filter)` — applies any structural differences from a source object to a target object, optionally filtering each difference.
174175
* `applyChange(target, source, change)` — applies a single change record to a target object. NOTE: `source` is unused and may be removed.
175176
* `revertChange(target, source, change)` reverts a single change record to a target object. NOTE: `source` is unused and may be removed.
@@ -178,11 +179,14 @@ A standard import of `var diff = require('deep-diff')` is assumed in all of the
178179

179180
The `diff` function calculates the difference between two objects.
180181

182+
181183
#### Arguments
182184

183185
* `lhs` - the left-hand operand; the origin object.
184186
* `rhs` - the right-hand operand; the object being compared structurally with the origin object.
185-
* `prefilter` - an optional function that determines whether difference analysis should continue down the object graph.
187+
* `options` - A configuration object that can have the following properties:
188+
- `prefilter`: function that determines whether difference analysis should continue down the object graph. This function can also replace the `options` object in the parameters for backward compatibility.
189+
- `normalize`: function that pre-processes every _leaf_ of the tree.
186190
* `acc` - an optional accumulator/array (requirement is that it have a `push` function). Each difference is pushed to the specified accumulator.
187191

188192
Returns either an array of changes or, if there are no changes, `undefined`. This was originally chosen so the result would be pass a truthy test:
@@ -227,6 +231,51 @@ const none = diff(data, clone,
227231
assert.equal(two.length, 2, 'should reflect two differences');
228232
assert.ok(typeof none === 'undefined', 'should reflect no differences');
229233
```
234+
#### Normalizing object properties
235+
236+
The `normalize`'s signature should be `function(path, key, lhs, rhs)` and it should return either a falsy value if no normalization has occured, or a `[lhs, rhs]` array to replace the original values. This step doesn't occur if the path was filtered out in the `prefilter` phase.
237+
238+
```javascript
239+
const diff = require('deep-diff');
240+
const assert = require('assert');
241+
242+
const data = {
243+
pull: 149,
244+
submittedBy: 'saveman71',
245+
};
246+
247+
const clone = JSON.parse(JSON.stringify(data));
248+
clone.issue = 42;
249+
250+
const two = diff(data, clone);
251+
const none = diff(data, clone, {
252+
normalize: (path, key, lhs, rhs) => {
253+
if (lhs === 149) {
254+
lhs = 42;
255+
}
256+
if (rhs === 149) {
257+
rhs = 42;
258+
}
259+
return [lsh, rhs];
260+
}
261+
});
262+
263+
assert.equal(two.length, 1, 'should reflect one difference');
264+
assert.ok(typeof none === 'undefined', 'should reflect no difference');
265+
```
266+
267+
### `observableDiff`
268+
269+
The `observableDiff` function calculates the difference between two objects and reports each to an observer function.
270+
271+
#### Argmuments
272+
273+
* `lhs` - the left-hand operand; the origin object.
274+
* `rhs` - the right-hand operand; the object being compared structurally with the origin object.
275+
* `observer` - The observer to report to.
276+
* `options` - A configuration object that can have the following properties:
277+
- `prefilter`: function that determines whether difference analysis should continue down the object graph. This function can also replace the `options` object in the parameters for backward compatibility.
278+
- `normalize`: function that pre-processes every _leaf_ of the tree.
230279

231280
## Contributing
232281

test/tests.js

+68
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,23 @@
268268

269269
});
270270

271+
describe('if the filtered config is passed as an object', function () {
272+
273+
it('changes to the array to not appear as a difference', function () {
274+
var prefilter = function (path, key) {
275+
return key === 'supportedBy';
276+
};
277+
var diff = deep(lhs, rhs, {prefilter: prefilter});
278+
expect(diff).to.be.ok();
279+
expect(diff.length).to.be(2);
280+
expect(diff[0]).to.have.property('kind');
281+
expect(diff[0].kind).to.be('E');
282+
expect(diff[1]).to.have.property('kind');
283+
expect(diff[1].kind).to.be('N');
284+
});
285+
286+
});
287+
271288
describe('if the filtered property is not an array', function () {
272289

273290
it('changes do not appear as a difference', function () {
@@ -290,6 +307,57 @@
290307
});
291308
});
292309

310+
describe('Can normalize properties to before diffing', function () {
311+
var testLHS = {
312+
array: [1, 2, 3, 4, 5],
313+
};
314+
315+
var testRHS = {
316+
array: '1/2/3/4/5',
317+
};
318+
319+
it('changes do not appear as a difference', function () {
320+
var filter = {
321+
normalize: function (path, key, lhs, rhs) {
322+
expect(key).to.be('array');
323+
324+
if (Array.isArray(lhs)) {
325+
lhs = lhs.join('/');
326+
}
327+
if (Array.isArray(rhs)) {
328+
rhs = rhs.join('/');
329+
}
330+
return [lhs, rhs];
331+
}
332+
};
333+
334+
var diff;
335+
336+
diff = deep(testLHS, testRHS, filter);
337+
expect(diff).to.be.an('undefined');
338+
339+
diff = deep(testRHS, testLHS, filter);
340+
expect(diff).to.be.an('undefined');
341+
});
342+
343+
it('falsy return does not normalize', function () {
344+
var filter = {
345+
// eslint-disable-next-line no-unused-vars
346+
normalize: function (path, key, lhs, rhs) {
347+
return false;
348+
}
349+
};
350+
351+
var diff;
352+
353+
diff = deep(testLHS, testRHS, filter);
354+
expect(diff).to.be.ok();
355+
356+
diff = deep(testRHS, testLHS, filter);
357+
expect(diff).to.be.ok();
358+
});
359+
});
360+
293361
describe('A target that has nested values', function () {
294362
var nestedOne = {
295363
noChange: 'same',

0 commit comments

Comments
 (0)