(function initializeGulp () { 'use strict'; var fs = require('fs'); var cheerio = require('cheerio'); var rimraf = require('rimraf'); var gulp = require('gulp'); var git = require('gulp-git'); var filter = require('gulp-filter'); var less = require('gulp-less'); var data = require('gulp-data'); var change = require('gulp-change'); var rsync = require('gulp-rsync'); var webserver = require('gulp-webserver'); var streamqueue = require('streamqueue'); var ignore = require('gulp-ignore'); var prompt = require('gulp-prompt'); var handlebars = require('gulp-compile-handlebars'); var rename = require('gulp-rename'); var dir = { 'dist': './dist', 'src': './src' }; // List of file paths. var paths = { 'html': dir.src + '/**/*.html', 'index': dir.src + '/index.hbs', 'css': dir.src + '/css/**/*.css', 'js': dir.src + '/js/**/*.js', 'keybase': dir.src + '/keybase.txt', 'talks': dir.src + '/talks', 'talkindex': dir.src + '/talks/index.hbs', 'posts': dir.src + '/posts', 'images': [ dir.src + '/**/*.png', dir.src + '/**/*.gif', dir.src + '/**/*.jpg', dir.src + '/**/*.jpeg', dir.src + '/**/*.svg' ] }; // The current package.json file. var packageJson = require('./package.json'); /** * The handlebars configuration object. */ var handlebarsConfig = { helpers: { 'datetime': function (object) { return object.toLocaleDateString(); } } }; /** * This method parses through discovered presentations, reads their * html metadata, and returns an array of that metadata. */ function buildPresentationManifest () { var presentations = []; var files = fs.readdirSync(paths.talks); for (var i = 0; i < files.length; i++) { var file = paths.talks + '/' + files[i]; try { var stat = fs.statSync(file); var $ = cheerio.load(fs.readFileSync(file)); presentations.push({ 'title': $("head title").text(), 'description': $("head meta[name='description']").attr('content'), 'mtime': stat.mtime, 'path': 'talks/' + files[i].replace('.hbs', '.html') }); } catch (e) { // Do nothing } } presentations.sort(function (a, b) { return a.mtime >= b.mtime ? 1 : -1; }); return presentations; } /** * This method parses through discovered posts, reads their * html metadata, and returns an array of that metadata. */ function buildPostManifest () { var posts = []; var files = fs.readdirSync(paths.posts); for (var i = 0; i < files.length; i++) { var file = paths.posts + '/' + files[i]; try { var stat = fs.statSync(file); var $ = cheerio.load(fs.readFileSync(file)); posts.push({ 'title': $("head title").text(), 'description': $("head meta[name='description']").attr('content'), 'mtime': stat.mtime, 'path': 'posts/' + files[i].replace('.hbs', '.html') }); } catch (e) { // Do nothing } } posts.sort(function (a, b) { return a.mtime >= b.mtime ? 1 : -1; }); return posts; } function performTemplateChange(content) { var file = dir.src + '/layout/post.hbs'; var stat = fs.statSync(file); return fs.readFileSync(file, {'encoding': 'utf-8'}); } function performTalkTemplateChange(content) { var file = dir.src + '/layout/talk.hbs'; var stat = fs.statSync(file); return fs.readFileSync(file, {'encoding': 'utf-8'}); } /** * Clean the output directory. * * @param {Function} cb callback. * @return {*} A gulp stream that performs this action. */ gulp.task('clean', function (cb) { rimraf(dir.dist, cb); }); /** * Build the static file structure from our dependencies. */ gulp.task('package:libs', function (cb) { var resolveBootstrap = gulp.src( './node_modules/bootstrap/dist/css/bootstrap.css') .pipe(gulp.dest(dir.dist + '/css')); var resolveCSS = gulp.src( './node_modules/@fortawesome/fontawesome-free/css/*') .pipe(filter('*.css')) .pipe(gulp.dest(dir.dist + '/css')); var resolveFonts = gulp.src( './node_modules/@fortawesome/fontawesome-free/webfonts/*') .pipe(filter(['*.otf', '*.eot', '*.svg', '*.ttf', '*.woff', '*.woff2'])) .pipe(gulp.dest(dir.dist + '/fonts')); // Reveal.js is a special snowflake. var resolveReveal = gulp.src('./node_modules/reveal.js/*/**/*.*', {'base': './node_modules/reveal.js/'}) .pipe(ignore(['**/test/**', '*.js'])) .pipe(filter([ '**/*.js', '**/*.css', '**/*.eot', '**/*.ttf', '**/*.woff' ])) .pipe(gulp.dest(dir.dist)); streamqueue({'objectMode': true}, resolveBootstrap, resolveCSS, resolveReveal, resolveFonts); cb() }); /** * Package all images. */ gulp.task('package:images', function () { return gulp.src(paths.images, {'base': dir.src}) .pipe(gulp.dest(dir.dist)); }); /** * Package keybase static files. */ gulp.task('package:keybase', function () { return gulp.src(paths.keybase, {'base': dir.src}) .pipe(gulp.dest(dir.dist)); }); /** * Package all css. */ gulp.task('package:css', function () { return gulp.src(paths.css, {'base': dir.src}) .pipe(gulp.dest(dir.dist)); }); /** * Package all js. */ gulp.task('package:js', function () { return gulp.src(paths.js, {'base': dir.src}) .pipe(gulp.dest(dir.dist)); }); /** * Package the handlebars files. */ gulp.task('package:talkindex', function () { var templateData = { 'presentations': buildPresentationManifest(), 'author': packageJson.author }; // Automatically build the site list. return gulp.src(dir.src + '/talks.hbs', {'base': dir.src}) .pipe(handlebars(templateData, handlebarsConfig)) .pipe(rename(function (path) { path.extname = ".html"; })) .pipe(gulp.dest(dir.dist)); }); /** * Package the handlebars files. */ gulp.task('package:postindex', function () { var templateData = { 'posts': buildPostManifest(), 'author': packageJson.author }; // Automatically build the site list. return gulp.src(dir.src + '/index.hbs', {'base': dir.src}) .pipe(handlebars(templateData, handlebarsConfig)) .pipe(rename(function (path) { path.extname = ".html"; })) .pipe(gulp.dest(dir.dist)); }); gulp.task('package:posts', function () { var templateData = { 'author': packageJson.author }; // Automatically build the site list. return gulp.src(dir.src + '/posts/*.hbs', {'base': dir.src}) .pipe(data(function(file) { var stat = fs.statSync(file.path); var $ = cheerio.load(fs.readFileSync(file.path)); return { 'title': $("head title").text(), 'description': $("head meta[name='description']").attr('content'), 'body': $("body").html(), }})) .pipe(change(performTemplateChange)) .pipe(handlebars(templateData, handlebarsConfig)) .pipe(rename(function (path) { path.extname = ".html"; })) .pipe(gulp.dest(dir.dist)); }); gulp.task('package:talks', function () { var templateData = { 'author': packageJson.author }; // Automatically build the site list. return gulp.src(dir.src + '/talks/*.hbs', {'base': dir.src}) .pipe(data(function(file) { var stat = fs.statSync(file.path); var $ = cheerio.load(fs.readFileSync(file.path)); var newpath = file.clone(); return { 'title': $("head title").text(), 'description': $("head meta[name='description']").attr('content'), 'body': $("body").html(), 'path': newpath.relative.replace('.hbs', '.html'), }})) .pipe(change(performTalkTemplateChange)) .pipe(handlebars(templateData, handlebarsConfig)) .pipe(rename(function (path) { path.extname = ".html"; })) .pipe(gulp.dest(dir.dist)); }); /** * Copy the HTML files into the dist folder. */ gulp.task('package:html', function () { return gulp.src(paths.html, {'base': dir.src}) .pipe(gulp.dest(dir.dist)); }); /** * This task builds a new presentation from the base presentation template. */ gulp.task('new', function () { var templateData = { author: packageJson.author }; var destinationFolder = ''; return gulp.src(dir.src + '/template/index.hbs') .pipe(prompt.prompt([ { type: 'input', name: 'folderName', message: 'Presentation Folder Name (/^[a-z][a-z_]+$/):', validate: function (value) { var result = value.match(/^([a-z][a-z_]+)$/); return result !== null; } }, { type: 'input', name: 'title', message: 'Presentation Title:' }, { type: 'input', name: 'description', message: 'Presentation Description:' }, { type: 'input', name: 'event', message: 'First presented at:' }, { type: 'input', name: 'event', message: 'First presented on (date):' }], function (res) { destinationFolder = res.folderName; templateData.presentation = { 'title': res.title, 'description': res.description, 'event': res.event } })) .pipe(handlebars(templateData, handlebarsConfig)) .pipe(rename(function (path) { path.dirname += '/' + destinationFolder; path.basename = "index"; path.extname = ".html"; })) .pipe(gulp.dest(dir.src)) .pipe(git.add()); }); /** * Package the entire site into the dist folder. */ gulp.task('package', gulp.series('package:html', 'package:talks', 'package:talkindex', 'package:posts', 'package:postindex', 'package:libs', 'package:keybase', 'package:images', 'package:css', 'package:js')); gulp.task('rsync', function () { gulp.src(dir.dist) .pipe(rsync({ root: dir.dist, hostname: 'kleos.inaugust.com', destination: '/var/www/inaugust.com', recursive: true })); }); gulp.task('push', function () { gulp.src(dir.dist) git.push('origin', 'master', function (err) { if (err) throw err; }); }); /** * Build the current release package and push it */ gulp.task('release', gulp.series('package', 'rsync', 'push')); /** * Start a local server and serve the application code. This is * equivalent to opening index.html in a browser. * * @return {*} A gulp stream that performs this action. */ gulp.task('serve', function () { gulp.watch(paths.html, gulp.series('package:html')); gulp.watch(paths.images, gulp.series('package:images')); gulp.watch(paths.talks, gulp.series('package:talks')); gulp.watch(dir.src + '/talks/*.hbs', gulp.series('package:talks')); gulp.watch(paths.css, gulp.series('package:css')); gulp.watch(paths.js, gulp.series('package:js')); gulp.watch(paths.posts, gulp.series('package:posts')); gulp.watch(paths.index, gulp.series('package:posts')); return gulp.src(dir.dist) .pipe(webserver({ 'livereload': true, 'open': true })); }); })();