{%= description %}
var glob = require('{%= name %}')({ gitignore: true });
var files = glob.readdirSync('**/*.js');
Jump to docs sections:
{%= include("install-npm", {save: true}) %}
Params
All "read" methods take a glob pattern and an options
object.
pattern
{String}: Glob pattern to use for matching. (multiple pattern support is planned)options
{Object}: Options forglob-fs
or middleware.
Examples:
// sync
var files = glob.readdirSync('*.js', {});
// async
glob.readdir('*.js', function(err, files) {
console.log(files);
});
// stream
glob.readdirStream('*.js', {})
.on('data', function(file) {
console.log(file);
});
// promise
glob.readdirPromise('*.js')
.then(function(files) {
console.log(file);
});
{%= apidocs("./lib/readers.js") %} {%= apidocs("index.js") %}
glob-fs uses middleware to add file matching and exclusion capabilities, or other features that may or may not eventually become core functionality.
What is a middleware?
A middleware is a function that "processes" files as they're read from the file system by glob-fs.
Additionally, middleware can:
- be chained
include
orexclude
a file based on some condition, like whether or not one of its properties matches a regex or glob pattern.- determine whether or not to continue recursing in a specific directory
- modifying an existing property to the
file
object - add a new property to the
file
object
Ignoring files
In the following example, notemp
is a complete and functional middleware for excluding any filepath that has the substring temp
:
var glob = require('glob-fs')();
function notemp(file) {
if (/temp/.test(file.path)) {
file.exclude = true;
}
return file;
}
glob.use(notemp)
.readdirStream('**/*.js')
.on('data', function(file) {
console.log(file.relative);
});
Matching
Pattern matching is done by default in glob-fs, but you get disable the built-in matchers or get more specific by adding a middleware that uses [micromatch][] or [minimatch][] for matching files.
var glob = require('glob-fs')({ gitignore: true });
var mm = require('micromatch');
glob.use(function(file) {
if (mm.isMatch(file.relative, 'vendor/**')) file.exclude = true;
return file;
})
.readdirStream('**/*.js')
.on('data', function(file) {
console.log(file.relative);
});
recursion
Here is how a middleware might determine whether or not to recurse based on a certain pattern:
var glob = require('glob-fs')();
// this specific check is already done by glob-fs, it's just used here as an example
function recurse(file) {
// `file.pattern` is an object with a `glob` (string) property
file.recurse = file.pattern.glob.indexOf('**') !== -1;
return file;
}
// use the middleware
glob.use(recurse)
.readdir('**/*.js', function(err, files) {
console.log(files);
});
Built-in middleware
Currently glob-fs includes and runs the following middleware automatically:
{%= related(mm(Object.keys(dependencies), "glob-fs*")) %}
Disabling built-ins
To disable built-in middleware and prevent them from running, pass builtins: false
on the global options. This will disable all built-in middleware.
Example:
var glob = require('glob-fs')({builtins: false});
To disable a specific middleware from running, you can usually pass the name of the middleware on the options, like dotfiles: false
, but it's best to check the readme of that middleware for specifics.
- Naming: any middleware published to npm should be prefixed with
glob-fs-
, as in:glob-fs-dotfiles
. - Keywords: please add
glob-fs
to the keywords array in package.json - Options: all middleware should return a function that takes an
options
object, as in the Middleware Example - Return
file
: all middleware should return thefile
object after processing.
- A middleware should only do one specific thing.
- Multiple middleware libs can be bundled together to create a single middleware.
- Pattern matching should be extremely specific. Don't force downstream middleware to reverse your mistakes.
- As mentioned in the middleware conventions section, always return the
file
object. - A single conditional should only set
file.exclude
totrue
, orfile.include
totrue
, never both. - It's completely okay to check
this.options
- Middleware modules should be fully documented.
Note that the gitignore
option is already true
by default, it's just shown here as a placeholder for how options may be defined.
var glob = require('{%= name %}')({ gitignore: true });
glob.readdir('**/*.js', function(err, files) {
console.log(files);
});
var glob = require('{%= name %}')({ gitignore: true });
glob.readdirPromise('**/*')
.then(function (files) {
console.log(files);
});
var glob = require('{%= name %}')({ gitignore: true });
glob.readdirStream('**/*')
.on('data', function (file) {
console.log(file.path);
})
var glob = require('{%= name %}')({ gitignore: true });
var files = glob.readdirSync('**/*.js');
console.log(files);
(WIP)
The following events are emitted with all "read" methods:
read
: emitted immediately before an iterator calls the first middleware.include
: emits afile
object when it's matchedexclude
: emits afile
object when it's ignored/excludedfile
: emits afile
object when the iterator pushes it into the results array. Only applies tosync
,async
andpromise
.dir
: emits afile
object when the iterator finds a directoryend
when the iterator is finished readingerror
on errors
async
var glob = require('..')({ gitignore: true });
glob.on('dir', function (file) {
console.log(file);
});
glob.readdir('**/*.js', function (err, files) {
if (err) return console.error(err);
console.log(files.length);
});
promise
var glob = require('{%= name %}')({ gitignore: true });
glob.on('include', function (file) {
console.log('including:', file.path);
});
glob.on('exclude', function (file) {
console.log('excluding:', file.path);
});
glob.readdirPromise('**/*');
sync
Also has an example of a custom event, emitted from a middleware:
var glob = require('{%= name %}')({ gitignore: true })
.use(function (file) {
if (/\.js$/.test(file.path)) {
// custom event
this.emit('js', file);
}
return file;
});
glob.on('js', function (file) {
console.log('js file:', file.path);
});
glob.on('exclude', function (file) {
console.log('excluded:', i.excludes++);
});
glob.on('include', function (file) {
console.log('included:', i.includes++)
});
glob.on('end', function () {
console.log('total files:', this.files.length);
});
glob.readdirSync('**/*.js');
stream
var glob = require('{%= name %}')({ gitignore: true })
glob.readdirStream('**/*')
.on('data', function (file) {
console.log(file.path)
})
.on('error', console.error)
.on('end', function () {
console.log('end');
});
- when files are read from the file system, an object is created to keep a record of the file's
path
,dirname
, and fsstat
object and other pertinent information that makes it easier to make decisions about inclusion and exclusion later on. file
objects are decorated with aparse
method that is used to calculate thefile.relative
andfile.absolute
properties.- the
file.parse()
method is called in the iterator, right after the call tofs.stats
and just before the call to the middleware handler (.handle()
). This ensures that all middleware have access to necessary path information. file.relative
is the file path that's actually pushed into thefiles
array that is ultimately returned.file.relative
is calculated usingpath.relative(file.path, cwd)
, wherecwd
is passed on the options (globally, or on a middleware), andfile.path
is typically the absolute, actual file path to the file being globbed.
middleware
- middleware
- middleware handler
- externalize middleware to modules (started, prs welcome!)
events
- events
tests
- unit tests (need to be moved)
iterators
- sync iterator
- async iterator
- stream iterator
- promise iterator
read methods
- glob.readdir (async)
- glob.readdirSync
- glob.readdirStream
- glob.readdirPromise
patterns
- Multiple pattern support. will need to change pattern handling, middleware handling. this is POC currently
- Negation patterns (might not do this, since it can be handled in middleware)
- matching method, memoized/cached/bound to a glob pattern or patterns, so it can be reused without having to recompile the regex.
other
- clean up
./lib
- comparsion to [node-glob][]
(Add your project to the .verb.md template do a PR!)
{%= related(['glob-fs-dotfiles', 'glob-fs-gitignore']) %}
{%= related(['micromatch', 'braces', 'fill-range', 'is-glob']) %}
{%= include("tests") %}
{%= include("contributing") %}
{%= include("author") %}
{%= copyright() %} {%= license() %}
{%= include("footer") %}
{%= reflinks(['verb', 'glob', 'minimatch']) %}