lib/index.js
function analyzeFile (file, content, filter, depResolve, depth, result) {
  depth = typeof depth === 'number' ? depth : Infinity
  result = result || {}

  if (depth < 1) {
    return
  }

  if (file in result) {
    return
  }

  debug('analyze file: file = %s, depth = %s', file, depth)

  let deps = parseFile(file, content) || []
  let item = result[file] = {
    deps: [],
    relatives: [],
    modules: []
  }

  // filter deps
  if (filter) {
    deps = deps.filter(dep => filter(dep, file))
  }

  // convert
  deps.forEach(dep => {
    let info = getDepInfo(dep, file, depResolve)

    item.deps.push(info)

    if (info.module && item.modules.indexOf(info.module) < 0) {
      item.modules.push(info.module)
    } else if (info.file && item.relatives.indexOf(info.file) < 0) {
      item.relatives.push(info.file)

      // deep first traversing
      analyzeFile(info.file, fs.readFileSync(info.file, 'utf8'), filter, depResolve, depth - 1, result)
    }
  })

  return result
}
function analyzeFile (file, content, filter, depResolve, depth, result) {
  depth = typeof depth === 'number' ? depth : Infinity
  result = result || {}

  if (depth < 1) {
    return
  }

  if (file in result) {
    return
  }

  debug('analyze file: file = %s, depth = %s', file, depth)

  let deps = parseFile(file, content) || []
  let item = result[file] = {
    deps: [],
    relatives: [],
    modules: []
  }

  // filter deps
  if (filter) {
    deps = deps.filter(dep => filter(dep, file))
  }

  // convert
  deps.forEach(dep => {
    let info = getDepInfo(dep, file, depResolve)

    item.deps.push(info)

    if (info.module && item.modules.indexOf(info.module) < 0) {
      item.modules.push(info.module)
    } else if (info.file && item.relatives.indexOf(info.file) < 0) {
      item.relatives.push(info.file)

      // deep first traversing
      analyzeFile(info.file, fs.readFileSync(info.file, 'utf8'), filter, depResolve, depth - 1, result)
    }
  })

  return result
}
function analyzeFile ( file , content , filter , depResolve , depth , result ) { depth = typeof depth === 'number' ? depth : Infinity result = result || { } if ( depth < 1 ) { return } if ( file in result ) { return } debug ( 'analyze file: file = %s, depth = %s' , file , depth ) let deps = parseFile ( file , content ) || [ ] let item = result [ file ] = { deps : [ ] , relatives : [ ] , modules : [ ] } // filter deps if ( filter ) { deps = deps . filter ( dep => filter ( dep , file ) ) } // convert deps . forEach ( dep => { let info = getDepInfo ( dep , file , depResolve ) item . deps . push ( info ) if ( info . module && item . modules . indexOf ( info . module ) < 0 ) { item . modules . push ( info . module ) } else if ( info . file && item . relatives . indexOf ( info . file ) < 0 ) { item . relatives . push ( info . file ) // deep first traversing analyzeFile ( info . file , fs . readFileSync ( info . file , 'utf8' ) , filter , depResolve , depth - 1 , result ) } } ) return result }
recursively analyze single file
@param  {String} file      file path
@param  {String} content   file content
@param  {Function} filter  filter function
@param  {Function} depResolve resolve dep to normal dep format
@param  {Number} depth     max analyze depth
@param  {Object} result    the analyed result
@return {Object}
recursively analyze single file