-
-
Save aseemk/927172 to your computer and use it in GitHub Desktop.
Test app for Express blocks middleware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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...'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- 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 %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- 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> |
As the code is right now, navigating to / hangs. I haven't been able to figure out where the hang is coming from; none of the debug messages get printed.
If I swap the order of the two middlewares, app.router
and blocks
, requests no longer hang, but it seems to be the wrong order, because I get this error message:
ReferenceError: block is not defined
at Object.anonymous (eval at <anonymous> (/usr/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
at Object.<anonymous> (/usr/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
at ServerResponse._render (/usr/lib/node/.npm/express/2.2.2/package/lib/view.js:377:21)
at ServerResponse.render (/usr/lib/node/.npm/express/2.2.2/package/lib/view.js:242:17)
at Object.<anonymous> (/Users/aseemk/Projects/Node/block-test/app.js:14:9)
at param (/usr/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:148:21)
at pass (/usr/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:164:10)
at Object.router [as handle] (/usr/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:170:6)
at next (/usr/lib/node/.npm/connect/1.3.0/package/lib/http.js:204:15)
at Object.handle (/usr/lib/node/.npm/express/2.2.2/package/lib/http.js:75:5)
@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
The three .html files should be in a views directory. Gist doesn't show full pathnames for files.