-
Notifications
You must be signed in to change notification settings - Fork 9
/
index.js
76 lines (66 loc) · 1.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
var from = require('from2')
var path = require('path')
module.exports = walker
function walker (dirs, opts) {
var fs = opts && opts.fs || require('fs')
var filter = opts && opts.filter || function (filename) { return true }
if (!Array.isArray(dirs)) dirs = [dirs]
var maxDepth = opts && opts.maxDepth || Infinity
dirs = dirs.filter(filter)
var pending = []
var root = dirs.shift()
if (root) pending.push(root)
return from.obj(read)
function read (size, cb) {
if (!pending.length) {
if (dirs.length) {
root = dirs.shift()
pending.push(root)
return read(size, cb)
}
return cb(null, null)
}
kick(cb)
}
function kick (cb) {
var name = pending.shift()
if (typeof name === 'undefined') return cb(null, null)
fs.lstat(name, function (err, st) {
if (err) return done(err)
if (!st.isDirectory() || depthLimiter(name, root, maxDepth)) return done(null)
fs.readdir(name, function (err, files) {
if (err) return done(err)
files.sort()
for (var i = 0; i < files.length; i++) {
var next = path.join(name, files[i])
if (filter(next)) pending.unshift(next)
}
if (name === root) kick(cb)
else done(null)
})
function done (err) {
if (err) return cb(err)
var item = {
root: root,
filepath: name,
stat: st,
relname: root === name ? path.basename(name) : path.relative(root, name),
basename: path.basename(name)
}
var isFile = st.isFile()
if (isFile) {
item.type = 'file'
}
var isDir = st.isDirectory()
if (isDir) item.type = 'directory'
cb(null, item)
}
})
}
}
function depthLimiter (filePath, relativeTo, maxDepth) {
if (maxDepth === Infinity) return false
const rootDepth = relativeTo.split(path.sep).length
const fileDepth = filePath.split(path.sep).length
return fileDepth - rootDepth > maxDepth
}