Website/node_modules/metalsmith-branch/lib/index.js

136 lines
2.9 KiB
JavaScript
Executable file

'use strict';
var Ware = require('ware')
var match = require('multimatch')
var debug = require('debug')('metalsmith-branch')
var clone = require('clone')
var has = hasOwnProperty
/**
* Metalsmith plugin to run separate middleware pipelines on selected files.
*
* @param {String or Object or Function} filter
* @return {Function}
*
* Example:
*
* metalsmith(__dirname)
* .use( branch()
* .pattern('*.md') // for only md source files,
* .use( markdown() ) // generate html
* )
* .use( branch('images/*') // you can specify pattern or filter in constructor
* .use( imageVariants() )
* )
* .build()
*
* Nested branches are possible too:
*
* metalsmith(__dirname)
* .use( branch('*.md')
* .use( markdown() )
* .use( branch('special/*.html') // post-process markdown files in 'special' dir
* .use( postProcess() )
* )
* )
* .build()
*
*/
module.exports = function plugin(matcher){
var files, root;
var filter = function(){ return true; };
var ware = new Ware();
branch.use = function(fn){
ware.use(fn);
return this;
}
branch.filter = function(fn){
filter = fn;
return this;
}
branch.pattern = function(pattern){
debug('pattern: ' + pattern);
return this.filter( function(file){
return !!match(file,pattern)[0];
});
}
/**
* Run filtered set of files through branch pipeline
* and mutate root (metalsmith) files afterwards.
*
* Note also that root is injected.
* That way, you can mutate the metadata directly in middleware
*
* Note also `done` callback is passed in from root.
*
*/
function run(fn){
var selected = filterObject(files, filter)
var keys = Object.keys(selected)
debug("selected files: " + Object.keys(selected).join(", "));
ware.run(selected,root,function(err){
if (err) return fn(err);
fullMerge(files,selected,keys);
debug("files after branch processed: " + Object.keys(files).join(", "));
fn();
});
}
/**
* Function called by root (metalsmith) pipeline
*
*/
function branch(f,metalsmith,done){
files = f; root = metalsmith;
if (matcher == undefined){
} else if (typeof matcher == "function"){
branch.filter(matcher);
} else {
branch.pattern(matcher);
}
run(done);
}
return branch;
}
// utils
function filterObject( obj, filt ){
var ret = {}, i = -1
for (var k in obj){
i = i + 1;
if (has.call(obj,k)){
if (filt(k,obj[k],i)) ret[k] = obj[k];
}
}
return ret;
}
function fullMerge( obj, selected, keys){
keys = keys || [];
// add new and replace modified
for (var k in selected){
if (has.call(selected,k)) obj[k] = selected[k];
};
// delete deleted
for (var i=0;i<keys.length;++i){
var k = keys[i];
if (!(has.call(selected,k))) delete obj[k];
};
}