deepdash
Version:
➔ 𝐃eep standalone lib / 𝐋odash extension: ✓ eachDeep ✓ filterDeep ✓ mapDeep ✓ reduceDeep ✓ pickDeep ✓ omitDeep ✓ keysDeep ✓ index ✓ condenseDeep ⋮ Parents stack ⋮ Circular check ⋮ Leaves only mode ⋮ Children mode ⋮ cherry-pick ⋮ esm
264 lines (249 loc) • 8.58 kB
JavaScript
var getCondense = require('./getCondense.js');
var isObject = require('./private/isObject.js');
var getEachDeep = require('./getEachDeep.js');
function getFilterDeep(_) {
var eachDeep = getEachDeep(_);
var condense = getCondense();
function filterDeep(obj, predicate, options) {
predicate = _.iteratee(predicate);
if (!options) {
options = {};
} else {
options = _.cloneDeep(options);
if (options.leafsOnly !== undefined) {
options.leavesOnly = options.leafsOnly;
}
}
if (!options.onTrue) {
options.onTrue = {};
}
if (!options.onFalse) {
options.onFalse = {};
}
if (!options.onUndefined) {
options.onUndefined = {};
}
if (options.childrenPath !== undefined) {
if (options.onTrue.skipChildren === undefined) {
options.onTrue.skipChildren = false;
}
if (options.onUndefined.skipChildren === undefined) {
options.onUndefined.skipChildren = false;
}
if (options.onFalse.skipChildren === undefined) {
options.onFalse.skipChildren = false;
}
if (options.onTrue.cloneDeep === undefined) {
options.onTrue.cloneDeep = true;
}
if (options.onUndefined.cloneDeep === undefined) {
options.onUndefined.cloneDeep = true;
}
if (options.onFalse.cloneDeep === undefined) {
options.onFalse.cloneDeep = true;
}
}
options = _.merge(
{
checkCircular: false,
keepCircular: true,
//replaceCircularBy: <by>,
leavesOnly: options.childrenPath === undefined,
condense: true,
cloneDeep: _.cloneDeep,
pathFormat: 'string',
onTrue: { skipChildren: true, cloneDeep: true, keepIfEmpty: true },
onUndefined: {
skipChildren: false,
cloneDeep: false,
keepIfEmpty: false,
},
onFalse: {
skipChildren: true,
cloneDeep: false,
keepIfEmpty: false,
},
},
options
);
var eachDeepOptions = {
pathFormat: options.pathFormat,
checkCircular: options.checkCircular,
childrenPath: options.childrenPath,
includeRoot: options.includeRoot,
rootIsChildren: options.rootIsChildren,
ownPropertiesOnly: options.ownPropertiesOnly,
callbackAfterIterate: true,
leavesOnly: false,
};
var resIsArray = Array.isArray(obj);
var res = resIsArray ? [] : isObject(obj) ? {} : null;
var toCondense = options.condense ? [] : false;
eachDeep(
obj,
function (value, key, parent, context) {
if (!context.afterIterate) {
context.info._filterDeep = {};
if (!context.isCircular) {
var reply =
!options.leavesOnly || context.isLeaf
? predicate(value, key, parent, context)
: undefined;
if (!isObject(reply)) {
if (reply === undefined) {
reply = options.onUndefined;
} else if (reply) {
reply = options.onTrue;
} else {
reply = options.onFalse;
}
}
context.info._filterDeep.reply = reply;
context.info._filterDeep.empty =
reply.empty === undefined ? true : reply.empty;
if (reply.keepIfEmpty || !reply.skipChildren) {
if (options.cloneDeep && reply.cloneDeep) {
if (context.path !== undefined) {
var children = takeResultParent(context, res);
context.info._filterDeep.res = children[
key
] = options.cloneDeep(value);
} else {
context.info._filterDeep.res = res = options.cloneDeep(value);
}
} else {
if (context.path !== undefined) {
var children$1 = takeResultParent(context, res);
context.info._filterDeep.res = children$1[key] = context.info
.isArray
? []
: context.info.isObject
? {}
: value;
} else {
context.info._filterDeep.res = res = context.info.isArray
? []
: context.info.isObject
? {}
: value;
}
}
}
return !reply.skipChildren;
} else {
var children$2 = takeResultParent(context, res);
if (!options.keepCircular) {
delete children$2[key];
if (
toCondense &&
((children$2 === context.parent.info._filterDeep.res &&
context.parent.info.isArray) ||
Array.isArray(children$2)) &&
!context.parent.info._filterDeep.isSparse
) {
context.parent.info._filterDeep.isSparse = true;
toCondense.push(context.parent.info);
}
context.info._filterDeep.excluded = true;
} else {
context.info._filterDeep.res = children$2[key] =
'replaceCircularBy' in options
? options.replaceCircularBy
: context.circularParent.path !== undefined
? context.circularParent.info._filterDeep.res
: res;
}
return false;
}
} else if (context.afterIterate && !context.isCircular) {
var reply$1 = context.info._filterDeep.reply;
if (context.info._filterDeep.empty && !reply$1.keepIfEmpty) {
if (context.path === undefined) {
res = null;
} else {
var children$3 = takeResultParent(context, res);
delete children$3[key];
if (
toCondense &&
((children$3 === context.parent.info._filterDeep.res &&
context.parent.info.isArray) ||
Array.isArray(children$3)) &&
!context.parent.info._filterDeep.isSparse
) {
context.parent.info._filterDeep.isSparse = true;
toCondense.push(context.parent.info);
}
context.info._filterDeep.excluded = true;
}
} else {
var parent$1 = context.parent;
while (parent$1) {
// if (!parent.info._filterDeep) {
// parent.info._filterDeep = {};
// }
if (!parent$1.info._filterDeep.reply) {
parent$1.info._filterDeep.reply = options.onUndefined;
}
if (!parent$1.info._filterDeep.empty) {
break;
}
parent$1.info._filterDeep.empty = false;
parent$1 = parent$1.parent;
}
}
return;
}
},
eachDeepOptions
);
if (toCondense) {
for (var i = 0; i < toCondense.length; i++) {
var info = toCondense[i];
if (info._filterDeep.isSparse && !info._filterDeep.excluded) {
condense(info.children);
}
}
if (resIsArray) {
condense(res);
}
}
if (resIsArray && !res.length && !eachDeepOptions.includeRoot) {
return null;
}
return res;
}
return filterDeep;
function takeResultParent(context, res) {
if (context.parent.info.children) {
return context.parent.info.children;
}
if (!context.parent.info._filterDeep) {
context.parent.info._filterDeep = {};
}
var parent = context.parent.info._filterDeep.res;
if (parent === undefined) {
//if (!context.parent.parent) {
parent = context.parent.info._filterDeep.res = res;
// } else {
// parent = context.parent.info._filterDeep.res = Array.isArray(context.parent.value)
// ? []
// : {};
// }
}
if (context._item.childrenPath) {
var oParent = context.parent.value;
for (var i = 0; i < context._item.childrenPath.length; i++) {
var childKey = context._item.childrenPath[i];
oParent = oParent[childKey];
if (!parent[childKey]) {
parent[childKey] = Array.isArray(oParent) ? [] : {};
}
parent = parent[childKey];
}
}
context.parent.info.children = parent;
return parent;
}
}
module.exports = getFilterDeep;
;