From 2a89dbbc7c4e196689a92164eccf219431be9237 Mon Sep 17 00:00:00 2001 From: Remy Sharp Date: Sat, 21 Jul 2012 15:54:27 +0100 Subject: [PATCH] Server side processor support. Fixes #227. Not supporting Traceur. --- lib/handlers/bin.js | 49 ++++++++++++++++++++++++++++++++++---- lib/processors/index.js | 52 +++++++++++++++++++++++++++++++++++++++++ lib/routes.js | 2 +- 3 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 lib/processors/index.js diff --git a/lib/handlers/bin.js b/lib/handlers/bin.js index 81c78a54..81740110 100644 --- a/lib/handlers/bin.js +++ b/lib/handlers/bin.js @@ -6,6 +6,7 @@ var async = require('asyncjs'), custom = require('../custom'), blacklist = require('../blacklist'), scripts = require('../../scripts.json'), + processors = require('../processors'), Observable = utils.Observable; module.exports = Observable.extend({ @@ -74,6 +75,7 @@ module.exports = Observable.extend({ } }); }, + // TODO decide whether this is used anymore getBinSource: function (req, res) { res.contentType('json'); var output = JSON.stringify(this.templateFromBin(req.bin)); @@ -84,13 +86,40 @@ module.exports = Observable.extend({ res.send(output); }, getBinSourceFile: function (req, res) { - var format = req.params.format; + var format = req.params.format, + settings = req.bin.settings || {}, + reverseProcessorLookup = {}; + + if (format === 'js' || format === 'json') { + format = 'javascript'; + } + + if (format === 'md') { + format = 'markdown'; + } + + if (settings.processors) { + // first shuffle the bin around so they can request .less and get the .css panel...yeah, funky + // { html: 'markdown' } + for (var key in settings.processors) { + reverseProcessorLookup[settings.processors[key]] = key; + } + + // if we want the raw preprocessed content, just map + if (reverseProcessorLookup[format]) { + req.bin[format] = req.bin[reverseProcessorLookup[format]]; + } else if (settings.processors[format]) { + // else we need to convert and process the source + if (processors[settings.processors[format]] !== undefined) { + req.bin[format] = processors[settings.processors[format]](req.bin[format]); + // this delete ensures it doesn't happen again (in case we're looking at .html) + delete req.bin.settings.processors[format]; + } + } + } res.contentType(format); if (format !== 'html') { - if (format === 'js' || format === 'json') { - format = 'javascript'; - } res.send(req.bin[format]); } else { this.getBinPreview(req, res); @@ -314,6 +343,7 @@ module.exports = Observable.extend({ if (!result) { return next(new errors.NotFound('Could not find bin: ' + req.params.bin)); } else { + result.settings = JSON.parse(result.settings || '{}'); req.bin = result; // manually add the full url to the bin to allow templates access req.bin.permalink = helpers.urlForBin(req.bin, true); @@ -461,7 +491,7 @@ module.exports = Observable.extend({ stream: false, code: bin.url || null, revision: bin.url ? (bin.revision || 1) : null, - processors: JSON.parse(bin.settings || '{ "processors": {} }').processors + processors: bin.settings.processors || {} }, settings: options.settings || {panels: []} }; @@ -492,6 +522,15 @@ module.exports = Observable.extend({ }); }, formatPreview: function (bin, options, fn) { + if (bin.settings && bin.settings.processors) { + for (var panel in bin.settings.processors) { + if (processors[bin.settings.processors[panel]] !== undefined) { + bin['original_' + panel] = bin[panel]; + bin[panel] = processors[bin.settings.processors[panel]](bin[panel]); + } + } + } + var formatted = bin.html || '', helpers = this.helpers, insert = [], diff --git a/lib/processors/index.js b/lib/processors/index.js new file mode 100644 index 00000000..0af69bbb --- /dev/null +++ b/lib/processors/index.js @@ -0,0 +1,52 @@ +// 1. preload all the available preprocessors +var path = require('path'), + root = path.resolve(path.join(__dirname, '../../')), + jade = require(root + '/public/js/vendor/jade'), + coffee = require(root + '/public/js/vendor/coffee-script'), + markdown = require(root + '/public/js/vendor/markdown'), + less = require('less'), + stylus = require(root + '/public/js/vendor/stylus'); + +module.exports = { + coffee: function (source) { + var renderedCode = ''; + try { + renderedCode = coffee.compile(source, { + bare: true + }); + } catch (e) { + console && console.error(e.message); + } + return renderedCode; + }, + jade: function (source) { + return jade.compile(source, { pretty: true })(); + }, + markdown: function (source) { + return markdown.toHTML(source); + }, + less: function (source) { + var css = ''; + + less.Parser().parse(source, function (err, result) { + if (err) { + console && console.error(err); + return source; + } + css = result.toCSS().trim(); + }); + return css; + }, + stylus: function (source) { + var css = ''; + + stylus(source).render(function (err, result) { + if (err) { + console && console.error(err); + return; + } + css = result.trim(); + }); + return css; + } +}; \ No newline at end of file diff --git a/lib/routes.js b/lib/routes.js index 3f396d8c..0d33a2d3 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -76,7 +76,7 @@ module.exports = function (app) { // Source app.get('/:bin/:rev?/source', binHandler.getBinSource); - app.get('/:bin/:rev?.:format(js|json|css|html)', binHandler.getBinSourceFile); + app.get('/:bin/:rev?.:format(js|json|css|html|md|markdown|stylus|less|coffee|jade)', binHandler.getBinSourceFile); app.get('/:bin/:rev?/:format(js)', function (req, res) { // Redirect legacy /js suffix to the new .js extension. res.redirect(301, req.path.replace(/\/js$/, '.js'));