@ -3,10 +3,8 @@
var fs = require('fs');
var path = require('path');
var exec = require('child_process').exec;
var _ = require('lodash');
var async = require('async');
var express = require('express');
var handlebars = require('handlebars');
@ -52,28 +50,16 @@ function index(req, res) {
app.get('/', index);
function serveIfExists(path) {
return function _serveIfExists(cb) {
fs.exists(path, function (exists) {
if (!exists) {
cb(null, null);
return;
}
fs.readFile(path, {encoding: 'utf8'}, cb);
});
};
}
app.get('/slides', function showHandler(req, res) {
fs.readdir(pathToFile('data', 'slide'), function (err, files) {
files.sort();
var jsonFiles = _.filter(files, function (file) {
return /^\d+\.json $/.test(file);
return /^\d+\.md$/.test(file);
});
res.send(_.map(jsonFiles, function (file) {
return {
id: parseInt(file.replace(/\.json $/, ''), 10)
id: parseInt(file.replace(/\.md$/, ''), 10)
};
}));
});
@ -85,107 +71,34 @@ app.get(/slide\/(\d+)/, function showHandler(req, res, next) {
return;
}
var slideId = req.params[0];
var slidePath = pathToFile('data', 'slide', slideId + '.json');
fs.exists(slidePath, function (exists) {
if (!exists) {
next();
return;
}
fs.readFile(slidePath, {encoding: 'utf8'}, function (err, content) {
if (err) {
renderError(res, err);
return;
}
try {
var slide = JSON.parse(content);
} catch (err) {
renderError(res, err);
return;
}
var slideIndex = req.params[0];
async.parallel({
copy: serveIfExists(pathToFile('data', 'copy', slide.copy + '.md')),
code: serveIfExists(pathToFile('data', 'code', slide.code + '.js'))
}, function (err, slideContent) {
fs.readdir(pathToFile('data', 'slide'), function (err, files) {
if (err) {
renderError(res, err);
return;
return renderError(res, err);
}
slideContent.id = parseInt(slideId, 10);
slideContent.title = slide.title || '';
res.send(slideContent);
});
});
files.sort();
var markdownFiles = _.filter(files, function (file) {
return /\.md$/.test(file);
});
});
app.get(/results\/([^\/]+)\/(\d\d)$/, function resultsHandler(req, res, next) {
var app = req.params[0];
var slideId = req.params[1];
var validApps = [
'node', 'phantomjs-1.9.8', 'phantomjs-2.0.0'
];
if (!_.contains(validApps, app)) {
next();
return;
}
var slidePath = pathToFile('data', 'slide', slideId + '.json');
fs.exists(slidePath, function (exists) {
if (!exists) {
if (slideIndex > markdownFiles.length) {
return next();
}
var noSlideError = new Error('No code for slide');
async.waterfall([
function (cb) {
fs.readFile(slidePath, {encoding: 'utf8'}, cb);
},
function (content, cb) {
try {
var slide = JSON.parse(content);
} catch (err) {
cb(err, null);
return;
}
cb(null, slide);
},
function (slide, cb) {
var codePath = pathToFile('data', 'code', slide.code + '.js');
fs.exists(codePath, function (exists) {
if (exists) {
cb(null, codePath);
} else {
cb(noSlideError);
}
});
},
function (path, cb) {
exec(app + ' ' + path, cb);
}
], function (err, stdout, stderr) {
if (err === noSlideError) {
next();
return;
}
var markdownFile = markdownFiles[slideIndex - 1];
var markdownPath = pathToFile('data', 'slide', markdownFile);
fs.readFile(markdownPath, {encoding: 'utf8'}, function (err, content) {
if (err) {
res.send({stdout: '', stderr: err.toString()});
return;
return renderError(res, err);
}
res.send({stdout: stdout, stderr: stderr});
});
res.send({
id: parseInt(slideIndex, 10),
copy: content
});
});
});
});