Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

simple-diff

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simple-diff - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

6

bower.json
{
"name": "backbone-dom-view",
"main": "backbone-dom-view.js",
"version": "1.2.0",
"name": "simple-diff",
"main": "simple-diff.js",
"version": "1.3.0",
"homepage": "https://github.com/redexp/simple-diff",

@@ -6,0 +6,0 @@ "authors": [

{
"name": "simple-diff",
"version": "1.2.0",
"version": "1.3.0",
"description": "simple diff for object and arrays with options",

@@ -5,0 +5,0 @@ "main": "simple-diff.js",

simple-diff
===========
Lib for simple diff with moved items in array detection
Lib for simple diff with detection of moved items in array

@@ -131,11 +131,37 @@ [![Build Status](https://travis-ci.org/redexp/simple-diff.svg?branch=master)](https://travis-ci.org/redexp/simple-diff)

* `idProp` - id property for all arrays items. Default value: `id`
* `idProps` - hash where key is path to array and value is id property. Path examples: `users.list`, `user.list.1.friends`, `users.list.*.friends`
* `callback` - function which will be called for each event. Useful for memory management because in this case diff will not create array of all events.
* `addEvent` - name of event when new property added to object. Default value: `add`
* `changeEvent` - name of event when property value changed. Default value: `change`
* `removeEvent` - name of event when property removed from object. Default value: `remove`
* `addItemEvent` - name of event when new item added to array. Default value: `add-item`
* `removeItemEvent` - name of event when item removed from array. Default value: `remove-item`
* `moveItemEvent` - name of event when item changed it index in array. Default value: `move-item`
## `idProp: 'id' || '*'`
Property name with unique value in it array. Default value is `id`. If your arrays do not have unique properties then you should set this option as `*` and lib will compare items one by one without trying to find moved items.
## `idProps: {'path': 'propName' || '*'}`
Hash where key is path to array and value is id property. Path examples: `users.list`, `user.list.1.friends`, `users.list.*.friends`
## `callback: function (event)`
Function which will be called for each event. If callback is passed then lib will not create array of all changes.
## `addEvent: 'add'`
Name of event when new property added to object. Default value is `add`
## `changeEvent: 'change'`
Name of event when property value changed. Default value is `change`
## `removeEvent: 'remove'`
Name of event when property removed from object. Default value is `remove`
## `addItemEvent: 'add-item'`
Name of event when new item added to array. Default value is `add-item`
## `removeItemEvent: 'remove-item'`
Name of event when item removed from array. Default value is `remove-item`
## `moveItemEvent: 'move-item'`
Name of event when item changed it index in array. Default value is `move-item`

@@ -54,2 +54,47 @@ (function (root, factory) {

var idProp =
(ops.idProps &&
(
ops.idProps[oldPath.map(numberToAsterisk).join('.')] ||
ops.idProps[oldPath.join('.')]
)) || ID_PROP;
if (idProp === '*') {
var oldLength = oldObj.length,
newLength = newObj.length;
for (i = 0, len = oldLength > newLength ? oldLength : newLength; i < len; i++) {
if (i < oldLength && i < newLength) {
diff(oldObj[i], newObj[i], extend({}, ops, {
callback: callback,
oldPath: oldPath.concat(i),
newPath: newPath.concat(i)
}));
}
else if (i >= oldLength) {
callback({
oldPath: oldPath,
newPath: newPath,
type: ADD_ITEM_EVENT,
oldIndex: -1,
curIndex: -1,
newIndex: i,
newValue: newObj[i]
});
}
else if (i >= newLength) {
callback({
oldPath: oldPath,
newPath: newPath,
type: REMOVE_ITEM_EVENT,
oldIndex: i,
curIndex: newLength,
newIndex: -1
});
}
}
return changes;
}
var sample = oldObj.length > 0 ? oldObj[0] : newObj[0];

@@ -61,9 +106,3 @@

var idProp =
(objective && ops.idProps &&
(
ops.idProps[oldPath.map(numberToAsterisk).join('.')] ||
ops.idProps[oldPath.join('.')]
)) || ID_PROP,
oldHash = objective ? indexBy(oldObj, idProp) : hashOf(oldObj),
var oldHash = objective ? indexBy(oldObj, idProp) : hashOf(oldObj),
newHash = objective ? indexBy(newObj, idProp) : hashOf(newObj),

@@ -70,0 +109,0 @@ curArray = [].concat(oldObj),

@@ -1,1 +0,1 @@

!function(root,factory){"function"==typeof define&&define.amd?define([],factory):"object"==typeof exports?module.exports=factory():root.simpleDiff=factory()}(this,function(){function diff(oldObj,newObj,ops){ops=ops||{};var i,len,prop,id,changes=[],oldPath=ops.oldPath||[],newPath=ops.newPath||[],ID_PROP=ops.idProp||"id",ADD_EVENT=ops.addEvent||"add",REMOVE_EVENT=ops.removeEvent||"remove",CHANGE_EVENT=ops.changeEvent||"change",ADD_ITEM_EVENT=ops.addItemEvent||"add-item",REMOVE_ITEM_EVENT=ops.removeItemEvent||"remove-item",MOVE_ITEM_EVENT=ops.moveItemEvent||"move-item",callback=ops.callback||function(item){changes.push(item)};if(!(isObject(oldObj)&&isObject(newObj)||oldObj===newObj))return callback({oldPath:oldPath,newPath:newPath,type:CHANGE_EVENT,oldValue:oldObj,newValue:newObj}),changes;if(isArray(oldObj)){var sample=oldObj.length>0?oldObj[0]:newObj[0];if(sample===UNDEFINED)return changes;var curIndex,oldIndex,objective="object"==typeof sample,idProp=objective&&ops.idProps&&(ops.idProps[oldPath.map(numberToAsterisk).join(".")]||ops.idProps[oldPath.join(".")])||ID_PROP,oldHash=objective?indexBy(oldObj,idProp):hashOf(oldObj),newHash=objective?indexBy(newObj,idProp):hashOf(newObj),curArray=[].concat(oldObj);for(i=0,len=oldObj.length;i<len;i++)id=objective?oldObj[i][idProp]:oldObj[i],newHash.hasOwnProperty(id)||(curIndex=curArray.indexOf(oldObj[i]),curArray.splice(curIndex,1),callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:curIndex,newIndex:-1}));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)||(callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}),i>=curArray.length?curArray.push(newObj[i]):curArray.splice(i,0,newObj[i]));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)&&(oldIndex=oldObj.indexOf(oldHash[id]),curIndex=curArray.indexOf(oldHash[id]),i!==curIndex&&(callback({oldPath:oldPath,newPath:newPath,type:MOVE_ITEM_EVENT,oldIndex:oldIndex,curIndex:curIndex,newIndex:i}),curArray.splice(curIndex,1),curArray.splice(i,0,oldHash[id])),diff(oldHash[id],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(oldIndex),newPath:newPath.concat(i)})))}else{for(prop in oldObj)oldObj.hasOwnProperty(prop)&&(newObj.hasOwnProperty(prop)?isObject(oldObj[prop])&&isObject(newObj[prop])?diff(oldObj[prop],newObj[prop],extend({},ops,{callback:callback,oldPath:oldPath.concat(prop),newPath:newPath.concat(prop)})):oldObj[prop]!==newObj[prop]&&callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:CHANGE_EVENT,oldValue:oldObj[prop],newValue:newObj[prop]}):callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:REMOVE_EVENT,oldValue:oldObj[prop],newValue:UNDEFINED}));for(prop in newObj)newObj.hasOwnProperty(prop)&&(oldObj.hasOwnProperty(prop)||callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:ADD_EVENT,oldValue:UNDEFINED,newValue:newObj[prop]}))}return changes}function isObject(object){return!!object&&"object"==typeof object}function isArray(array){return Array.isArray?Array.isArray(array):"[object Array]"===Object.prototype.toString.call(array)}function indexBy(array,id){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i][id]]=array[i];return hash}function hashOf(array){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i]]=array[i];return hash}function extend(target){for(var i=1,len=arguments.length;i<len;i++){var source=arguments[i];for(var prop in source)source.hasOwnProperty(prop)&&(target[prop]=source[prop])}return target}function numberToAsterisk(value){return"number"==typeof value?"*":value}var UNDEFINED;return diff});
!function(root,factory){"function"==typeof define&&define.amd?define([],factory):"object"==typeof exports?module.exports=factory():root.simpleDiff=factory()}(this,function(){function diff(oldObj,newObj,ops){ops=ops||{};var i,len,prop,id,changes=[],oldPath=ops.oldPath||[],newPath=ops.newPath||[],ID_PROP=ops.idProp||"id",ADD_EVENT=ops.addEvent||"add",REMOVE_EVENT=ops.removeEvent||"remove",CHANGE_EVENT=ops.changeEvent||"change",ADD_ITEM_EVENT=ops.addItemEvent||"add-item",REMOVE_ITEM_EVENT=ops.removeItemEvent||"remove-item",MOVE_ITEM_EVENT=ops.moveItemEvent||"move-item",callback=ops.callback||function(item){changes.push(item)};if(!(isObject(oldObj)&&isObject(newObj)||oldObj===newObj))return callback({oldPath:oldPath,newPath:newPath,type:CHANGE_EVENT,oldValue:oldObj,newValue:newObj}),changes;if(isArray(oldObj)){var idProp=ops.idProps&&(ops.idProps[oldPath.map(numberToAsterisk).join(".")]||ops.idProps[oldPath.join(".")])||ID_PROP;if("*"===idProp){var oldLength=oldObj.length,newLength=newObj.length;for(i=0,len=oldLength>newLength?oldLength:newLength;i<len;i++)i<oldLength&&i<newLength?diff(oldObj[i],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(i),newPath:newPath.concat(i)})):i>=oldLength?callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}):i>=newLength&&callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:newLength,newIndex:-1});return changes}var sample=oldObj.length>0?oldObj[0]:newObj[0];if(sample===UNDEFINED)return changes;var curIndex,oldIndex,objective="object"==typeof sample,oldHash=objective?indexBy(oldObj,idProp):hashOf(oldObj),newHash=objective?indexBy(newObj,idProp):hashOf(newObj),curArray=[].concat(oldObj);for(i=0,len=oldObj.length;i<len;i++)id=objective?oldObj[i][idProp]:oldObj[i],newHash.hasOwnProperty(id)||(curIndex=curArray.indexOf(oldObj[i]),curArray.splice(curIndex,1),callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:curIndex,newIndex:-1}));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)||(callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}),i>=curArray.length?curArray.push(newObj[i]):curArray.splice(i,0,newObj[i]));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)&&(oldIndex=oldObj.indexOf(oldHash[id]),curIndex=curArray.indexOf(oldHash[id]),i!==curIndex&&(callback({oldPath:oldPath,newPath:newPath,type:MOVE_ITEM_EVENT,oldIndex:oldIndex,curIndex:curIndex,newIndex:i}),curArray.splice(curIndex,1),curArray.splice(i,0,oldHash[id])),diff(oldHash[id],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(oldIndex),newPath:newPath.concat(i)})))}else{for(prop in oldObj)oldObj.hasOwnProperty(prop)&&(newObj.hasOwnProperty(prop)?isObject(oldObj[prop])&&isObject(newObj[prop])?diff(oldObj[prop],newObj[prop],extend({},ops,{callback:callback,oldPath:oldPath.concat(prop),newPath:newPath.concat(prop)})):oldObj[prop]!==newObj[prop]&&callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:CHANGE_EVENT,oldValue:oldObj[prop],newValue:newObj[prop]}):callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:REMOVE_EVENT,oldValue:oldObj[prop],newValue:UNDEFINED}));for(prop in newObj)newObj.hasOwnProperty(prop)&&(oldObj.hasOwnProperty(prop)||callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:ADD_EVENT,oldValue:UNDEFINED,newValue:newObj[prop]}))}return changes}function isObject(object){return!!object&&"object"==typeof object}function isArray(array){return Array.isArray?Array.isArray(array):"[object Array]"===Object.prototype.toString.call(array)}function indexBy(array,id){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i][id]]=array[i];return hash}function hashOf(array){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i]]=array[i];return hash}function extend(target){for(var i=1,len=arguments.length;i<len;i++){var source=arguments[i];for(var prop in source)source.hasOwnProperty(prop)&&(target[prop]=source[prop])}return target}function numberToAsterisk(value){return"number"==typeof value?"*":value}var UNDEFINED;return diff});

@@ -455,2 +455,90 @@ var expect = require('chai').expect,

});
it('should handle idProp: * to compare arrays as is', function () {
var changes = diff(
[
{a: 1},
{a: 2}
],
[
{a: 1},
{a: 2}
],
{idProp: '*'}
);
expect(changes.length).to.equal(0);
changes = diff(
[
{a: 1},
{a: 2}
],
[
{a: 2},
{a: 1},
{a: 3}
],
{idProp: '*'}
);
expect(changes).to.deep.equal([
{
oldPath: [0, 'a'],
newPath: [0, 'a'],
type: 'change',
oldValue: 1,
newValue: 2
},
{
oldPath: [1, 'a'],
newPath: [1, 'a'],
type: 'change',
oldValue: 2,
newValue: 1
},
{
oldPath: [],
newPath: [],
type: 'add-item',
oldIndex: -1,
curIndex: -1,
newIndex: 2,
newValue: {a: 3}
}
]);
changes = diff(
[
{a: 1},
{a: 2},
{a: 3},
{a: 4}
],
[
{a: 1},
{a: 2}
],
{idProp: '*'}
);
expect(changes).to.deep.equal([
{
oldPath: [],
newPath: [],
type: 'remove-item',
oldIndex: 2,
curIndex: 2,
newIndex: -1
},
{
oldPath: [],
newPath: [],
type: 'remove-item',
oldIndex: 3,
curIndex: 2,
newIndex: -1
}
]);
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc