Generate files with a 1-to-1 dependency.
Because sometimes you don't need a complex build tool :)
- Uses globs to pick which files to process
- Supports both an "easy" syntax and custom functions
- Only processes files when the source has changed
- Full async / concurrency support
- Creates any required destination folders
Take a screenshot of all your movies:
var regen = require('regen');
regen({
cwd: './movies',
src: '**/*.{mp4,mov}',
dest: '../thumbs/$path/$name.jpg',
process: 'ffmpeg $src -vframes 1 -y $dest',
parallel: 'cpu',
report: 'Taking screenshots $progress'
}, callback);
regen({
cwd: /* the directory from which to to resolve paths */,
src: /* source file filter */,
dest: /* how to generate output file names */,
process: /* async operation to run on each file */,
parallel: /* concurrency level (optional) */,
report: /* callback to report progress of operations */
}, callback);
The directory from which src
and dest
paths are resolved. cwd
can be an absolute path, or relative to the current process.
A glob filter to pick source files, relative to cwd
. For example:
**/*
all files**/lib*.c
all c files starting with "lib"photos/*.jpg
all jpg files in "photos"**/*.{txt,md}
both txt and md files
Note: all globs must use forward slashes, even on Windows.
A function to derive the destination file path from each source.
It must return either an absolute path, or a relative path from cwd
.
function dest(src) {
// the 'src' param is a relative path from 'cwd'
return path.join('bin', src.replace('.txt', '_checksum.txt'));
}
Instead of a function, you can also pass in a string with the following tokens:
$path
relative path of the source file incwd
$name
source file name, without the extension or the.
$ext
source file extension, without the.
Examples:
/absolute/output/$name.$ext
relative/$path/$name_suffix.$ext
Note: this path syntax must use forward slashes, even on Windows.
The async operation to be executed on each file. It will only run if the destination does not exist, or if the source file has changed since. Files are processed in parallel, up to the number of CPUs.
It can be either a function:
function process(src, dest, callback) {
// src and dest are absolute paths
}
Or a string to be executed with child_process.exec, with the following tokens:
$src
the full path to the source file$dest
the full path to the destination file
Examples:
ffmpeg $src -vframes 1 -y $dest
cat $src | md5 > $dest
You can specify if the process
operations should be run in parallel for faster processing. For example, disk-bound operations are usually better done in series, but CPU intensive ones can easily be distributed.
The value can be either:
0
: all operations are done in series (default){number}
: run at most N operations concurrently'cpu'
: run as many operations as there are CPUs / cores
regen
can optionally report on the status of the operations.
You can pass a custom callback, that will be called once before any operation starts, and then after each file has been processed.
regen({ report: progress });
function progress(stats) {
// stats.totalFiles = number of files matching the <src> pattern
// stats.outdated = number of files that needed regen
// stats.processed = number of files processed so far
}
Alternatively, you can pass a string value to display a progress bar in the console:
regen({ report: 'Taking screenshots $progress' })
// Taking screenshots [=== ] 4 / 15 files