immutable-recursive
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -16,175 +16,253 @@ 'use strict'; | ||
var nestedMaps = (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B", | ||
c: "C", | ||
d: { | ||
e: "E" | ||
} | ||
}, | ||
f: "F" | ||
a: { | ||
b: "B", | ||
c: "C", | ||
d: { | ||
e: "E" | ||
} | ||
}, | ||
f: "F" | ||
}); | ||
var childLists = (0, _immutable.fromJS)({ | ||
name: "root", | ||
children: [{ | ||
name: "child 1", | ||
children: [{ name: "grandchild 1" }, { name: "grandchild 2" }] | ||
}, { | ||
name: "child 2", | ||
children: [] | ||
}, { name: "child 3" }] | ||
name: "root", | ||
children: [{ | ||
name: "child 1", | ||
children: [{ name: "grandchild 1" }, { name: "grandchild 2" }] | ||
}, { | ||
name: "child 2", | ||
children: [] | ||
}, { name: "child 3" }] | ||
}); | ||
(0, _tape2.default)('deepMap', function (test) { | ||
test.plan(3); | ||
test.plan(3); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMap)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMap iterates through every node using a childPath'); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMap)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMap iterates through every node using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMap)(function (item) { | ||
// normally deepMap on trees that don't require childPaths is a bit pointless | ||
// because you'll almost certainly have to deal with leaves and parents differently | ||
return (0, _utils.isLeaf)(item) ? item + "!" : item.set('abc', 123); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!", | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMap)(function (item) { | ||
// normally deepMap on trees that don't require childPaths is a bit pointless | ||
// because you'll almost certainly have to deal with leaves and parents differently | ||
return (0, _utils.isLeaf)(item) ? item + "!" : item.set('abc', 123); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!", | ||
abc: 123 | ||
}, | ||
abc: 123 | ||
}, | ||
f: "F!", | ||
abc: 123 | ||
}, | ||
abc: 123 | ||
}, | ||
f: "F!", | ||
abc: 123 | ||
})), 'deepMap iterates through every node without using a childPath (kind of pointless)'); | ||
})), 'deepMap iterates through every node without using a childPath (kind of pointless)'); | ||
var names = []; | ||
childLists.update((0, _map.deepMap)(function (item) { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), test.ok((0, _immutable.is)((0, _immutable.fromJS)(names), (0, _immutable.fromJS)(['grandchild 1', 'grandchild 2', 'child 1', 'child 2', 'child 3', 'root'])), 'deepMap iterates from the outside in'); | ||
var names = []; | ||
childLists.update((0, _map.deepMap)(function (item) { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), test.ok((0, _immutable.is)((0, _immutable.fromJS)(names), (0, _immutable.fromJS)(['grandchild 1', 'grandchild 2', 'child 1', 'child 2', 'child 3', 'root'])), 'deepMap iterates from the outside in'); | ||
}); | ||
(0, _tape2.default)('deepMapLeaves', function (test) { | ||
test.plan(2); | ||
test.plan(2); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapLeaves)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
children: [{ | ||
name: "child 1", | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMapLeaves iterates through only leaves when using a childPath'); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapLeaves)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
children: [{ | ||
name: "child 1", | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMapLeaves iterates through only leaves when using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapLeaves)(function (item) { | ||
return item + "!"; | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!" | ||
} | ||
}, | ||
f: "F!" | ||
})), 'deepMapLeaves iterates through only leaves when not using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapLeaves)(function (item) { | ||
return item + "!"; | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!" | ||
} | ||
}, | ||
f: "F!" | ||
})), 'deepMapLeaves iterates through only leaves when not using a childPath'); | ||
}); | ||
(0, _tape2.default)('deepMapParents', function (test) { | ||
test.plan(2); | ||
test.plan(2); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapParents)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1" }, { name: "grandchild 2" }] | ||
}, { | ||
name: "child 2", | ||
children: [] | ||
}, { name: "child 3" }] | ||
})), 'deepMapParents iterates through every parent node using a childPath'); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapParents)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1" }, { name: "grandchild 2" }] | ||
}, { | ||
name: "child 2", | ||
children: [] | ||
}, { name: "child 3" }] | ||
})), 'deepMapParents iterates through every parent node using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapParents)(function (item) { | ||
return item.set('abc', 123); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B", | ||
c: "C", | ||
d: { | ||
e: "E", | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapParents)(function (item) { | ||
return item.set('abc', 123); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B", | ||
c: "C", | ||
d: { | ||
e: "E", | ||
abc: 123 | ||
}, | ||
abc: 123 | ||
}, | ||
f: "F", | ||
abc: 123 | ||
}, | ||
abc: 123 | ||
}, | ||
f: "F", | ||
abc: 123 | ||
})), 'deepMapParents iterates through every parent node without using a childPath'); | ||
})), 'deepMapParents iterates through every parent node without using a childPath'); | ||
}); | ||
(0, _tape2.default)('deepMapOutwards', function (test) { | ||
test.plan(3); | ||
test.plan(3); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapOutwards)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMapOutwards iterates through every node using a childPath'); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapOutwards)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMapOutwards iterates through every node using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapOutwards)(function (item) { | ||
// normally deepMapOutwards on trees that don't require childPaths is a bit pointless | ||
// because you'll almost certainly have to deal with leaves and parents differently | ||
return (0, _utils.isLeaf)(item) ? item + "!" : item.set('abc', '123'); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!", | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapOutwards)(function (item) { | ||
// normally deepMapOutwards on trees that don't require childPaths is a bit pointless | ||
// because you'll almost certainly have to deal with leaves and parents differently | ||
return (0, _utils.isLeaf)(item) ? item + "!" : item.set('abc', '123'); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!", | ||
abc: "123!" | ||
}, | ||
abc: "123!" | ||
}, | ||
f: "F!", | ||
abc: "123!" | ||
}, | ||
abc: "123!" | ||
}, | ||
f: "F!", | ||
abc: "123!" | ||
})), 'deepMapOutwards iterates through every node without using a childPath (kind of pointless)'); | ||
})), 'deepMapOutwards iterates through every node without using a childPath (kind of pointless)'); | ||
var names = []; | ||
childLists.update((0, _map.deepMapOutwards)(function (item) { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), test.ok((0, _immutable.is)((0, _immutable.fromJS)(names), (0, _immutable.fromJS)(['root', 'child 1', 'grandchild 1', 'grandchild 2', 'child 2', 'child 3'])), 'deepMapOutwards iterates from the inside out'); | ||
var names = []; | ||
childLists.update((0, _map.deepMapOutwards)(function (item) { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), test.ok((0, _immutable.is)((0, _immutable.fromJS)(names), (0, _immutable.fromJS)(['root', 'child 1', 'grandchild 1', 'grandchild 2', 'child 2', 'child 3'])), 'deepMapOutwards iterates from the inside out'); | ||
}); | ||
(0, _tape2.default)('deepMapLeavesOutwards', function (test) { | ||
test.plan(3); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapLeavesOutwards)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
children: [{ | ||
name: "child 1", | ||
children: [{ name: "grandchild 1", abc: 123 }, { name: "grandchild 2", abc: 123 }] | ||
}, { | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, { name: "child 3", abc: 123 }] | ||
})), 'deepMapLeavesOutwards iterates through every leaf node using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapLeavesOutwards)(function (item) { | ||
return item + "!"; | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!" | ||
} | ||
}, | ||
f: "F!" | ||
})), 'deepMapLeavesOutwards iterates through every leaf node without using a childPath'); | ||
var names = []; | ||
childLists.update((0, _map.deepMapLeavesOutwards)(function (item) { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), test.ok((0, _immutable.is)((0, _immutable.fromJS)(names), (0, _immutable.fromJS)(['grandchild 1', 'grandchild 2', 'child 2', 'child 3'])), 'deepMapLeavesOutwards iterates from the inside out'); | ||
}); | ||
(0, _tape2.default)('deepMapParentsOutwards', function (test) { | ||
test.plan(3); | ||
test.ok((0, _immutable.is)(childLists.update((0, _map.deepMapParentsOutwards)(function (item) { | ||
return item.set('abc', 123); | ||
}, ['children'])), (0, _immutable.fromJS)({ | ||
name: "root", | ||
abc: 123, | ||
children: [{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [{ name: "grandchild 1" }, { name: "grandchild 2" }] | ||
}, { | ||
name: "child 2", | ||
children: [] | ||
}, { name: "child 3" }] | ||
})), 'deepMapParentsOutwards iterates through every parent node using a childPath'); | ||
test.ok((0, _immutable.is)(nestedMaps.update((0, _map.deepMapParentsOutwards)(function (item) { | ||
return item.set('abc', '123'); | ||
})), (0, _immutable.fromJS)({ | ||
a: { | ||
b: "B", | ||
c: "C", | ||
d: { | ||
e: "E", | ||
abc: "123" | ||
}, | ||
abc: "123" | ||
}, | ||
f: "F", | ||
abc: "123" | ||
})), 'deepMapParentsOutwards iterates through every parent node without using a childPath'); | ||
var names = []; | ||
childLists.update((0, _map.deepMapParentsOutwards)(function (item) { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), test.ok((0, _immutable.is)((0, _immutable.fromJS)(names), (0, _immutable.fromJS)(['root', 'child 1'])), 'deepMapParentsOutwards iterates from the inside out'); | ||
}); |
@@ -36,4 +36,2 @@ 'use strict'; | ||
return (0, _utils.isLeaf)(item, childPath) ? item : item.updateIn(childPath, function (kids) { | ||
console.log("..."); | ||
console.log(item); | ||
return kids.filter(function (kid, kidKey) { | ||
@@ -40,0 +38,0 @@ return filterer(kid, nodePath.push(kidKey), tree); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.deepPick = exports.deepFilter = exports.deepMapParents = exports.deepMapLeaves = exports.deepMap = exports.deepDeleteChildren = exports.deepDelete = exports.deepSetChildren = exports.deepSet = exports.deepUpdateChildren = exports.deepUpdate = exports.deepGetChildren = exports.deepGet = undefined; | ||
exports.deepPick = exports.deepFilter = exports.deepReduceParentsOutwards = exports.deepReduceLeavesOutwards = exports.deepReduceOutwards = exports.deepReduceParents = exports.deepReduceLeaves = exports.deepReduce = exports.deepMapParentsOutwards = exports.deepMapLeavesOutwards = exports.deepMapOutwards = exports.deepMapParents = exports.deepMapLeaves = exports.deepMap = exports.deepDeleteChildren = exports.deepDelete = exports.deepSetChildren = exports.deepSet = exports.deepUpdateChildren = exports.deepUpdate = exports.deepGetChildren = exports.deepGet = undefined; | ||
@@ -89,3 +89,60 @@ var _get = require('./get'); | ||
}); | ||
Object.defineProperty(exports, 'deepMapOutwards', { | ||
enumerable: true, | ||
get: function get() { | ||
return _map.deepMapOutwards; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepMapLeavesOutwards', { | ||
enumerable: true, | ||
get: function get() { | ||
return _map.deepMapLeavesOutwards; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepMapParentsOutwards', { | ||
enumerable: true, | ||
get: function get() { | ||
return _map.deepMapParentsOutwards; | ||
} | ||
}); | ||
var _reduce = require('./reduce'); | ||
Object.defineProperty(exports, 'deepReduce', { | ||
enumerable: true, | ||
get: function get() { | ||
return _reduce.deepReduce; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepReduceLeaves', { | ||
enumerable: true, | ||
get: function get() { | ||
return _reduce.deepReduceLeaves; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepReduceParents', { | ||
enumerable: true, | ||
get: function get() { | ||
return _reduce.deepReduceParents; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepReduceOutwards', { | ||
enumerable: true, | ||
get: function get() { | ||
return _reduce.deepReduceOutwards; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepReduceLeavesOutwards', { | ||
enumerable: true, | ||
get: function get() { | ||
return _reduce.deepReduceLeavesOutwards; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deepReduceParentsOutwards', { | ||
enumerable: true, | ||
get: function get() { | ||
return _reduce.deepReduceParentsOutwards; | ||
} | ||
}); | ||
var _filter = require('./filter'); | ||
@@ -92,0 +149,0 @@ |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.deepMapOutwards = exports.deepMapParents = exports.deepMapLeaves = exports.deepMap = undefined; | ||
exports.deepMapParentsOutwards = exports.deepMapLeavesOutwards = exports.deepMapOutwards = exports.deepMapParents = exports.deepMapLeaves = exports.deepMap = undefined; | ||
@@ -40,6 +40,17 @@ var _immutable = require('immutable'); | ||
var mappedSelf = mapper(self, nodePath, tree); | ||
if (options.onlyParents && (0, _utils.isLeaf)(self, childPath)) { | ||
return self; | ||
} | ||
if ((0, _utils.isLeaf)(mappedSelf, childPath)) { | ||
return mappedSelf; | ||
var mappedSelf; | ||
if (options.onlyLeaves) { | ||
mappedSelf = self; | ||
if ((0, _utils.isLeaf)(mappedSelf, childPath)) { | ||
return mapper(self, nodePath, tree); | ||
} | ||
} else { | ||
mappedSelf = mapper(self, nodePath, tree); | ||
if ((0, _utils.isLeaf)(mappedSelf, childPath)) { | ||
return mappedSelf; | ||
} | ||
} | ||
@@ -75,6 +86,6 @@ | ||
/** | ||
* Once fully applied, this iterates through the leaf nodes in the provided tree, passing them all through a mapper function. Leaf nodes are nodes that have no child nodes. | ||
* Once fully applied, this iterates through the leaf nodes in the provided tree, passing them all through a `mapper` function. Leaf nodes are nodes that have no child nodes. | ||
* Nodes are processed branch by branch, in the order that Immutable maps through the child iterables. | ||
* | ||
* @param {Mapper} mapper The function to be called for every node in the tree, the results of which will be used to create the modified tree. | ||
* @param {Mapper} mapper The function to be called for every leaf node in the tree, the results of which will be used to create the modified tree. | ||
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
@@ -93,6 +104,6 @@ * @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`. | ||
/** | ||
* Once fully applied, this iterates through the parent nodes in the provided tree, passing them all through a mapper function. Parent nodes are nodes that have child nodes. | ||
* Once fully applied, this iterates through the parent nodes in the provided tree, passing them all through a `mapper` function. Parent nodes are nodes that have child nodes. | ||
* Nodes are processed branch by branch in the order that Immutable maps through the child iterables, inward from leaves to the root node. | ||
* | ||
* @param {Mapper} mapper The function to be called for every node in the tree. | ||
* @param {Mapper} mapper The function to be called for every parent node in the tree. | ||
* the results of which will be used to create the modified iterable. | ||
@@ -118,4 +129,4 @@ * @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
* | ||
* - If you modify a node's children, then those children will already be modified by the time they are called by the mapper function. | ||
* - Because of the above, if a node removes or renames its own children iterable then those children will not be passed through the mapper function. | ||
* - If you modify a node's children, then those children will already be modified by the time they are called by the `mapper` function. | ||
* - Because of the above, if a node removes or renames its own children iterable then those children will not be passed through the `mapper` function. | ||
* | ||
@@ -135,5 +146,48 @@ * @param {Mapper} mapper The function to be called for every node in the tree, the results of which will be used to create the modified tree. | ||
/** | ||
* Once fully applied, this iterates through the leaf nodes in the provided tree, passing them all through a `mapper` function. | ||
* Nodes are processed branch by branch in the order that Immutable maps through the child iterables, outwards from the root node to the leaf nodes. | ||
* Sibling nodes are processed in the order that Immutable iterates through collections. | ||
* | ||
* @param {Mapper} mapper The function to be called for every leaf node in the tree, the results of which will be used to create the modified tree. | ||
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
* @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`. | ||
*/ | ||
function deepMapLeavesOutwards(mapper) { | ||
var childPath = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; | ||
return function (tree) { | ||
return mapRecursiveOutwards(tree, (0, _utils.asList)(childPath), mapper, tree, { onlyLeaves: true }); | ||
}; | ||
} | ||
/** | ||
* Once fully applied, this iterates through the parent nodes in the provided tree, passing them all through a `mapper` function. | ||
* Nodes are processed branch by branch in the order that Immutable maps through the child iterables, outwards from the root node to the leaf nodes. | ||
* Sibling nodes are processed in the order that Immutable iterates through collections. | ||
* | ||
* Because this moves from the root node outwards this function behaves quite differently to the other deep map functions. | ||
* | ||
* - If you modify a node's children, then those children will already be modified by the time they are called by the `mapper` function. | ||
* - Because of the above, if a node removes or renames its own children iterable then those children will not be passed through the `mapper` function. | ||
* | ||
* @param {Mapper} mapper The function to be called for every parent node in the tree, the results of which will be used to create the modified tree. | ||
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
* @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`. | ||
*/ | ||
function deepMapParentsOutwards(mapper) { | ||
var childPath = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; | ||
return function (tree) { | ||
return mapRecursiveOutwards(tree, (0, _utils.asList)(childPath), mapper, tree, { onlyParents: true }); | ||
}; | ||
} | ||
exports.deepMap = deepMap; | ||
exports.deepMapLeaves = deepMapLeaves; | ||
exports.deepMapParents = deepMapParents; | ||
exports.deepMapOutwards = deepMapOutwards; | ||
exports.deepMapOutwards = deepMapOutwards; | ||
exports.deepMapLeavesOutwards = deepMapLeavesOutwards; | ||
exports.deepMapParentsOutwards = deepMapParentsOutwards; |
@@ -37,2 +37,3 @@ 'use strict'; | ||
* @param {*} node The node to make blank. | ||
* @param {ChildPath} [childPath=null] An Array or List of keys indicating where to find the node's children. | ||
* @return {*} The blank node. | ||
@@ -39,0 +40,0 @@ */ |
{ | ||
"name": "immutable-recursive", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Extra functions for use with Immutable.js to better handle tree structures / nested data and recursive iteration", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -18,35 +18,45 @@ # immutable-recursive | ||
| Function | Plan | Write | Tests | Document | Examples | | ||
| -------- | ---- | ----- | ----- | -------- | -------- | | ||
| deepGet | Done | Done | Done | Done | | | ||
| deepGetChildren | Done | Done | Done | Done | | | ||
| deepSet | Done | Done | Done | Done | | | ||
| deepSetChildren | Done | Done | Done | Done | | | ||
| deepUpdate | Done | Done | Done | Done | | | ||
| deepUpdateChildren | Done | Done | Done | Done | | | ||
| deepDelete | Done | Done | Done | Done | | | ||
| deepDeleteChildren | Done | Done | Done | Done | | | ||
| deepDeleteCollapse | In progress | | | | | | ||
| deepMap | Done | Done | In progress | In progress | | | ||
| deepMapLeaves | Done | Done | In progress | Done | | | ||
| deepMapParents | Done | Done | In progress | Done | | | ||
| deepMapOutward | Done | Done | In progress | Done | | | ||
| deepMapParentsOutward | Done | | | | | | ||
| deepReduce | In progress | | | | | | ||
| deepFilter | Done | Done | In progress | Done | | | ||
| deepFilterCollapse | In progress | | | | | | ||
| deepPick | Done | Done | Done | Done | | | ||
| deepSortBy | Done | In progress | | | | | ||
| deconstruct | Done | In progress | | | | | ||
| reconstruct | In progress | | | | | | ||
| asList | Done | Done | Done | Done | Done | | ||
| blankNode | Done | Done | Done | | | | ||
| nodePathToKeys | Done | Done | Done | Done | Done | | ||
| nodePathToKeysChildren | Done | Done | Done | Done | Done | | ||
| isLeaf | Done | Done | Done | Done | Done | | ||
| pick | Done | Done | Done | Done | Done | | ||
| isSiblingOf | Done | | | | | | ||
| isParentOf | Done | | | | | | ||
| isAncestorOf | Done | | | | | | ||
| getCommonAncestor | | | | | | | ||
| Function | Plan | Write | Tests | Document | Examples | | ||
| -------- | ---- | ----- | ----- | -------- | -------- | | ||
| deepGet | Done | Done | Done | Done | | | ||
| deepGetChildren | Done | Done | Done | Done | | | ||
| deepSet | Done | Done | Done | Done | | | ||
| deepSetChildren | Done | Done | Done | Done | | | ||
| deepUpdate | Done | Done | Done | Done | | | ||
| deepUpdateChildren | Done | Done | Done | Done | | | ||
| deepDelete | Done | Done | Done | Done | | | ||
| deepDeleteChildren | Done | Done | Done | Done | | | ||
| deepDeleteCollapse | In progress | | | | | | ||
| deepMap | Done | Done | Done | In progress | | | ||
| deepMapLeaves | Done | Done | Done | Done | | | ||
| deepMapParents | Done | Done | Done | Done | | | ||
| deepMapOutward | Done | Done | Done | Done | | | ||
| deepMapLeavesOutward | Done | Done | Done | Done | | | ||
| deepMapParentsOutward | Done | Done | Done | Done | | | ||
| deepReduce | Done | Done | Done | Done | | | ||
| deepReduceLeaves | Done | Done | Done | Done | | | ||
| deepReduceParents | Done | Done | Done | Done | | | ||
| deepReduceOutward | Done | Done | Done | Done | | | ||
| deepReduceLeavesOutward | Done | Done | Done | Done | | | ||
| deepReduceParentsOutward | Done | Done | Done | Done | | | ||
| deepFilter | Done | Done | Done | Done | | | ||
| deepFilterCollapse | In progress | | | | | | ||
| deepPick | Done | Done | Done | Done | | | ||
| deconstruct | Done | In progress | | | | | ||
| reconstruct | In progress | | | | | | ||
| asList | Done | Done | Done | Done | Done | | ||
| blankNode | Done | Done | Done | Done | | | ||
| nodePathToKeys | Done | Done | Done | Done | Done | | ||
| nodePathToKeysChildren | Done | Done | Done | Done | Done | | ||
| isLeaf | Done | Done | Done | Done | Done | | ||
| pick | Done | Done | Done | Done | Done | | ||
| isSiblingOf | Done | | | | | | ||
| isParentOf | Done | | | | | | ||
| isAncestorOf | Done | | | | | | ||
| getChildren | In progress | | | | | | ||
| setChildren | In progress | | | | | | ||
| updateChildren | In progress | | | | | | ||
| filterChildren | In progress | | | | | | ||
| deleteChildren | In progress | | | | | | ||
| getCommonAncestor | In progress | | | | | | ||
@@ -59,13 +69,11 @@ | Typedef | Plan | Document | Examples | ||
| mapper | Done | Done | | | ||
| updater | Done | In progress | | | ||
| reducer | Done | In progress | | | ||
| filter | Done | In progress | | | ||
| updater | Done | Done | | | ||
| reducer | Done | Done | | | ||
| filter | Done | Done | | | ||
- Reconsider paramaters passed to mappers / updaters etc. and which children, parents or ancestors should be accessible | ||
- Test mapper iteration order | ||
- Test mapper / filter / reducer argument lists | ||
- Show reverse() or sortBy() examples when using deeply | ||
- Try adding @externals for JS and Immutable, try grouping under different modules | ||
- Allow functions to be passsed into ChildPath and modify all affected library functions so they can use it | ||
- Add a 'thinking in trees and nodes' style intro | ||
- Add documentation about deep data manipulation pitfalls, avoiding killing children, limitation of child-collection-less nodes | ||
- Add documentation about deep data manipulation pitfalls, avoiding killing children | ||
- Add build process with Travis | ||
@@ -72,0 +80,0 @@ - Add coverage reporting and build failing |
@@ -15,3 +15,5 @@ import tape from 'tape'; | ||
deepMapParents, | ||
deepMapOutwards | ||
deepMapOutwards, | ||
deepMapLeavesOutwards, | ||
deepMapParentsOutwards | ||
} from '../map'; | ||
@@ -267,2 +269,114 @@ | ||
), 'deepMapOutwards iterates from the inside out'); | ||
}); | ||
tape('deepMapLeavesOutwards', test => { | ||
test.plan(3); | ||
test.ok(is( | ||
childLists.update(deepMapLeavesOutwards(item => item.set('abc', 123), ['children'])), | ||
fromJS({ | ||
name: "root", | ||
children: [ | ||
{ | ||
name: "child 1", | ||
children: [ | ||
{name: "grandchild 1", abc: 123}, | ||
{name: "grandchild 2", abc: 123} | ||
] | ||
}, | ||
{ | ||
name: "child 2", | ||
abc: 123, | ||
children: [] | ||
}, | ||
{name: "child 3", abc: 123} | ||
] | ||
}) | ||
), 'deepMapLeavesOutwards iterates through every leaf node using a childPath'); | ||
test.ok(is( | ||
nestedMaps.update(deepMapLeavesOutwards(item => item + "!")), | ||
fromJS({ | ||
a: { | ||
b: "B!", | ||
c: "C!", | ||
d: { | ||
e: "E!" | ||
} | ||
}, | ||
f: "F!" | ||
}) | ||
), 'deepMapLeavesOutwards iterates through every leaf node without using a childPath'); | ||
var names = []; | ||
childLists.update(deepMapLeavesOutwards(item => { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), | ||
test.ok(is(fromJS(names), | ||
fromJS([ | ||
'grandchild 1', | ||
'grandchild 2', | ||
'child 2', | ||
'child 3' | ||
]) | ||
), 'deepMapLeavesOutwards iterates from the inside out'); | ||
}); | ||
tape('deepMapParentsOutwards', test => { | ||
test.plan(3); | ||
test.ok(is( | ||
childLists.update(deepMapParentsOutwards(item => item.set('abc', 123), ['children'])), | ||
fromJS({ | ||
name: "root", | ||
abc: 123, | ||
children: [ | ||
{ | ||
name: "child 1", | ||
abc: 123, | ||
children: [ | ||
{name: "grandchild 1"}, | ||
{name: "grandchild 2"} | ||
] | ||
}, | ||
{ | ||
name: "child 2", | ||
children: [] | ||
}, | ||
{name: "child 3"} | ||
] | ||
}) | ||
), 'deepMapParentsOutwards iterates through every parent node using a childPath'); | ||
test.ok(is( | ||
nestedMaps.update(deepMapParentsOutwards(item => item.set('abc', '123'))), | ||
fromJS({ | ||
a: { | ||
b: "B", | ||
c: "C", | ||
d: { | ||
e: "E", | ||
abc: "123" | ||
}, | ||
abc: "123" | ||
}, | ||
f: "F", | ||
abc: "123" | ||
}) | ||
), 'deepMapParentsOutwards iterates through every parent node without using a childPath'); | ||
var names = []; | ||
childLists.update(deepMapParentsOutwards(item => { | ||
names.push(item.get('name')); | ||
return item; | ||
}, ['children'])), | ||
test.ok(is(fromJS(names), | ||
fromJS([ | ||
'root', | ||
'child 1' | ||
]) | ||
), 'deepMapParentsOutwards iterates from the inside out'); | ||
}); |
@@ -36,4 +36,2 @@ import { | ||
: item.updateIn(childPath, kids => { | ||
console.log("..."); | ||
console.log(item); | ||
return kids.filter((kid, kidKey) => filterer(kid, nodePath.push(kidKey), tree)); | ||
@@ -40,0 +38,0 @@ }); |
@@ -145,3 +145,3 @@ | ||
* @callback Mapper | ||
* @param {*} value The value to map. | ||
* @param {*} value The value to update. | ||
* @param {List} nodePath The current node's `NodePath`, a `List` of keys used to uniquely identify the current node. | ||
@@ -170,2 +170,13 @@ * @param {Iterable} tree The original `tree` passed into the map function. | ||
/** | ||
* A function required as an argument for the `deepReduce` functions. | ||
* | ||
* @callback Reducer | ||
* @param {*} reduction The current reduction. | ||
* @param {*} value The current value. | ||
* @param {List} nodePath The current node's `NodePath`, a `List` of keys used to uniquely identify the current node. | ||
* @param {Iterable} tree The original `tree` passed into the map function. | ||
* @return {*} The new reduced value. | ||
*/ | ||
export { | ||
@@ -194,6 +205,18 @@ deepGet, | ||
deepMapLeaves, | ||
deepMapParents | ||
deepMapParents, | ||
deepMapOutwards, | ||
deepMapLeavesOutwards, | ||
deepMapParentsOutwards | ||
} from './map'; | ||
export { | ||
deepReduce, | ||
deepReduceLeaves, | ||
deepReduceParents, | ||
deepReduceOutwards, | ||
deepReduceLeavesOutwards, | ||
deepReduceParentsOutwards | ||
} from './reduce'; | ||
export { | ||
deepFilter | ||
@@ -200,0 +223,0 @@ } from './filter'; |
@@ -35,8 +35,19 @@ import { | ||
const mapRecursiveOutwards = (self, childPath, mapper, tree, options, nodePath = List()) => { | ||
const mappedSelf = mapper(self, nodePath, tree); | ||
if(isLeaf(mappedSelf, childPath)) { | ||
return mappedSelf; | ||
if(options.onlyParents && isLeaf(self, childPath)) { | ||
return self; | ||
} | ||
var mappedSelf; | ||
if(options.onlyLeaves) { | ||
mappedSelf = self; | ||
if(isLeaf(mappedSelf, childPath)) { | ||
return mapper(self, nodePath, tree); | ||
} | ||
} else { | ||
mappedSelf = mapper(self, nodePath, tree); | ||
if(isLeaf(mappedSelf, childPath)) { | ||
return mappedSelf; | ||
} | ||
} | ||
return mappedSelf.updateIn(childPath, (children) => { | ||
@@ -65,6 +76,6 @@ return children.map((kid, key) => mapRecursiveOutwards(kid, childPath, mapper, tree, options, nodePath.push(key))); | ||
/** | ||
* Once fully applied, this iterates through the leaf nodes in the provided tree, passing them all through a mapper function. Leaf nodes are nodes that have no child nodes. | ||
* Once fully applied, this iterates through the leaf nodes in the provided tree, passing them all through a `mapper` function. Leaf nodes are nodes that have no child nodes. | ||
* Nodes are processed branch by branch, in the order that Immutable maps through the child iterables. | ||
* | ||
* @param {Mapper} mapper The function to be called for every node in the tree, the results of which will be used to create the modified tree. | ||
* @param {Mapper} mapper The function to be called for every leaf node in the tree, the results of which will be used to create the modified tree. | ||
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
@@ -79,6 +90,6 @@ * @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`. | ||
/** | ||
* Once fully applied, this iterates through the parent nodes in the provided tree, passing them all through a mapper function. Parent nodes are nodes that have child nodes. | ||
* Once fully applied, this iterates through the parent nodes in the provided tree, passing them all through a `mapper` function. Parent nodes are nodes that have child nodes. | ||
* Nodes are processed branch by branch in the order that Immutable maps through the child iterables, inward from leaves to the root node. | ||
* | ||
* @param {Mapper} mapper The function to be called for every node in the tree. | ||
* @param {Mapper} mapper The function to be called for every parent node in the tree. | ||
* the results of which will be used to create the modified iterable. | ||
@@ -100,4 +111,4 @@ * @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
* | ||
* - If you modify a node's children, then those children will already be modified by the time they are called by the mapper function. | ||
* - Because of the above, if a node removes or renames its own children iterable then those children will not be passed through the mapper function. | ||
* - If you modify a node's children, then those children will already be modified by the time they are called by the `mapper` function. | ||
* - Because of the above, if a node removes or renames its own children iterable then those children will not be passed through the `mapper` function. | ||
* | ||
@@ -113,2 +124,36 @@ * @param {Mapper} mapper The function to be called for every node in the tree, the results of which will be used to create the modified tree. | ||
/** | ||
* Once fully applied, this iterates through the leaf nodes in the provided tree, passing them all through a `mapper` function. | ||
* Nodes are processed branch by branch in the order that Immutable maps through the child iterables, outwards from the root node to the leaf nodes. | ||
* Sibling nodes are processed in the order that Immutable iterates through collections. | ||
* | ||
* @param {Mapper} mapper The function to be called for every leaf node in the tree, the results of which will be used to create the modified tree. | ||
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
* @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`. | ||
*/ | ||
function deepMapLeavesOutwards(mapper, childPath = null) { | ||
return (tree) => mapRecursiveOutwards(tree, asList(childPath), mapper, tree, {onlyLeaves: true}); | ||
} | ||
/** | ||
* Once fully applied, this iterates through the parent nodes in the provided tree, passing them all through a `mapper` function. | ||
* Nodes are processed branch by branch in the order that Immutable maps through the child iterables, outwards from the root node to the leaf nodes. | ||
* Sibling nodes are processed in the order that Immutable iterates through collections. | ||
* | ||
* Because this moves from the root node outwards this function behaves quite differently to the other deep map functions. | ||
* | ||
* - If you modify a node's children, then those children will already be modified by the time they are called by the `mapper` function. | ||
* - Because of the above, if a node removes or renames its own children iterable then those children will not be passed through the `mapper` function. | ||
* | ||
* @param {Mapper} mapper The function to be called for every parent node in the tree, the results of which will be used to create the modified tree. | ||
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node. | ||
* @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`. | ||
*/ | ||
function deepMapParentsOutwards(mapper, childPath = null) { | ||
return (tree) => mapRecursiveOutwards(tree, asList(childPath), mapper, tree, {onlyParents: true}); | ||
} | ||
export { | ||
@@ -118,3 +163,5 @@ deepMap, | ||
deepMapParents, | ||
deepMapOutwards | ||
deepMapOutwards, | ||
deepMapLeavesOutwards, | ||
deepMapParentsOutwards | ||
} |
@@ -36,2 +36,3 @@ import { | ||
* @param {*} node The node to make blank. | ||
* @param {ChildPath} [childPath=null] An Array or List of keys indicating where to find the node's children. | ||
* @return {*} The blank node. | ||
@@ -38,0 +39,0 @@ */ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
464521
76
4532
80