2017-12-12 13:00:19 +01:00

96 lines
2.6 KiB
JavaScript

// This plugin mutates the `files` map of metalsmith
// at build time to only keep what was updated
// We consider any update in layouts/ to trigger an update on every html file
// Otherwise, if it's an asset or a file with no layout then we compare
// the file's last modification time to the process start time
const path = require('path');
const async = require('async');
const chokidar = require('chokidar');
let lastRunTime = false;
let layoutChange = true;
let cssChange = true;
const layoutFiles = path.join(__dirname, '../layouts/**/*');
const cssFiles = path.join(__dirname, '../src/stylesheets/**/*');
const CSSEntryPoints = ['stylesheets/index.css', 'stylesheets/header.css'];
const hasChanged = file =>
file.stats && file.stats.ctime && file.stats.mtime
? Date.parse(file.stats.ctime) > lastRunTime ||
Date.parse(file.stats.mtime) > lastRunTime
: true;
module.exports = function onlyChanged(files, metalsmith, cb) {
if (lastRunTime === false) {
chokidar
.watch(layoutFiles, { ignoreInitial: true })
.on('all', () => {
layoutChange = true;
})
.on('error', err => {
throw err;
});
chokidar
.watch(cssFiles, { ignoreInitial: true })
.on('all', () => {
cssChange = true;
})
.on('error', err => {
throw err;
});
lastRunTime = Date.now();
layoutChange = false;
cssChange = false;
cb(null);
return;
}
async.parallel(
Object.entries(files).map(([name, file]) => done => {
if (!file.stats) {
done(null); // keep file, we do not know
return;
}
if (!file.layout) {
const cssEntryPointNeedsUpdate =
CSSEntryPoints.indexOf(name) !== -1 && cssChange === true;
if (!hasChanged(file) && !cssEntryPointNeedsUpdate) {
// file has no layout and was not updated, remove file
// from files to process
// eslint-disable-next-line no-param-reassign
delete files[name];
}
done(null);
return;
}
if (/\.html$/.test(name) && layoutChange === true) {
done(null); // html page need rebuild, some layout files changed
return;
}
if (!hasChanged(file)) {
// eslint-disable-next-line no-param-reassign
delete files[name]; // file was not updated, layouts were not updated
}
done(null);
}),
err => {
if (!err) {
lastRunTime = Date.now();
layoutChange = false;
cssChange = false;
console.log(`[metalsmith]: onlyChanged | ${Object.keys(files)}`); // eslint-disable-line no-console
}
cb(err);
}
);
};