only build files that have changed
JavaScript

README.md

npm version Build Status

metalsmith-changed

Only process files that have changed.

metalsmith-changed will write a ctimes json-file to your build-folder in order to keep track of changed files.

Must be used with metalsmith.clean(false), .clean(true) (the default) disables metalsmith-changed and all files are passed on to the next plugin.

metalsmith-changed can also be disabled with force: true and individual files can be ignored (always build) with forcePattern.

example

var Metalsmith = require('metalsmith');
var changed = require('metalsmith-changed');

Metalsmith()
  .clean(false)
  .use(changed())
  ... // more plugins
  .build(function (err) {
    if (err) throw err;
  });

Which is useful when watching files and livereloading:

const Metalsmith = require('metalsmith');
const changed = require('metalsmith-changed');
const livereload = require('metalsmith-livereload');
const nodeStatic = require('node-static');
const watch = require('glob-watcher');
const open = require('open');

const DIR = __dirname + '/test/fixtures/';

/**
 * Build with metalsmith.
 */
const build = (clean = false) => (done) => {
  console.log(`Building. clean: ${clean}.`);
  Metalsmith(DIR)
    .clean(clean)
    .use(changed())
//    .use(expensivePlugin())  // ie markdown -> html
    .use(livereload({ debug: true }))
    .build((err, files) => {
      let filenames = Object.keys(files).join(', ');
      console.log('Built: ' + filenames);
      done(err);
    });
};

/**
 * Serve files.
 */
var serve = new nodeStatic.Server(DIR + 'build');
require('http').createServer((req, res) => {
  req.addListener('end', () => serve.serve(req, res));
  req.resume();
}).listen(8080);

/**
 * Watch files.
 */
watch(DIR + 'src/**/*', { ignoreInitial: false }, build(false));
// watch(DIR + 'templates/**/*', build(true));  // force build of all files

/**
 * Open browser.
 */
open('http://localhost:8080');

As ctimes are persisted to disk, this works nice with cli tools like watch run too.

forcePattern

If the option forcePattern is defined, files matching the pattern(s) will not be removed from building even if the file has not changed. forcePattern should be a string or an array of strings.

micromatch is used for matching the files.

Example:

Metalsmith()
  .clean(false)
  .use(changed({
    forcePattern: [
      '**/index.md',  // always build index files
      ...             // more patterns
    ]
  }))
  ... // more plugins
  .build(function(err){
    if (err) throw err;
  });

default options

changed({
  force: false,  // build all files
  forcePattern: false,  // always build files matching these patterns
  forceAllPattern: false,  // force build of all files if files matching this pattern is changed
  ctimes: 'metalsmith-changed-ctimes.json'  // where to store ctimes, relative to the build folder
})

metalsmith-changed-ctimes.json

metalsmith-changed-ctimes.json is written to your build folder upon every build. metalsmith-changed takes ctimes from files[n].stats.ctime, so if a plugin creates files with .stats.ctime, metalsmith-changed can be used with it.

Files without stats.ctime are always built.

develop

npm build  # babel
npm test
DEBUG=metalsmith-changed npm test  # test with debug output

release

npm version patch|minor|major
npm publish