Skip to content

Instantly share code, notes, and snippets.

@aseemk
Forked from laurie71/blocks.js
Created April 19, 2011 11:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aseemk/927172 to your computer and use it in GitHub Desktop.
Save aseemk/927172 to your computer and use it in GitHub Desktop.
Test app for Express blocks middleware
var express = require('express');
var app = express.createServer();
app.configure(function () {
app.use(require('./blocks')(app));
app.use(app.router);
});
app.set('views', __dirname);
app.set('view engine', 'html');
app.register('.html', require('ejs'));
app.get('/', function (req, res) {
res.render('test', { foo: 'bar' });
});
app.listen(8080);
console.log('listening on port 8080...');
var debug = require('util').debug;
// helper prototype for rendering block scripts, stylesheet links, etc
var blocktag = {
toString: function() {
var tag = this.tag,
html = '<'+tag,
that = this;
Object.getOwnPropertyNames(this).forEach(function(prop) {
if (prop !== 'tag') {
html += ' '+prop+'="'+that[prop]+'"';
}
});
if (tag === 'script') {
html += '></script>';
} else {
html += ' />';
}
return html;
}
}
module.exports = function(app) {
return function(req, res, next) {
// request-local hash of named blocks
var blocks = {};
// dynamic helper for defining/rendering blocks
function block(name) {
var block, html;
if (arguments.length === 0) return next(new Error('unnamed block'));
block = blocks[name];
if (arguments.length === 1) {
// render block contents
html = '';
if (block) {
block.forEach(function(item) {
html = String(item) + html;
});
}
debug('block: '+name+': '+JSON.stringify(block));
debug('html: '+html);
return html;
} else {
// define/append block contents
if (! block) block = blocks[name] = [];
block.push(Array.prototype.slice.call(arguments, 1));
debug('block: '+name+': '+JSON.stringify(block));
return '';
}
};
// utility method for adding a script to a block
block.script = function(src) {
return Object.create(blocktag, {
src : { enumerable: true, value: src },
tag : { enumerable: true, value: 'script' },
type: { enumerable: true, value: 'text/javascript' }
});
};
// utility method for adding a stylesheet to a block
block.stylesheet = function(href, media) {
var tag = Object.create(blocktag, {
href: { enumerable: true, value: href },
tag : { enumerable: true, value: 'link' },
type: { enumerable: true, value: 'text/css' },
rel : { enumerable: true, value: 'stylesheet' }
});
if (media) {
tag.media = media;
}
return tag;
};
debug('add helpers');
// res.local('block', block);
// req.app.dynamicHelpers(block);
// req.app.helpers(block);
app.helpers({block:block});
next();
};
};
<!-- use blocks.js to inject content into *parent* layout -->
<!-- use new layout() helper to select parent layout -->
<% layout('layout_site') %>
<% block('head', block.stylesheet('layout.css')) %>
<% block('foot', block.script('layout.js')) %>
<h1>Main Layout</h1>
<p>
This is the main page layout.
It is wrapped by the <t>layout_site</t> layout.
It adds the following blocks to the layout:
</p>
<ul><li>A layout.css stylesheet in the document head</li>
<li>A layout.js script at the document foot</li>
</ul>
<%- body %>
<!doctype html>
<head>
<meta charset=utf-8>
<title>Nested Layouts with Blocks Demo</title>
<!-- pull in the 'head' block content defined by our child layouts/pages -->
<%- block('head') %>
</head>
<body>
<h1>Site Layout</h1>
<p>
This is the master site layout.
It is not wrapped by a layout.
It includes the following dynamic blocks:
</p>
<ul><li><t>head</t>: a block whose content is rendered in the HTML 'head' section</li>
<li><t>foot</t>: a block whose content is rendered just before the closing 'body' tag</li>
</ul>
<%- body %>
<!-- pull in the 'foot' block content defined by our child layouts/pages -->
<%- block('foot') %>
</body>
</html>
<!-- use blocks.js to inject content into layout -->
<!-- use new layout() helper to get nested layouts -->
<% layout('layout_main') %>
<% block('head', block.stylesheet('page.css')) %>
<% block('foot', block.script('page.js')) %>
<h2>Index Page</h2>
<p>
This is the main page content.
It is wrapped by the <t>layout_main</t> layout.
It adds the following blocks to the layout:
</p>
<ul><li>A page.css stylesheet in the document head</li>
<li>A page.js script at the document foot</li>
</ul>
@aseemk
Copy link
Author

aseemk commented Apr 20, 2011

@laurie71 found the bug: require('blocks') returns a function which needs to be called with app and which returns the actual middleware. Fixed, and now it works. Thanks Laurie!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment