Skip to content

Commit

Permalink
fix #17, fix #19, close #21
Browse files Browse the repository at this point in the history
  • Loading branch information
Phillip Clark committed Aug 13, 2014
1 parent 2b04b39 commit dea80f2
Show file tree
Hide file tree
Showing 8 changed files with 632 additions and 494 deletions.
29 changes: 27 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

## ChangeLog

`0.2.0` - [Fixes Bug #17](https://github.com/flitbit/diff/issues/17), [Fixes Bug #19](https://github.com/flitbit/diff/issues/19), [Enhancement #21](https://github.com/flitbit/diff/issues/21) Applying changes that are properly structured can now be applied as a change (no longer requires typeof Diff) - supports differences being applied after round-trip serialization to JSON format. Prefilter now reports the path of all changes - it was not showing a path for arrays and anything in the structure below (reported by @ravishvt).

*Breaking Change* – The structure of change records for differences below an array element has changed. Array indexes are now reported as numeric elements in the `path` if the changes is merely edited (an `E` kind). Changes of kind `A` (array) are only reported for changes in the terminal array itself and will have a nested `N` (new) item or a nested `D` (deleted) item.

`0.1.7` - [Enhancement #11](https://github.com/flitbit/diff/issues/11) Added the ability to filter properties that should not be analyzed while calculating differences. Makes `deep-diff` more usable with frameworks that attach housekeeping properties to existing objects. AngularJS does this, and the new filter ability should ease working with it.

`0.1.6` - Changed objects within nested arrays can now be applied. They were previously recording the changes appropriately but `applyDiff` would error. Comparison of `NaN` works more sanely - comparison to number shows difference, comparison to another `Nan` does not.
Expand Down Expand Up @@ -55,7 +59,7 @@ var deep = require('deep-diff')

**browser**
```html
<script src="deep-diff-0.1.3.min.js"></script>
<script src="deep-diff-0.2.0.min.js"></script>
```
> Minified, browser release of the current version of the module is under the `releases` folder.
> In a browser, `deep-diff` defines a global variable `DeepDiff`. If there is a conflict in the global namesapce you can restore the conflicting definition and assign `deep-diff` to another variable like this: `var deep = DeepDiff.noConflict();`.
Expand Down Expand Up @@ -89,8 +93,9 @@ var rhs = {

var differences = diff(lhs, rhs);
```
The code snippet above would result in the following structure describing the differences:
*up to v 0.1.7* The code snippet above would result in the following structure describing the differences:
``` javascript
// Versions < 0.2.0
[ { kind: 'E',
path: [ 'name' ],
lhs: 'my object',
Expand All @@ -109,6 +114,26 @@ The code snippet above would result in the following structure describing the di
item: { kind: 'N', rhs: { than: 'before' } } } ]
```

*v 0.2.0 and above* The code snippet above would result in the following structure describing the differences:
``` javascript
[ { kind: 'E',
path: [ 'name' ],
lhs: 'my object',
rhs: 'updated object' },
{ kind: 'E',
path: [ 'details', 'with', 2 ],
lhs: 'elements',
rhs: 'more' },
{ kind: 'A',
path: [ 'details', 'with' ],
index: 3,
item: { kind: 'N', rhs: 'elements' } },
{ kind: 'A',
path: [ 'details', 'with' ],
index: 4,
item: { kind: 'N', rhs: { than: 'before' } } } ]
```

### Differences

Differences are reported as one or more change records. Change records have the following structure:
Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "deep-diff",
"main": "index.js",
"version": "0.1.6",
"version": "0.2.0",
"homepage": "https://github.com/flitbit/diff",
"authors": [
"Phillip Clark <phillip@flitbit.com>"
Expand Down
40 changes: 40 additions & 0 deletions examples/apply-diff-from-any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*jshint indent:2, laxcomma:true, laxbreak:true*/
var util = require('util')
, diff = require('..')
, data = require('./practice-data')
;

var cycle = -1
, i
, len = data.length
, prior = {}
, comparand
, records
, ch
;

var applyEachChange = function (ch) {
diff.applyChange(prior, comparand, ch);
};

while (++cycle < 10) {
i = -1;
while (++i < len) {

comparand = data[i];


// get the difference...
records = diff(prior, comparand);

// round-trip serialize to prune the underlying types...
var serialized = JSON.stringify(records);
var desierialized = JSON.parse(serialized);

if (desierialized) {
desierialized.forEach(applyEachChange);

prior = comparand;
}
}
}
117 changes: 117 additions & 0 deletions examples/array-change.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*jshint indent:2, laxcomma:true, laxbreak:true*/
var util = require('util')
, expect = require('expect.js')
, eql = require('deep-equal')
, deep = require('..')
;

var lhs = {
"id": "Release",
"phases": [{
"id": "Phase1",
"tasks": [
{"id": "Task1"},
{"id": "Task2"}
]
}, {
"id": "Phase2",
"tasks": [
{"id": "Task3"}
]
}]
};
var rhs = {
"id": "Release",
"phases": [{
// E: Phase1 -> Phase2
"id": "Phase2",
"tasks": [
{"id": "Task3"}
]
}, {
"id": "Phase1",
"tasks": [
{"id": "Task1"},
{"id": "Task2"}
]
}]
};

var diff = deep.diff(lhs, rhs);

// there should be differences
expect(diff).to.be.ok();
expect(diff.length).to.be(6);


// It.phases[0].id changed from 'Phase1' to 'Phase2'
//
expect(diff[0].kind).to.be('E');
expect(diff[0].path).to.be.an('array');
expect(diff[0].path).to.have.length(3);
expect(diff[0].path[0]).to.be('phases');
expect(diff[0].path[1]).to.be(0);
expect(diff[0].path[2]).to.be('id');
expect(diff[0].lhs).to.be('Phase1');
expect(diff[0].rhs).to.be('Phase2');

// It.phases[0].tasks[0].id changed from 'Task1' to 'Task3'
//
expect(diff[1].kind).to.be('E');
expect(diff[1].path).to.be.an('array');
expect(diff[1].path).to.have.length(5);
expect(diff[1].path[0]).to.be('phases');
expect(diff[1].path[1]).to.be(0);
expect(diff[1].path[2]).to.be('tasks');
expect(diff[1].path[3]).to.be(0);
expect(diff[1].path[4]).to.be('id');
expect(diff[1].lhs).to.be('Task1');
expect(diff[1].rhs).to.be('Task3');

// It.phases[0].tasks[1] was deleted
//
expect(diff[2].kind).to.be('A');
expect(diff[2].path).to.be.an('array');
expect(diff[2].path).to.have.length(3);
expect(diff[2].path[0]).to.be('phases');
expect(diff[2].path[1]).to.be(0);
expect(diff[2].path[2]).to.be('tasks');
expect(diff[2].index).to.be(1);
expect(diff[2].item.kind).to.be('D');

// It.phases[1].id changed from 'Phase2' to 'Phase1'
//
expect(diff[3].kind).to.be('E');
expect(diff[3].path).to.be.an('array');
expect(diff[3].path).to.have.length(3);
expect(diff[3].path[0]).to.be('phases');
expect(diff[3].path[1]).to.be(1);
expect(diff[3].path[2]).to.be('id');
expect(diff[3].lhs).to.be('Phase2');
expect(diff[3].rhs).to.be('Phase1');

// It.phases[1].tasks[0].id changed from 'Task3' to 'Task1'
//
expect(diff[4].kind).to.be('E');
expect(diff[4].path).to.be.an('array');
expect(diff[4].path).to.have.length(5);
expect(diff[4].path[0]).to.be('phases');
expect(diff[4].path[1]).to.be(1);
expect(diff[4].path[2]).to.be('tasks');
expect(diff[4].path[3]).to.be(0);
expect(diff[4].path[4]).to.be('id');
expect(diff[4].lhs).to.be('Task3');
expect(diff[4].rhs).to.be('Task1');

// It.phases[1].tasks[1] is new
//
expect(diff[5].kind).to.be('A');
expect(diff[5].path).to.be.an('array');
expect(diff[5].path).to.have.length(3);
expect(diff[5].path[0]).to.be('phases');
expect(diff[5].path[1]).to.be(1);
expect(diff[5].path[2]).to.be('tasks');
expect(diff[5].index).to.be(1);
expect(diff[5].item.kind).to.be('N');

var applied = deep.applyDiff(lhs, rhs);
6 changes: 5 additions & 1 deletion examples/example1.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ deep.observableDiff(lhs, rhs, function (d) {
if (d.path.length !== 1 || d.path.join('.') !== 'name') {
deep.applyChange(lhs, rhs, d);
}
});
}, function (path, key) {
var p = (path && path.length) ? path.join('/') : '<no-path>'
util.log('prefilter: path = ' + p + ' key = ' + key);
}
);

console.log(util.inspect(lhs, false, 99));
Loading

0 comments on commit dea80f2

Please sign in to comment.