Added presentation framework.

This commit is contained in:
Michael Krotscheck 2015-07-15 18:29:20 -07:00
parent 92bca6599b
commit 178f5ad135
8 changed files with 534 additions and 0 deletions

12
.editorconfig Normal file
View File

@ -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

6
.gitignore vendored
View File

@ -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

28
README.md Normal file
View File

@ -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

33
bower.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "presentations",
"version": "1.0.0",
"homepage": "https://krotscheck.github.com/presentations",
"authors": [
"Michael Krotscheck <krotscheck@gmail.com>"
],
"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"
]
}
}
}

234
gulpfile.js Normal file
View File

@ -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
}));
});
})();

39
package.json Normal file
View File

@ -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"
}

71
src/index.hbs Normal file
View File

@ -0,0 +1,71 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Convention Presentations</title>
<link rel="stylesheet"
href="css/bootstrap.css">
<meta name="description"
content="Convention Presentations by {{author.name}}">
<meta name="author" content="{{author.name}}">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
</head>
<body style="margin-top: 70px; margin-bottom: 70px">
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<span class="navbar-brand">Convention Presentations</span>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<ul class="list-unstyled">
<li><strong>Author:</strong> {{author.name}}</li>
<li><strong>Website:</strong>
<a href="{{author.url}}">{{author.url}}</a>
</li>
</ul>
<br/>
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="col-xs-2">Last Updated</th>
<th>Title</th>
</tr>
</thead>
<tbody>
{{#each presentations}}
<tr>
<td>{{datetime mtime}}</td>
<td>
<a href="{{path}}" target="_blank">
{{title}}
</a>
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
<nav class="navbar navbar-default navbar-fixed-bottom">
<div class="container-fluid">
<p class="navbar-text">
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/">
<img alt="Creative Commons License"
src="https://i.creativecommons.org/l/by/4.0/88x31.png"/>
</a>
This work by <span xmlns:cc="http://creativecommons.org/ns#"
property="cc:attributionName">{{author.name}}</span>
is licensed under a <a rel="license"
href="http://creativecommons.org/licenses/by/4.0/">Creative
Commons Attribution 4.0 International License</a>.
</p>
</div>
</nav>
</body>
</html>

111
src/template/index.hbs Normal file
View File

@ -0,0 +1,111 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{presentation.title}}</title>
<meta name="description"
content="{{presentation.description}}">
<meta name="author" content="{{author.name}}">
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style"
content="black-translucent"/>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="../css/reveal.css">
<link rel="stylesheet" href="../css/font-awesome.css">
<link rel="stylesheet" href="../css/font-mfizz.css">
<link rel="stylesheet" href="../css/theme/serif.css" id="theme">
<!-- Code syntax highlighting -->
<link rel="stylesheet" href="../lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href =
window.location.search.match(/print-pdf/gi) ?
'../css/print/pdf.css' :
'../css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
<!--[if lt IE 9]>
<script src="../lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal" data-transition="slide">
<div class="slides">
<section>
<h1>{{presentation.title}}</h1>
<h3>{{presentation.description}}</h3>
<p>by {{author.name}}</p>
</section>
</div>
<script src="../lib/js/head.min.js"></script>
<script src="../js/reveal.js"></script>
<script>
// Full list of configuration options available at:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
transition: 'slide', // none/fade/slide/convex/concave/zoom
// Optional reveal.js plugins
dependencies: [
{
src: '../lib/js/classList.js', condition: function () {
return !document.body.classList;
}
},
{
src: '../plugin/markdown/marked.js',
condition: function () {
return !!document.querySelector('[data-markdown]');
}
},
{
src: '../plugin/markdown/markdown.js',
condition: function () {
return !!document.querySelector('[data-markdown]');
}
},
{
src: '../plugin/highlight/highlight.js',
async: true,
condition: function () {
return !!document.querySelector('pre code');
},
callback: function () {
hljs.initHighlightingOnLoad();
}
},
{src: '../plugin/zoom-js/zoom.js', async: true},
{src: '../plugin/notes/notes.js', async: true}
]
});
</script>
</div>
</body>
</html>