From 3ae91a0ae00571044721eaead914eaaca29beff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Sko=C5=99epa?= <jakub@skorepa.info> Date: Sat, 5 Mar 2016 19:17:02 +0100 Subject: [PATCH] Start work on promisifying and tidying up Created jobs which will replace sequence with promise-based api --- .gitignore | 1 + index.js | 337 +++++++++++++++++------------------ package.json | 1 + sitegin/jobs.js | 134 ++++++++++++++ sitegin/sitegin.js | 43 ++--- sitegin/transformer-other.js | 15 +- 6 files changed, 334 insertions(+), 197 deletions(-) create mode 100644 sitegin/jobs.js diff --git a/.gitignore b/.gitignore index b3cb2ed..c09a9cb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build-debug content theme static +.buildconfig diff --git a/index.js b/index.js index fa36619..8b12354 100755 --- a/index.js +++ b/index.js @@ -1,178 +1,175 @@ #!/usr/bin/env node -var sitegin = require('./sitegin/sitegin'); - -var input = new sitegin.input.Hugo(process.cwd()+'/content/'); -var transformerMD = new sitegin.transformer.Markdown; -var transformerTags = new sitegin.transformer.Tags; -var transformerNunjucks = new sitegin.transformer.Nunjucks; -var transformerUrlizeTags = new sitegin.transformer.UrlizeTags; -var output = new sitegin.output.Filesystem; -var sequencer = new sitegin.Sequencer; -var transformerGit = new sitegin.transformer.Git; -var transformerOther = new sitegin.transformer.Other; -var transformerImages = new sitegin.transformer.Images; - -var sass = require('node-sass'); -var fs = require('fs'); - -var builddir = "build"; -if(process.argv[2] !== "compileonly") builddir = "build-debug"; - -var oldEmit = sequencer.emit; -sequencer.emit = function() { - console.log("Event:",arguments[0]); - oldEmit.apply(sequencer, arguments); -} - -sequencer.on("", function(ev) { - console.log("Event:",ev); -}) - -var tasks = []; -var onDone = function(what) { - console.log(what, 'done'); - var removed = false; - for(var i = 0; i < tasks.length; i++) { - if(tasks[i] == what) { - removed = true; - tasks.splice(i,1); - break; - } +require('./sitegin/sitegin')({ + watch: false +}, function onLoad(jobs) { + var sass = require('node-sass'); + var fs = require('fs'); + + console.log('Sitegin successfully loaded'); + jobs.onReload(function() { + console.log("Sitegin reloaded"); + }) + +/* + var builddir = "build"; + if(process.argv[2] !== "compileonly") builddir = "build-debug"; + + var oldEmit = sequencer.emit; + sequencer.emit = function() { + console.log("Event:",arguments[0]); + oldEmit.apply(sequencer, arguments); } - if(!removed && process.argv[2] == "compileonly") throw new Error("Task "+what+" ended but was never registered"); - if(tasks.length == 0 && process.argv[2] == "compileonly") { - console.log("exitting"); - process.exit(); + + sequencer.on("", function(ev) { + console.log("Event:",ev); + }) + + var tasks = []; + var onDone = function(what) { + console.log(what, 'done'); + var removed = false; + for(var i = 0; i < tasks.length; i++) { + if(tasks[i] == what) { + removed = true; + tasks.splice(i,1); + break; + } + } + if(!removed && process.argv[2] == "compileonly") throw new Error("Task "+what+" ended but was never registered"); + if(tasks.length == 0 && process.argv[2] == "compileonly") { + console.log("exitting"); + process.exit(); + } } -} - - -// PIPELINE -sequencer -.load(input) -.registerNext(transformerGit) -.registerNext(transformerOther) -.registerNext(transformerImages) -.registerNext(transformerMD) -.registerNext(transformerUrlizeTags) -.registerNext(transformerTags) -.registerNext(transformerNunjucks) -.registerNext(output) -.finish(function(list) { - onDone("sequencer"); -}) -tasks.push('sequencer'); - -try {fs.mkdirSync(builddir);}catch(e){} -try {fs.mkdirSync(builddir+"/theme");}catch(e){} - -// SASS -var rendersass = function() { - sass.render ({file: "theme/sass/style.scss"},function(err, result) { - if(err == null) { - console.log("compiled sass"); - fs.writeFile(builddir+"/theme/style.css",result.css); - } else console.log("error ", err); - onDone("sass"); - }); -}; -tasks.push('sass'); - -rendersass(); - -// STATIC FILES -var fsextra = require('node-fs-extra'); -tasks.push('copy static'); -fsextra.copy( - 'static', - builddir, - function(file){ return !(file.match(".git") || file.match("static/articles")); }, - function(){onDone("copy static");} - ); -tasks.push('copy static/articles'); -fsextra.copy( - 'static/articles', - builddir+"/clanek", - function(){onDone("copy static/articles");} - ); -tasks.push('copy theme static'); -fsextra.copy( - 'theme/static', - builddir, - function(file){ return !file.match("\\.git") }, - function(){onDone("copy theme static");} - ); - -// DEVEL INCOMING -if(process.argv[2] !== "compileonly") { - var sync = require('browser-sync').create(); - sync.init({ - server: { - baseDir: builddir - }, - ui: { - port: 1338 - }, - port: 1337 - }); - - // CHANGE WATCHER - var chokidar = require('chokidar'); - - chokidar.watch('theme/static', {ignoreInitial: true, usePolling: false}) - .on('all', (event, path) => { - console.log(path); - console.log("theme static copy watcher"); - fsextra.copy( - 'theme/static', - builddir, - function(file){ return !file.match(".git"); }, - function(){} - ); - sync.reload(path); - }); - - chokidar.watch('static/', {ignoreInitial: true, usePolling: false}) - .on('all', (event, path) => { - if(path.match(/^static\/articles\/.*$/)) return; - console.log("static copy watcher"); - fsextra.copy( + + + // PIPELINE + sequencer + .load(input) + .registerNext(transformerGit) + .registerNext(transformerOther) + .registerNext(transformerImages) + .registerNext(transformerMD) + .registerNext(transformerUrlizeTags) + .registerNext(transformerTags) + .registerNext(transformerNunjucks) + .registerNext(output) + .finish(function(list) { + onDone("sequencer"); + }) + tasks.push('sequencer'); + + try {fs.mkdirSync(builddir);}catch(e){} + try {fs.mkdirSync(builddir+"/theme");}catch(e){} + + // SASS + var rendersass = function() { + sass.render ({file: "theme/sass/style.scss"},function(err, result) { + if(err == null) { + console.log("compiled sass"); + fs.writeFile(builddir+"/theme/style.css",result.css); + } else console.log("error ", err); + onDone("sass"); + }); + }; + tasks.push('sass'); + + rendersass(); + + // STATIC FILES + var fsextra = require('node-fs-extra'); + tasks.push('copy static'); + fsextra.copy( 'static', builddir, function(file){ return !(file.match(".git") || file.match("static/articles")); }, - function(){} + function(){onDone("copy static");} + ); + tasks.push('copy static/articles'); + fsextra.copy( + 'static/articles', + builddir+"/clanek", + function(){onDone("copy static/articles");} + ); + tasks.push('copy theme static'); + fsextra.copy( + 'theme/static', + builddir, + function(file){ return !file.match("\\.git") }, + function(){onDone("copy theme static");} ); - sync.reload(path); - }) - .unwatch('static/articles'); - - chokidar.watch('static/articles', {ignoreInitial: true, usePolling: false}) - .on('all', (event, path) => { - console.log("static articles copy watcher"); - fsextra.copy('static/articles',builddir+"/clanek",function(){}); - sync.reload(path); - }) - .unwatch('static/articles'); - - chokidar.watch(['theme/','content/'], {ignoreInitial: true, usePolling: false}) - .on('all', (event, path) => { - if(path.match(/^theme\/static\/.*$/)) return; - if(path.match(/^theme\/sass\/.*$/)) return; - console.log("rebuild watcher",path); - sequencer.load(input); - }) - .unwatch("theme/static") - .unwatch("theme/sass"); - - sequencer.finish(function() { - sync.reload("*.html"); - }); - - chokidar.watch('theme/sass', {ignoreInitial: true, usePolling: false}) - .on('all', function(event, path) { - console.log("sass: file change detected - rerendering "+event+" "+path); - rendersass(); - sync.reload(path); - }); -} + // DEVEL INCOMING + if(process.argv[2] !== "compileonly") { + var sync = require('browser-sync').create(); + sync.init({ + server: { + baseDir: builddir + }, + ui: { + port: 1338 + }, + port: 1337 + }); + + // CHANGE WATCHER + var chokidar = require('chokidar'); + + chokidar.watch('theme/static', {ignoreInitial: true, usePolling: false}) + .on('all', (event, path) => { + console.log(path); + console.log("theme static copy watcher"); + fsextra.copy( + 'theme/static', + builddir, + function(file){ return !file.match(".git"); }, + function(){} + ); + sync.reload(path); + }); + + chokidar.watch('static/', {ignoreInitial: true, usePolling: false}) + .on('all', (event, path) => { + if(path.match(/^static\/articles\/.*$/)) return; + console.log("static copy watcher"); + fsextra.copy( + 'static', + builddir, + function(file){ return !(file.match(".git") || file.match("static/articles")); }, + function(){} + ); + sync.reload(path); + }) + .unwatch('static/articles'); + + chokidar.watch('static/articles', {ignoreInitial: true, usePolling: false}) + .on('all', (event, path) => { + console.log("static articles copy watcher"); + fsextra.copy('static/articles',builddir+"/clanek",function(){}); + sync.reload(path); + }) + .unwatch('static/articles'); + + chokidar.watch(['theme/','content/'], {ignoreInitial: true, usePolling: false}) + .on('all', (event, path) => { + if(path.match(/^theme\/static\/.*$/)) return; + if(path.match(/^theme\/sass\/.*$/)) return; + console.log("rebuild watcher",path); + sequencer.load(input); + }) + .unwatch("theme/static") + .unwatch("theme/sass"); + + sequencer.finish(function() { + sync.reload("*.html"); + }); + + chokidar.watch('theme/sass', {ignoreInitial: true, usePolling: false}) + .on('all', function(event, path) { + console.log("sass: file change detected - rerendering "+event+" "+path); + rendersass(); + sync.reload(path); + }); + } + */ +}); diff --git a/package.json b/package.json index 0856faf..d37bc7b 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "nodegit-kit": "^0.8.0", "nunjucks": "^2.3.0", "nunjucks-date-filter": "^0.1.1", + "syntax-error": "^1.1.5", "toml": "~2.3.0", "toml-js": "0.0.8" }, diff --git a/sitegin/jobs.js b/sitegin/jobs.js new file mode 100644 index 0000000..e529de6 --- /dev/null +++ b/sitegin/jobs.js @@ -0,0 +1,134 @@ +var syntaxError = require('syntax-error'); +var fs = require('fs'); +var chokidar = require('chokidar'); +var eventEmitter = new (require('events').EventEmitter); + +var jobList = {}; +var watchers = []; + +function JobError(message, name) { + Error.captureStackTrace(this, JobError); + this.name = name; + this.message = message; + return this; +} + +var onReload = function() {} +var requireError = function(e, jobName, module, reject) { + if(e instanceof SyntaxError) { + var resolved = require.resolve(module); + fs.readFile(resolved, 'utf8', function(err, content) { + console.log(syntaxError(content,resolved)); + reject(new JobError('Failed to register job '+jobName)) + }) + } else { + if(e.code === 'MODULE_NOT_FOUND') + console.log('Module '+module+' not found'); + reject(new JobError('Failed to register job '+jobName)) + } +} + +var jobs = { + register: function(jobName, module, watch) { + return new Promise(function(resolve, reject) { + if(watch === undefined) watch = true; + if(jobList[jobName] !== undefined) { + return Promise.reject( + new JobError('Job '+jobName+' is already registered', 'JobAlreadyRegistered') + ) + } + + try { + var f = require(module); + jobList[jobName] = { + f: f, + module: module + }; + if(watch) jobs.watch(jobName); + resolve(); + } catch(e) {requireError(e, jobName, module, reject);} + }); + }, + reload: function(jobName) { + var module = jobList[jobName].module; + delete require.cache[require.resolve(module)]; + + return new Promise(function(resolve, reject) { + try { + var f = require(module); + delete jobList[jobName]; + jobList[jobName] = { + f: f, + module: module + }; + resolve(); + } catch(e) { + console.log(e); + requireError(e, jobName, module, reject); + } + }); + }, + // registerMultiple( + // {watch: true}, + // ['jobName','./module'],['jobName2','./module2'] + // ) + registerMultiple: function() { + var regs = []; + var watch = true; + for(i in arguments) { + var job = arguments[i]; + if(i == 0) { + if(job.watch !== undefined) watch = job.watch; + } else { + regs.push(jobs.register(job[0], job[1], watch)); + } + } + return Promise.all(regs); + }, + run: function() { + var jobName = arguments[0]; + if(jobList[jobName] === undefined) { + throw new JobError('Job '+jobName+' is not registered', 'JobNotRegistered') + } + return jobList[jobName].f.apply(null, Array.prototype.slice.call(arguments, 1)); + }, + runSequence: function() { + var prom; + for(i in arguments) { + var job = arguments[i]; + if(prom === undefined) + prom = jobs.run(job); + else + prom = prom.then(function() { + var args = [].splice.call(arguments, 0); + args.splice(0,0,job); + return jobs.run.apply(null,args) + }) + } + return prom; + }, + watch: function(jobName) { + var module = jobList[jobName].module; + var file = require.resolve(module); + var w = chokidar.watch(file); + w.on('change', path => { + jobs.reload(jobName) + .then(function() { + return onReload.apply(null, arguments); + }); + }); + watchers.push(w); + }, + onReload: function(f) { + onReload = f; + }, + close: function() { + watchers.forEach(function(w) { + w.close(); + console.log(w.getWatched()); + }); + watchers = []; + } +} + +module.exports = jobs; diff --git a/sitegin/sitegin.js b/sitegin/sitegin.js index f7a4a92..3c413c7 100644 --- a/sitegin/sitegin.js +++ b/sitegin/sitegin.js @@ -1,22 +1,25 @@ -exports.input = { - Hugo: require('./input-hugo') -} - -exports.output = { - Console: require('./output-console'), - Filesystem: require('./output-filesystem') -} +var jobs = require('./jobs'); -exports.transformer = { - Basichtml: require('./transformer-basichtml'), - Git: require('./transformer-git'), - Markdown: require('./transformer-markdown'), - Nunjucks: require('./transformer-nunjucks'), - Tags: require('./transformer-tags'), - UrlizeTags: require('./transformer-urlizetags'), - Other: require('./transformer-other'), - Images: require('./transformer-images'), +module.exports = function(config, onDone) { + jobs.registerMultiple( + config, + /*['input-hugo', './input-hugo'], + ['output-console', './output-console'], + ['output-filesystem', './output-filesystem'], + ['transformer-basichtml', './transformer-basichtml'], + ['transformer-git', './transformer-git'], + ['transformer-markdown', './transformer-markdown'], + ['transformer-nunjucks', './transformer-nunjucks'], + ['transformer-tags', './transformer-tags'], + ['transformer-urlizetags', './transformer-urlizetags'],*/ + ['transformer-other', './transformer-other'] + //['transformer-images', './transformer-images'] + ) + .then(function() { + if(onDone) onDone(jobs); + }) + .catch(function(e) { + console.log(e.stack) + jobs.close(); + }); } - -exports.Page = require('./Page'); -exports.Sequencer = require('./sequencer'); diff --git a/sitegin/transformer-other.js b/sitegin/transformer-other.js index b948057..1c471a7 100644 --- a/sitegin/transformer-other.js +++ b/sitegin/transformer-other.js @@ -1,8 +1,10 @@ var path = require('path'); -module.exports = function() { - var tr = this; - tr.fancyname = "transformer other"; - tr.forEachPage = function(article, cb) { + +module.exports = function(articleList) { + console.log(articleList) + return Promise.resolve(articleList); + + articleList.forEach(function(article) { var img = article.metadata.image; article.file = article.file.split(path.sep).join("/"); if(img) { @@ -12,7 +14,6 @@ module.exports = function() { article.metadata.image = img.replace("/",""); } } - - cb(); - } + }); + return Promise.resolve(articleList); } -- GitLab