Comparing version 0.0.8 to 0.0.9
@@ -1,18 +0,45 @@ | ||
| ||
var fs = require('fs'), | ||
var fs = require('fs'), | ||
path = require('path'); | ||
/** | ||
* merge two objects | ||
* @param target object to merge | ||
* @param source object to merge | ||
* @param {Boolean} [modify] whether to modify the target | ||
* @returns {Object} object (new unless modify is true) consisting of the merged objects | ||
*/ | ||
function extend(target, source, modify) { | ||
var result = target ? modify ? target : extend({}, target, true) : {}; | ||
if (!source) return result; | ||
for (var key in source) { | ||
if (source.hasOwnProperty(key) && source[key] !== undefined) { | ||
result[key] = source[key]; | ||
} | ||
} | ||
return result; | ||
} | ||
/** | ||
* read files and call a function with the contents of each file | ||
* @param {string} dir path of dir containing the files to be read | ||
* @param {string} encoding file encoding (default is 'utf8') | ||
* @param {boolean} recursive whether to recurse subdirs | ||
* @param {String} dir path of dir containing the files to be read | ||
* @param {String} encoding file encoding (default is 'utf8') | ||
* @param {Object} options options hash for encoding, recursive, and match/exclude | ||
* @param {Function(error, string)} callback callback for each files content | ||
* @param {Function(error)} complete fn to call when finished | ||
*/ | ||
function readFiles(dir, encoding, recursive, callback, complete) { | ||
function readFiles(dir, options, callback, complete) { | ||
if (typeof options === 'function') { | ||
complete = callback; | ||
callback = options; | ||
options = {}; | ||
} | ||
options = extend({ | ||
recursive: true, | ||
encoding: 'utf8' | ||
}, options); | ||
var files = []; | ||
var done = function (err) { | ||
var done = function(err) { | ||
if (typeof complete === 'function') { | ||
@@ -24,36 +51,26 @@ if (err) return complete(err); | ||
// encoding is optional and defaults to 'utf8' | ||
if (typeof encoding !== 'string') { | ||
complete = callback; | ||
callback = recursive; | ||
recursive = encoding; | ||
encoding = 'utf8'; | ||
} | ||
// recursive is optional and defaults to true | ||
if (typeof recursive !== 'boolean') { | ||
complete = callback; | ||
callback = recursive; | ||
recursive = true; | ||
} | ||
fs.readdir(dir, function(err, list) { | ||
if (err) return done(err); | ||
var i = 0; | ||
(function next() { | ||
var file = list[i++]; | ||
if (!file) return done(null, files); | ||
file = path.join(dir,file); | ||
var filename = list[i++]; | ||
if (!filename) return done(null, files); | ||
var file = path.join(dir, filename); | ||
fs.stat(file, function(err, stat) { | ||
if (stat && stat.isDirectory()) { | ||
readFiles(file, encoding, recursive, callback, function(err, sfiles) { | ||
if (stat && stat.isDirectory() && options.recursive) { | ||
readFiles(file, options, callback, function(err, sfiles) { | ||
files = files.concat(sfiles); | ||
next(); | ||
}); | ||
} | ||
else { | ||
files.push(file); | ||
fs.readFile(file, encoding, function(err, data) { | ||
} else { | ||
if (options.match && !options.match.test(filename)) return next(); | ||
if (options.exclude && options.exclude.test(filename)) return next(); | ||
if (options.shortName) files.push(filename); | ||
else files.push(file); | ||
fs.readFile(file, options.encoding, function(err, data) { | ||
if (err) return done(err); | ||
if (callback.length > 3) callback(null, data, file, next); | ||
if (callback.length > 3) | ||
if (options.shortName) callback(null, data, filename, next); | ||
else callback(null, data, file, next); | ||
else callback(null, data, next); | ||
@@ -63,7 +80,6 @@ }); | ||
}); | ||
})(); | ||
})(); | ||
}); | ||
} | ||
module.exports = readFiles; | ||
module.exports = readFiles; |
{ | ||
"name" : "node-dir", | ||
"version" : "0.0.8", | ||
"version" : "0.0.9", | ||
"description" : "asynchronous file and directory operations for Node.js", | ||
@@ -5,0 +5,0 @@ "main" : "index", |
@@ -11,5 +11,11 @@ # node-dir | ||
#### readFiles( dir, fileCallback, [finishedCallback] ) | ||
Sequentially read the content of each file in a directory, passing the contents to a callback, optionally calling a finished callback when complete. | ||
#### readFiles( dir, [options], fileCallback, [finishedCallback] ) | ||
Sequentially read the content of each file in a directory, passing the contents to a callback, optionally calling a finished callback when complete. The options and finishedCallback arguments are not required. | ||
Valid options are: | ||
- encoding: file encoding (defaults to 'utf8') | ||
- match: a regex pattern to specify filenames to operate on | ||
- exclude: a regex pattern to specify filenames to ignore | ||
- shortName: whether to aggregate only the base filename rather than the full filepath | ||
```javascript | ||
@@ -27,2 +33,16 @@ dir.readFiles(__dirname, | ||
// match only filenames with a .txt extension and that don't start with a `.´ | ||
dir.readFiles(__dirname, { | ||
match: /.txt$/, | ||
exclude: /^\./ | ||
}, function(err, content, next) { | ||
if (err) throw err; | ||
console.log('content:', content); | ||
next(); | ||
}, | ||
function(err, files){ | ||
if (err) throw err; | ||
console.log('finished reading files:',files); | ||
}); | ||
// the callback for each file can optionally have a filename argument as its 3rd parameter | ||
@@ -29,0 +49,0 @@ // and the finishedCallback argument is optional, e.g. |
130
test/test.js
@@ -10,6 +10,6 @@ var path = require('path'); | ||
var filenames = []; | ||
describe('readfiles method', function() { | ||
describe('readfiles method', function() { | ||
it('should exec a callback on every file contents and exec a done callback', function(done) { | ||
var filenames = []; | ||
dir.readFiles( | ||
@@ -31,5 +31,5 @@ tdir, function(err, content, filename, next) { | ||
'testdir/file1.txt', | ||
'testdir/file2.txt', | ||
'testdir/file2.text', | ||
'testdir/subdir/file3.txt', | ||
'testdir/subdir/file4.txt' | ||
'testdir/subdir/file4.text' | ||
]); | ||
@@ -41,2 +41,112 @@ filenames.should.eql(['file1', 'file2', 'file3', 'file4']); | ||
it('should accept an options argument that can specify encoding', function(done) { | ||
var filenames = []; | ||
dir.readFiles( | ||
tdir, { | ||
encoding: 'ascii' | ||
}, function(err, content, filename, next) { | ||
expect(err).to.equal(null); | ||
content = content.replace(/\r/g, ''); | ||
var shortName = path.basename(filename).replace(new RegExp(path.extname(filename) + '$'), ''); | ||
var expected = 'begin content of ' + shortName + '\ncontent body\nend content of ' + shortName; | ||
content.should.equal(expected); | ||
filenames.push(shortName); | ||
next(); | ||
}, function(err, files) { | ||
expect(err).to.equal(null); | ||
filenames.should.eql(['file1', 'file2', 'file3', 'file4']); | ||
done(); | ||
}); | ||
}); | ||
it('if shortName option is true, only aggregate the base filename rather than the full filepath', function(done) { | ||
var filenames = []; | ||
dir.readFiles( | ||
tdir, { | ||
shortName: true | ||
}, function(err, content, filename, next) { | ||
expect(err).to.equal(null); | ||
content = content.replace(/\r/g, ''); | ||
path.basename(filename).should.equal(filename); | ||
var shortName = filename.replace(new RegExp(path.extname(filename) + '$'), ''); | ||
var expected = 'begin content of ' + shortName + '\ncontent body\nend content of ' + shortName; | ||
content.should.equal(expected); | ||
filenames.push(filename); | ||
next(); | ||
}, function(err, files) { | ||
expect(err).to.equal(null); | ||
filenames.should.eql(['file1.txt', 'file2.text', 'file3.txt', 'file4.text']); | ||
done(); | ||
}); | ||
}); | ||
it('if given a match option, should only read files that match it', function(done) { | ||
var filenames = []; | ||
dir.readFiles( | ||
tdir, { | ||
match: /txt$/ | ||
}, function(err, content, filename, next) { | ||
expect(err).to.equal(null); | ||
content = content.replace(/\r/g, ''); | ||
var shortName = path.basename(filename).replace(new RegExp(path.extname(filename) + '$'), ''); | ||
var expected = 'begin content of ' + shortName + '\ncontent body\nend content of ' + shortName; | ||
content.should.equal(expected); | ||
filenames.push(shortName); | ||
next(); | ||
}, function(err, files) { | ||
expect(err).to.equal(null); | ||
filenames.should.eql(['file1', 'file3']); | ||
done(); | ||
}); | ||
}); | ||
it('match option should match pattern only to the filename itself, not the full filepath', function(done) { | ||
var filenames = []; | ||
dir.readFiles( | ||
tdir, { | ||
match: /^file/ | ||
}, function(err, content, filename, next) { | ||
expect(err).to.equal(null); | ||
content = content.replace(/\r/g, ''); | ||
var shortName = path.basename(filename).replace(new RegExp(path.extname(filename) + '$'), ''); | ||
var expected = 'begin content of ' + shortName + '\ncontent body\nend content of ' + shortName; | ||
filenames.push(shortName); | ||
content.should.equal(expected); | ||
next(); | ||
}, function(err, files) { | ||
expect(err).to.equal(null); | ||
var relFiles = files.map(function(curPath) { | ||
return path.relative(__dirname, curPath); | ||
}); | ||
relFiles.should.eql([ | ||
'testdir/file1.txt', | ||
'testdir/file2.text', | ||
'testdir/subdir/file3.txt', | ||
'testdir/subdir/file4.text' | ||
]); | ||
filenames.should.eql(['file1', 'file2', 'file3', 'file4']); | ||
done(); | ||
}); | ||
}); | ||
it('if given an exclude option, should only read files that do not match the exclude pattern', function(done) { | ||
var filenames = []; | ||
dir.readFiles( | ||
tdir, { | ||
exclude: /text$/ | ||
}, function(err, content, filename, next) { | ||
expect(err).to.equal(null); | ||
content = content.replace(/\r/g, ''); | ||
var shortName = path.basename(filename).replace(new RegExp(path.extname(filename) + '$'), ''); | ||
var expected = 'begin content of ' + shortName + '\ncontent body\nend content of ' + shortName; | ||
content.should.equal(expected); | ||
filenames.push(shortName); | ||
next(); | ||
}, function(err, files) { | ||
expect(err).to.equal(null); | ||
filenames.should.eql(['file1', 'file3']); | ||
done(); | ||
}); | ||
}); | ||
it('can be called with a callback in which the filename argument is omitted', function(done) { | ||
@@ -77,5 +187,5 @@ dir.readFiles( | ||
'testdir/file1.txt', | ||
'testdir/file2.txt', | ||
'testdir/file2.text', | ||
'testdir/subdir/file3.txt', | ||
'testdir/subdir/file4.txt' | ||
'testdir/subdir/file4.text' | ||
]); | ||
@@ -118,5 +228,5 @@ done(); | ||
'testdir/file1.txt', | ||
'testdir/file2.txt', | ||
'testdir/file2.text', | ||
'testdir/subdir/file3.txt', | ||
'testdir/subdir/file4.txt' | ||
'testdir/subdir/file4.text' | ||
]); | ||
@@ -139,5 +249,5 @@ relPaths.length.should.equal(1); | ||
'testdir/file1.txt', | ||
'testdir/file2.txt', | ||
'testdir/file2.text', | ||
'testdir/subdir/file3.txt', | ||
'testdir/subdir/file4.txt', | ||
'testdir/subdir/file4.text', | ||
'testdir/subdir' | ||
@@ -144,0 +254,0 @@ ]); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23000
435
107