diff --git a/README.md b/README.md index 713febc6..c40b3402 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ This is just [glob-watcher]. - Default is `process.cwd()`. - base - Specify the folder relative to the cwd. This is used to determine the file names when saving in `.dest()`. - Default is the `cwd` resolves to the folder path. + - Can also be a function that takes in a file and returns a folder path. - mode - Specify the mode the files should be created with. - Default is the mode of the input file (file.stat.mode) if any. - Default is the process mode if the input file has no mode property. diff --git a/lib/prepareWrite.js b/lib/prepareWrite.js index 015cad43..9779c701 100644 --- a/lib/prepareWrite.js +++ b/lib/prepareWrite.js @@ -5,6 +5,14 @@ var path = require('path'); var mkdirp = require('mkdirp'); var fs = require('graceful-fs'); +function stringOrFunc(v, file) { + if (typeof v !== 'string' && typeof v !== 'function') { + return null; + } + + return typeof v === 'string' ? v : v(file); +} + function prepareWrite(outFolder, file, opt, cb) { var options = assign({ cwd: process.cwd(), @@ -15,15 +23,16 @@ function prepareWrite(outFolder, file, opt, cb) { options.flag = (options.overwrite ? 'w' : 'wx'); var cwd = path.resolve(options.cwd); - - if (typeof outFolder !== 'string' && typeof outFolder !== 'function') { + var outFolderPath = stringOrFunc(outFolder, file); + if (!outFolderPath) { throw new Error('Invalid output folder'); } + var basePath = options.base ? + stringOrFunc(options.base, file) : path.resolve(cwd, outFolderPath); + if (!basePath) { + throw new Error('Invalid base option'); + } - var outFolderPath = ( - typeof outFolder === 'string' ? outFolder : outFolder(file) - ); - var basePath = options.base || path.resolve(cwd, outFolderPath); var writePath = path.resolve(basePath, file.relative); var writeFolder = path.dirname(writePath); diff --git a/test/dest.js b/test/dest.js index a5c7dd1a..9591302d 100644 --- a/test/dest.js +++ b/test/dest.js @@ -572,12 +572,11 @@ describe('dest stream', function() { stream.end(); }); - it('should change to the specified base', function(done) { + it('should change to the specified base as string', function(done) { var inputBase = path.join(__dirname, './fixtures'); var inputPath = path.join(__dirname, './fixtures/wow/suchempty'); var firstFile = new File({ - base: inputBase, cwd: __dirname, path: inputPath, stat: fs.statSync(inputPath) @@ -601,6 +600,38 @@ describe('dest stream', function() { stream.end(); }); + it('should change to the specified base as function', function(done) { + var inputBase = path.join(__dirname, './fixtures'); + var inputPath = path.join(__dirname, './fixtures/wow/suchempty'); + + var firstFile = new File({ + cwd: __dirname, + path: inputPath, + stat: fs.statSync(inputPath) + }); + + var onEnd = function(){ + buffered[0].base.should.equal(inputBase); + done(); + }; + + var stream = vfs.dest('./out-fixtures/', { + cwd: __dirname, + base: function(file){ + should.exist(file); + file.path.should.equal(inputPath); + return inputBase; + } + }); + + var buffered = []; + bufferStream = through.obj(dataWrap(buffered.push.bind(buffered)), onEnd); + + stream.pipe(bufferStream); + stream.write(firstFile); + stream.end(); + }); + it('should report IO errors', function(done) { var inputPath = path.join(__dirname, './fixtures/test.coffee'); var inputBase = path.join(__dirname, './fixtures/');