Skip to content

Instantly share code, notes, and snippets.

@sammoore
Created December 23, 2016 21:51
Show Gist options
  • Save sammoore/c85a4cfa823b1de98596924d938e298f to your computer and use it in GitHub Desktop.
Save sammoore/c85a4cfa823b1de98596924d938e298f to your computer and use it in GitHub Desktop.
Middleware for express/similar that adds a primitive 'res.yield' function based on 'res.render' but supports layouts by design. Note: clean-up pending.
// Given 'layout.ejs' in your view folder, use `res.yield` like you would `res.render`.
// Override what layout to use by supplying a second string parameter right after the view.
// Layouts are passed `yield` as a local; in ejs, example usage: `<%- yield %>`.
//
// TODO: clean-up argument coercion
// TODO: better/cleaner documentation for usage of `yield`.
// TODO: extract functionality into a middleware-generating module to supply e.g. a default layout.
// TODO: (possibly) turn the layout's `yield` into a function to support nested yields.
app.use(function (req, res, next) {
// default layout?
var defaultLayout = 'layout.ejs';
res.yield = function (view, layout, locals, fn) {
console.log('attempting to yield');
// handle 1 argument (just the view)
if (typeof layout == 'undefined') {
layout = defaultLayout;
locals = {};
}
// support: layout and locals are optional.
// handle 2 arguments
if (typeof locals == 'undefined' && typeof layout == 'function') {
fn = layout;
locals = {};
layout = defaultLayout;
} else if (typeof locals == 'undefined' && typeof layout != 'string') {
locals = layout;
layout = defaultLayout;
} else if (typeof locals == 'undefined') {
locals = {};
}
// handle 3 argument
if (typeof fn == 'undefined' && typeof locals == 'function' && typeof layout != 'string') {
fn = locals;
locals = layout;
layout = defaultLayout;
} else if (typeof fn == 'undefined' && typeof locals == 'function') {
fn = locals;
locals = {};
}
// default callback if none provided
var fn = typeof fn == 'function' ? fn : function(err, html) {
if (err) {
return this.next(err);
}
return this.send(html);
};
this.app.render(view, locals, (function(err, html) {
if (err) return fn(err);
locals.yield = html;
this.app.render(layout, locals, fn.bind(this));
}).bind(this));
};
next();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment