atomatic
Version:
An easy to use build and development tool for Atomic Design Systems, that works with rollup.js, Browserify, webpack and many more...
142 lines (114 loc) • 4.45 kB
JavaScript
const
minimatch = require('minimatch'),
path = require('path'),
globWatcher = require('glob-watcher'),
sgUtil = require('./util');
class Watcher {
constructor({conf, browserSync, CollectorStore: {getSections, getFiles, updateTimestamp}}) {
this.getSections = getSections;
this.getFiles = getFiles;
this.updateTimestamp = updateTimestamp;
this.browserSync = browserSync;
this.globOptions = conf.get('globOptions');
this.htmlExt = conf.get('htmlExt');
this.templateExt = conf.get('templateExt');
this.dataExt = conf.get('dataExt');
this.emitDelay = conf.get('emitDelay', 100);
this.logLevel = conf.get('logLevel', 0);
this.emitTimeout = null;
this.emitQue = {};
this.watch = this.watch.bind(this);
this.start = this.start.bind(this);
this.onAddFiles = this.onAddFiles.bind(this);
this.onUnlinkFiles = this.onUnlinkFiles.bind(this);
this.emitDelayed = this.emitDelayed.bind(this);
this.resetEmitQue = this.resetEmitQue.bind(this);
this.addToEmitQue = this.addToEmitQue.bind(this);
}
watch(section) {
const {watchPattern} = section;
return globWatcher(watchPattern, {ignoreInitial: true})
.on('change', (filename) => this.onChangeFiles(path.resolve(filename), section))
.on('add', (filename) => this.onAddFiles(path.resolve(filename), section))
.on('unlink', (filename) => this.onUnlinkFiles(path.resolve(filename), section));
}
start() {
this.getSections().forEach(this.watch);
}
onAddFiles(filename, section) {
if (minimatch(filename, `**/*.${this.templateExt}`)) {
if (this.logLevel > 1) {
sgUtil.log(`Watcher: file has been added (${filename})`);
}
const affectedUrls = this.updateTimestamp(filename);
this.removeCaches(filename, section);
section.setFile({filename, section});
this.emitDelayed(filename, affectedUrls, 'onadd');
}
if (minimatch(filename, `**/*.+(${this.dataExt}|js)`)) {
this.onChangeFiles(filename, section);
}
}
onChangeFiles(filename, section) {
if (this.logLevel > 1) {
sgUtil.log(`Watcher: file has been updated (${filename})`);
}
if (minimatch(filename, `**/*+(${this.templateExt}|${this.dataExt}|js)`)) {
filename = sgUtil.replaceFileExtension(filename, this.templateExt);
const affectedUrls = this.updateTimestamp(filename);
section.updateFile(filename);
this.removeCaches(filename, section);
this.emitDelayed(filename, affectedUrls, 'onchange');
}
}
onUnlinkFiles(filename, section) {
if (minimatch(filename, `**/*.${this.templateExt}`)) {
if (this.logLevel > 1) {
sgUtil.log(`Watcher: file has been unlinked (${filename})`);
}
const affectedUrls = this.updateTimestamp(filename);
section.unsetFile(filename);
this.removeCaches(filename, section);
this.emitDelayed(filename, affectedUrls, 'onunlink');
}
if (minimatch(filename, `**/*.+(${this.dataExt}|js)`)) {
this.onChangeFiles(filename, section);
}
}
addToEmitQue({filename, extension}) {
if (this.emitQue[extension] === undefined) {
this.emitQue[extension] = [];
}
this.emitQue[extension].push(filename);
}
resetEmitQue() {
this.emitQue = {};
}
emitDelayed(filename, affectedUrls, origin) {
const
{htmlExt, templateExt, dataExt, emitQue, emitDelay, addToEmitQue, resetEmitQue, browserSync} = this,
extension = sgUtil.getFileExtension(filename);
if ([htmlExt, templateExt, dataExt].indexOf(extension) !== -1) {
addToEmitQue({filename, extension});
clearTimeout(this.emitTimeout);
const extensions = Object.keys(emitQue);
this.emitTimeout = setTimeout(() => {
sgUtil.log(`[atomatic] Emit reload based on file changes`, 'bs');
browserSync.sockets.emit('atomatic:reload', affectedUrls);
browserSync.emitter.emit('atomatic:change', affectedUrls);
if (!origin !== 'onchange' || !extensions.indexOf(dataExt)) {
browserSync.sockets.emit('atomatic:fetchSection');
}
resetEmitQue();
}, emitDelay);
}
}
removeCaches(filename, section) {
section._timestamp = 0;
const dirname = path.dirname(filename);
Object.keys(this.globOptions.cache)
.filter(key => key.indexOf(dirname) !== -1)
.map(key => delete this.globOptions.cache[key]);
}
}
module.exports = Watcher;