2024-08-14 15:17:51 +08:00

82 lines
1.6 KiB
JavaScript

'use strict';
var _ = require('lodash');
var jsondiffpatch = require('jsondiffpatch');
var ChangeHandler = require('./change-handler');
function Differ() { }
module.exports = Differ;
Differ.prototype.createDiff = function(a, b) {
// create a configured instance, match objects by name
var diffpatcher = jsondiffpatch.create({
objectHash: function(obj) {
return obj.id || JSON.stringify(obj);
}
});
return diffpatcher.diff(a, b);
};
Differ.prototype.diff = function(a, b, handler) {
handler = handler || new ChangeHandler();
function walk(diff, model) {
_.forEach(diff, function(d, key) {
// is array
if (d._t === 'a') {
_.forEach(d, function(val, idx) {
if (idx === '_t') {
return;
}
var removed = /^_/.test(idx),
added = !removed && _.isArray(val),
moved = removed && val[0] === '';
idx = parseInt(removed ? idx.slice(1) : idx, 10);
if (added || (removed && !moved)) {
handler[removed ? 'removed' : 'added'](model, key, val[0], idx);
} else
if (moved) {
handler.moved(model, key, val[1], val[2]);
} else {
walk(val, model[key][idx]);
}
});
} else {
if (_.isArray(d)) {
handler.changed(model, key, d[0], d[1]);
} else {
handler.changed(model, key);
walk(d, model[key]);
}
}
});
}
var diff = this.createDiff(a, b);
walk(diff, b, handler);
return handler;
};
module.exports.diff = function(a, b, handler) {
return new Differ().diff(a, b, handler);
};