dist/tree-tools.js
function filter(tree, query, options) {
    var compiledQuery = _.isFunction(query) ? query : _.matches(query);

    var settings = _.defaults(options, {
      childNode: ['children']
    });

    settings.childNode = _.castArray(settings.childNode);

    var seekDown = function seekDown(tree) {
      return tree.filter(function (branch, index) {
        return compiledQuery(branch, index);
      }).map(function (branch) {
        settings.childNode.some(function (key) {
          if (_.has(branch, key)) {
            if (_.isArray(branch[key])) {
              branch[key] = seekDown(branch[key]);
            } else {
              delete branch[key];
            }
          }
        });
        return branch;
      });
    };

    if (_.isArray(tree)) {
      return seekDown(tree, []) || [];
    } else {
      return seekDown([tree], [])[0] || {};
    }
  }
function filter(tree, query, options) {
    var compiledQuery = _.isFunction(query) ? query : _.matches(query);

    var settings = _.defaults(options, {
      childNode: ['children']
    });

    settings.childNode = _.castArray(settings.childNode);

    var seekDown = function seekDown(tree) {
      return tree.filter(function (branch, index) {
        return compiledQuery(branch, index);
      }).map(function (branch) {
        settings.childNode.some(function (key) {
          if (_.has(branch, key)) {
            if (_.isArray(branch[key])) {
              branch[key] = seekDown(branch[key]);
            } else {
              delete branch[key];
            }
          }
        });
        return branch;
      });
    };

    if (_.isArray(tree)) {
      return seekDown(tree, []) || [];
    } else {
      return seekDown([tree], [])[0] || {};
    }
  }
function filter ( tree , query , options ) { var compiledQuery = _ . isFunction ( query ) ? query : _ . matches ( query ) ; var settings = _ . defaults ( options , { childNode : [ 'children' ] } ) ; settings . childNode = _ . castArray ( settings . childNode ) ; var seekDown = function seekDown ( tree ) { return tree . filter ( function ( branch , index ) { return compiledQuery ( branch , index ) ; } ) . map ( function ( branch ) { settings . childNode . some ( function ( key ) { if ( _ . has ( branch , key ) ) { if ( _ . isArray ( branch [ key ] ) ) { branch [ key ] = seekDown ( branch [ key ] ) ; } else { delete branch [ key ] ; } } } ) ; return branch ; } ) ; } ; if ( _ . isArray ( tree ) ) { return seekDown ( tree , [ ] ) || [ ] ; } else { return seekDown ( [ tree ] , [ ] ) [ 0 ] || { } ; } }
Return a copy of the tree with all non-matching nodes removed

NOTE: This function seeks downwards, so any parent that does not match will also omit its child nodes

@param {Object|array} tree The tree structure to search (assumed to be a collection)
@param {Object|function} query A valid lodash query to run (anything valid via _.find()) or a matching function to be run on each node
@param {Object} [options] Options object
@param {array|string} [options.childNode="children"] Node or nodes to examine to discover the child elements
Return a copy of the tree with all non - matching nodes removed