From 178f5ad1358b7c3e2275ff4340135ea4f8a9a629 Mon Sep 17 00:00:00 2001 From: Michael Krotscheck Date: Wed, 15 Jul 2015 18:29:20 -0700 Subject: [PATCH] Added presentation framework. --- .editorconfig | 12 +++ .gitignore | 6 ++ README.md | 28 +++++ bower.json | 33 ++++++ gulpfile.js | 234 +++++++++++++++++++++++++++++++++++++++++ package.json | 39 +++++++ src/index.hbs | 71 +++++++++++++ src/template/index.hbs | 111 +++++++++++++++++++ 8 files changed, 534 insertions(+) create mode 100644 .editorconfig create mode 100644 README.md create mode 100644 bower.json create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 src/index.hbs create mode 100644 src/template/index.hbs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..025b86f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 123ae94..c825564 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,9 @@ build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules +bower_components + +# IDE things +.idea +*.iml +dist diff --git a/README.md b/README.md new file mode 100644 index 0000000..15b2640 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +My Convention Presentations +=========================== + +If you're interested in my presentations, you can go look at them here: +https://krotscheck.github.io/presentations/ + + +Building your own presentations +------------------------------- + +If you would like to use this repository as a base from which to build your +own presentation website, you can clone the ``starter`` branch and work from +there. The following commands will get you started: + + // This will install miscellaneous runtime dependencies. + npm install + + // This will start a VERY basic presentation wizard. To modify the + // output, make changes in ./src/template/index.hbs + npm run new + + // This will create a local webhost, serving all of your presentations. + // It will autodetect changes and refresh any applicable pages. + npm run serve + + // This will construct your current presentations, and push them to + // gh-pages. + npm run release diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..090f7c2 --- /dev/null +++ b/bower.json @@ -0,0 +1,33 @@ +{ + "name": "presentations", + "version": "1.0.0", + "homepage": "https://krotscheck.github.com/presentations", + "authors": [ + "Michael Krotscheck " + ], + "license": "Apache-2.0", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "font-awesome": "~4.3.0", + "font-mfizz": "~2.0.1", + "reveal.js": "~3.1.0", + "bootstrap": "~3.3.5" + }, + "overrides": { + "font-mfizz": { + "main": [ + "css/font-mfizz.css", + "fonts/font-mfizz.eot", + "fonts/font-mfizz.svg", + "fonts/font-mfizz.ttf", + "fonts/font-mfizz.woff" + ] + } + } +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..4ea26d3 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,234 @@ +(function initializeGulp () { + 'use strict'; + + var fs = require('fs'); + var cheerio = require('cheerio'); + var rimraf = require('rimraf'); + var mainBowerFiles = require('main-bower-files'); + + var gulp = require('gulp'); + var git = require('gulp-git'); + var filter = require('gulp-filter'); + var less = require('gulp-less'); + 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', + 'hbs': dir.src + '/index.hbs', + 'index': dir.src + '/index.hbs' + }; + + // Contents of all our bower dependencies' main:[] fields. + var bowerFiles = mainBowerFiles(); + + // 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(dir.src); + + for (var i = 0; i < files.length; i++) { + var file = dir.src + '/' + files[i] + '/index.html'; + 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'), + 'author': $('head meta[name="author"]').attr('content'), + 'mtime': stat.mtime, + 'path': files[i] + '/index.html' + }); + } catch (e) { + // Do nothing + } + } + presentations.sort(function (a, b) { + return a.mtime >= b.mtime ? 1 : -1; + }); + return presentations; + } + + /** + * 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 bower dependencies. Reveal.js + * is given a special snowflake status, because it doesn't observe the + * standard packaging format that bower files like. + */ + gulp.task('package:libs', function (cb) { + var resolveCSS = gulp.src(bowerFiles) + .pipe(filter('*.css')) + .pipe(gulp.dest(dir.dist + '/css')); + + var resolveLESS = gulp.src(bowerFiles) + .pipe(filter('*.less')) + .pipe(less()) + .pipe(gulp.dest(dir.dist + '/css')); + + var resolveFonts = gulp.src(bowerFiles) + .pipe(filter(['*.otf', '*.eot', '*.svg', '*.ttf', '*.woff', '*.woff2'])) + .pipe(gulp.dest(dir.dist + '/fonts')); + + var resolveLibs = gulp.src(bowerFiles) + .pipe(filter('*.js')) + .pipe(gulp.dest(dir.dist + '/js')); + + // Reveal.js is a special snowflake. + var resolveReveal = gulp.src('./bower_components/reveal.js/*/**/*.*', + {'base': './bower_components/reveal.js/'}) + .pipe(ignore(['**/test/**', '*.js'])) + .pipe(filter([ + '**/*.js', + '**/*.css', + '**/*.eot', + '**/*.ttf', + '**/*.woff' + ])) + .pipe(gulp.dest(dir.dist)); + + return streamqueue({'objectMode': true}, resolveCSS, resolveLESS, + resolveReveal, resolveLibs, resolveFonts); + }); + + /** + * Package the handlebars files. + */ + gulp.task('package:hbs', function () { + + var templateData = { + 'presentations': buildPresentationManifest(), + 'author': packageJson.author + }; + + // Automatically build the site list. + return gulp.src(paths.hbs, {'base': dir.src}) + .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', ['package:html', 'package:hbs', 'package:libs']); + + /** + * 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, ['package:html']); + gulp.watch(paths.hbs, ['package:hbs']); + + return gulp.src(dir.dist) + .pipe(webserver({ + 'livereload': true, + 'open': true + })); + }); +})(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..65441f5 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "presentations", + "version": "1.0.0", + "description": "My convention presentations.", + "main": "index.html", + "private": true, + "scripts": { + "postinstall": "bower install", + "start": "gulp serve", + "prestart": "gulp package", + "prepublish": "gulp package", + "new": "gulp new" + }, + "author": { + "name": "Michael Krotscheck", + "email": "krotscheck@gmail.com", + "url": "http://www.krotscheck.net/" + }, + "license": "Apache-2.0", + "dependencies": {}, + "devDependencies": { + "bower": "^1.4.1", + "cheerio": "^0.19.0", + "gulp": "^3.9.0", + "gulp-compile-handlebars": "^0.5.0", + "gulp-filter": "^3.0.0", + "gulp-git": "^1.2.4", + "gulp-ignore": "^1.2.1", + "gulp-less": "^3.0.3", + "gulp-prompt": "^0.1.2", + "gulp-rename": "^1.2.2", + "gulp-util": "^3.0.6", + "gulp-webserver": "^0.9.1", + "main-bower-files": "^2.9.0", + "rimraf": "^2.4.2", + "streamqueue": "^1.1.0" + }, + "repository": "git@github.com:krotscheck/presentations.git" +} diff --git a/src/index.hbs b/src/index.hbs new file mode 100644 index 0000000..c5cbc93 --- /dev/null +++ b/src/index.hbs @@ -0,0 +1,71 @@ + + + + + + Convention Presentations + + + + + + + + +
+
+
+ +
+ + + + + + + + + {{#each presentations}} + + + + + {{/each}} + +
Last UpdatedTitle
{{datetime mtime}} + + {{title}} + +
+
+
+
+ + + diff --git a/src/template/index.hbs b/src/template/index.hbs new file mode 100644 index 0000000..1d05d8f --- /dev/null +++ b/src/template/index.hbs @@ -0,0 +1,111 @@ + + + + + + + {{presentation.title}} + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

{{presentation.title}}

+ +

{{presentation.description}}

+ +

by {{author.name}}

+
+
+ + + + + +
+ +