Plato on Github
Report Home
node_modules/json-diff/lib/index.js
Maintainability
51.65
Lines of code
222
Difficulty
107.80
Estimated Errors
2.63
Function weight
By Complexity
By SLOC
// Generated by IcedCoffeeScript 1.3.3f (function() { var SequenceMatcher, arrayDiff, colorize, descalarize, diff, diffScore, diffString, diffWithScore, extendedTypeOf, findMatchingObject, isScalar, isScalarized, objectDiff, scalarize, __hasProp = {}.hasOwnProperty; SequenceMatcher = require('difflib').SequenceMatcher; extendedTypeOf = require('./util').extendedTypeOf; colorize = require('./colorize').colorize; isScalar = function(obj) { return typeof obj !== 'object'; }; objectDiff = function(obj1, obj2) { var change, key, keys1, keys2, result, score, subscore, value1, value2, _ref, _ref1; result = {}; score = 0; keys1 = Object.keys(obj1); keys2 = Object.keys(obj2); for (key in obj1) { if (!__hasProp.call(obj1, key)) continue; value1 = obj1[key]; if (!(!(key in obj2))) continue; result["" + key + "__deleted"] = value1; score -= 30; } for (key in obj2) { if (!__hasProp.call(obj2, key)) continue; value2 = obj2[key]; if (!(!(key in obj1))) continue; result["" + key + "__added"] = value2; score -= 30; } for (key in obj1) { if (!__hasProp.call(obj1, key)) continue; value1 = obj1[key]; if (!(key in obj2)) continue; score += 20; value2 = obj2[key]; _ref = diffWithScore(value1, value2), subscore = _ref[0], change = _ref[1]; if (change) result[key] = change; score += Math.min(20, Math.max(-10, subscore / 5)); } if (Object.keys(result).length === 0) { _ref1 = [100 * Object.keys(obj1).length, void 0], score = _ref1[0], result = _ref1[1]; } else { score = Math.max(0, score); } return [score, result]; }; findMatchingObject = function(item, fuzzyOriginals) { var bestMatch, candidate, key, score; bestMatch = null; for (key in fuzzyOriginals) { if (!__hasProp.call(fuzzyOriginals, key)) continue; candidate = fuzzyOriginals[key]; if (key !== '__next') { if (extendedTypeOf(item) === extendedTypeOf(candidate)) { score = diffScore(item, candidate); if (!bestMatch || score > bestMatch.score) { bestMatch = { score: score, key: key }; } } } } return bestMatch; }; scalarize = function(array, originals, fuzzyOriginals) { var bestMatch, item, proxy, _i, _len, _results; _results = []; for (_i = 0, _len = array.length; _i < _len; _i++) { item = array[_i]; if (isScalar(item)) { _results.push(item); } else if (fuzzyOriginals && (bestMatch = findMatchingObject(item, fuzzyOriginals)) && bestMatch.score > 40) { originals[bestMatch.key] = item; _results.push(bestMatch.key); } else { proxy = "__$!SCALAR" + originals.__next++; originals[proxy] = item; _results.push(proxy); } } return _results; }; isScalarized = function(item, originals) { return (typeof item === 'string') && (item in originals); }; descalarize = function(item, originals) { if (isScalarized(item, originals)) { return originals[item]; } else { return item; } }; arrayDiff = function(obj1, obj2, stats) { var allEqual, change, i, i1, i2, item, item1, item2, j, j1, j2, op, opcodes, originals1, originals2, result, score, seq1, seq2, _i, _j, _k, _l, _len, _m, _n, _ref; originals1 = { __next: 1 }; seq1 = scalarize(obj1, originals1); originals2 = { __next: originals1.__next }; seq2 = scalarize(obj2, originals2, originals1); opcodes = new SequenceMatcher(null, seq1, seq2).getOpcodes(); result = []; score = 0; allEqual = true; for (_i = 0, _len = opcodes.length; _i < _len; _i++) { _ref = opcodes[_i], op = _ref[0], i1 = _ref[1], i2 = _ref[2], j1 = _ref[3], j2 = _ref[4]; if (op !== 'equal') allEqual = false; switch (op) { case 'equal': for (i = _j = i1; i1 <= i2 ? _j < i2 : _j > i2; i = i1 <= i2 ? ++_j : --_j) { item = seq1[i]; if (isScalarized(item, originals1)) { if (!isScalarized(item, originals2)) { throw new AssertionError("internal bug: isScalarized(item, originals1) != isScalarized(item, originals2) for item " + (JSON.stringify(item))); } item1 = descalarize(item, originals1); item2 = descalarize(item, originals2); change = diff(item1, item2); if (change) { result.push(['~', change]); allEqual = false; } else { result.push([' ']); } } else { result.push([' ', item]); } score += 10; } break; case 'delete': for (i = _k = i1; i1 <= i2 ? _k < i2 : _k > i2; i = i1 <= i2 ? ++_k : --_k) { result.push(['-', descalarize(seq1[i], originals1)]); score -= 5; } break; case 'insert': for (j = _l = j1; j1 <= j2 ? _l < j2 : _l > j2; j = j1 <= j2 ? ++_l : --_l) { result.push(['+', descalarize(seq2[j], originals2)]); score -= 5; } break; case 'replace': for (i = _m = i1; i1 <= i2 ? _m < i2 : _m > i2; i = i1 <= i2 ? ++_m : --_m) { result.push(['-', descalarize(seq1[i], originals1)]); score -= 5; } for (j = _n = j1; j1 <= j2 ? _n < j2 : _n > j2; j = j1 <= j2 ? ++_n : --_n) { result.push(['+', descalarize(seq2[j], originals2)]); score -= 5; } } } if (allEqual || (opcodes.length === 0)) { result = void 0; score = 100; } else { score = Math.max(0, score); } return [score, result]; }; diffWithScore = function(obj1, obj2) { var type1, type2; type1 = extendedTypeOf(obj1); type2 = extendedTypeOf(obj2); if (type1 === type2) { switch (type1) { case 'object': return objectDiff(obj1, obj2); case 'array': return arrayDiff(obj1, obj2); } } if (obj1 !== obj2) { return [ 0, { __old: obj1, __new: obj2 } ]; } else { return [100, void 0]; } }; diff = function(obj1, obj2) { var change, score, _ref; _ref = diffWithScore(obj1, obj2), score = _ref[0], change = _ref[1]; return change; }; diffScore = function(obj1, obj2) { var change, score, _ref; _ref = diffWithScore(obj1, obj2), score = _ref[0], change = _ref[1]; return score; }; diffString = function(obj1, obj2, options) { return colorize(diff(obj1, obj2), options); }; module.exports = { diff: diff, diffString: diffString }; }).call(this);