diff --git a/index.js b/index.js index b5161a8..146e74a 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const arrayUnion = require('array-union'); const glob = require('glob'); const pify = require('pify'); +const dirGlob = require('dir-glob'); const globP = pify(glob); @@ -25,7 +26,9 @@ const generateGlobTasks = (patterns, taskOpts) => { statCache: Object.create(null), realpathCache: Object.create(null), symlinks: Object.create(null), - ignore: [] + ignore: [], + expandDirectories: true, + nodir: true }, taskOpts); patterns.forEach((pattern, i) => { @@ -48,6 +51,20 @@ const generateGlobTasks = (patterns, taskOpts) => { return globTasks; }; +const globDirs = (task, fn) => { + if (Array.isArray(task.opts.expandDirectories)) { + return fn(task.pattern, {files: task.opts.expandDirectories}); + } + + if (typeof task.opts.expandDirectories === 'object') { + return fn(task.pattern, task.opts.expandDirectories); + } + + return fn(task.pattern); +}; + +const getPattern = (task, fn) => task.opts.expandDirectories ? globDirs(task, fn) : [task.pattern]; + module.exports = (patterns, opts) => { let globTasks; @@ -57,16 +74,29 @@ module.exports = (patterns, opts) => { return Promise.reject(err); } - return Promise.all( - globTasks.map(task => globP(task.pattern, task.opts)) - ) + const getTasks = Promise.all(globTasks.map(task => Promise.resolve(getPattern(task, dirGlob)) + .then(globs => Promise.all(globs.map(glob => ({ + pattern: glob, + opts: task.opts + })))) + )) + .then(tasks => arrayUnion.apply(null, tasks)); + + return getTasks.then(tasks => Promise.all(tasks.map(task => globP(task.pattern, task.opts)))) .then(paths => arrayUnion.apply(null, paths)); }; module.exports.sync = (patterns, opts) => { const globTasks = generateGlobTasks(patterns, opts); + const tasks = globTasks.reduce( + (tasks, task) => arrayUnion(getPattern(task, dirGlob.sync).map(glob => ({ + pattern: glob, + opts: task.opts + }))), + [] + ); - return globTasks.reduce( + return tasks.reduce( (matches, task) => arrayUnion(matches, glob.sync(task.pattern, task.opts)), [] ); diff --git a/package.json b/package.json index a8e659f..fa2938a 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ ], "dependencies": { "array-union": "^1.0.1", + "dir-glob": "^2.0.0", "glob": "^7.1.2", "pify": "^3.0.0" }, diff --git a/readme.md b/readme.md index 3a231a4..fa26320 100644 --- a/readme.md +++ b/readme.md @@ -69,7 +69,26 @@ See supported `minimatch` [patterns](https://github.com/isaacs/minimatch#usage). Type: `Object` -See the [`node-glob` options](https://github.com/isaacs/node-glob#options). +See the [`node-glob` options](https://github.com/isaacs/node-glob#options) in addition to the ones below. + +##### expandDirectories + +Type: `boolean` `Array` `Object`
+Default: `true` + +If set to `true`, `globby` will automatically glob directories for you. If you define an `Array` it will only glob files that matches the patterns inside the `Array`. You can also define an `Object` with `files` and `extensions` like below: + +```js +globby('images', { + expandDirectories: { + files: ['cat', 'unicorn', '*.jpg'], + extensions: ['png'] + } +}).then(paths => { + console.log(paths); + //=> ['cat.png', 'unicorn.png', 'cow.jpg', 'rainbow.jpg'] +}); +``` ## Globbing patterns diff --git a/test.js b/test.js index 5570218..c8b4c47 100644 --- a/test.js +++ b/test.js @@ -1,4 +1,5 @@ import fs from 'fs'; +import path from 'path'; import test from 'ava'; import m from '.'; @@ -14,11 +15,13 @@ const fixture = [ test.before(() => { fs.mkdirSync('tmp'); fixture.forEach(fs.writeFileSync.bind(fs)); + fixture.forEach(x => fs.writeFileSync(path.join(__dirname, 'tmp', x))); }); test.after(() => { - fs.rmdirSync('tmp'); fixture.forEach(fs.unlinkSync.bind(fs)); + fixture.forEach(x => fs.unlinkSync(path.join(__dirname, 'tmp', x))); + fs.rmdirSync('tmp'); }); test('glob - async', async t => { @@ -78,6 +81,24 @@ test('expose hasMagic', t => { t.false(m.hasMagic(['path1', 'path2'])); }); +test('expandDirectories option', t => { + t.deepEqual(m.sync('tmp'), ['tmp/a.tmp', 'tmp/b.tmp', 'tmp/c.tmp', 'tmp/d.tmp', 'tmp/e.tmp']); + t.deepEqual(m.sync('tmp', {expandDirectories: ['a*', 'b*']}), ['tmp/a.tmp', 'tmp/b.tmp']); + t.deepEqual(m.sync('tmp', { + expandDirectories: { + files: ['a', 'b'], + extensions: ['tmp'] + } + }), ['tmp/a.tmp', 'tmp/b.tmp']); + t.deepEqual(m.sync('tmp', { + expandDirectories: { + files: ['a', 'b'], + extensions: ['tmp'] + }, + ignore: ['**/b.tmp'] + }), ['tmp/a.tmp']); +}); + // Rejected for being an invalid pattern [ {},