express-bem
v1.1.0
Published
bem bundles renderer for express
Downloads
15
Readme
express-bem
BEM bundles render adapter for express :palm_tree:
Why
Because laziness and short memory. And because simple solutions rocks.
And now it's just a npm i express-bem
and 3 lines of code to use bem blocks library in any app.
Plugins
- express-bem-bemtree
- express-bem-bemhtml
- express-bem-bh
- express-bem-tools-make bem-tools make middleware
- express-bem-enb-make enb make middleware
Dependencies
Peer
express v3.0+
TL;DR
Quick start guide. Run it in your shell:
git clone https://github.com/express-bem/project-stub.git ./express-bem-project-stub
cd express-bem-project-stub
npm install
PORT=3030 node app.js
And after start:
open http://localhost:3030/
Look closer at stub: https://github.com/express-bem/project-stub
Installation
$ npm i express-bem --save
Usage
To load and init module you can use this snippet:
var Express = require('express');
var ExpressBem = require('express-bem');
// create app and bem
var app = Express();
var bem = ExpressBem({
projectRoot: './path-to/bem-project', // bem project root, used for bem make only
path: './custom.bundles' // path to your bundles
});
// here to lookup bundles at your path you need small patch
app.bem = bem.bindTo(app);
// register engines
bem.usePlugin('express-bem-bemtree'); // requires module express-bem-bemtree
bem.usePlugin('express-bem-bemhtml'); // ... express-bem-bemhtml
Allowed options for cache
param object are:
load
if set tofalse
will reload any template files each timeexec
if set tofalse
will exec template files each time
But also can be set to boolean.
Examples:
var bem = ExpressBem({
cache: {
load: true, // don't reload
exec: false // but execute with context
}
});
var cachingbem = ExpressBem({
cache: true // cache all
});
Also you can add your custom engine
bem.engine('.bh.js', function (name, options, cb) {
// some custom .bh.js realisation
cb(null, 'result');
});
Or even more complex (call this before loading plugins or set default engine by self):
bem.engine('fullstack', '.bem', ['.bemhtml.js', '.bemtree.js'], function (name, options, cb) {
var view = this;
// pass options.bemjson directly to bemhtml
if (options.bemjson) return view.thru('bemhtml');
// return bemjson if requested
if (options.raw === true) return view.thru('bemtree');
// full stack
view.thru('bemtree', name, options, function (err, bemjson) {
if (err) return cb(err);
options.bemjson = bemjson;
view.thru('bemhtml', name, options, function (err, data) {
if (err) return cb(err);
cb(null, data);
});
});
});
See also ExpressBem.prototype.bindTo
method.
And then just use res.render
(or app.render
) in your code and pass
some data (or bemjson
tree) there:
app.get('/', function (req, res) {
res.render('your-bundle', {
bemjson: { // view-oriented bemjson tree here
block: 'page',
content: [
'Hello!'
]
}
}
});
Or raw data to execute bemtree
app.get('/', function (req, res) {
res.render('your-bundle', {
title: 'Cool story #1',
storyId: req.query.id,
story: {title: 'Cool', content: '... Lorem Ipsum ...'}
});
});
Directories
If you want to use your bem
repo you can just pull it with git
submodules
or install as npm
package and then just use it as your special bundles path.
.
├── app.js
└── node_modules
└── my-super-mockup
├── desktop.blocks
│ └──...
└── desktop.bundles
├── index
│ ├── index.bemhtml.js
│ └── index.bemtree.js
└── layout
├── layout.bemhtml.js
└── layout.bemtree.js
Otherwise you can import somehow bemhtml.js
and/or bemtree.js
files
to your views
path and use them with default View.prototype.lookup
.
.
├── app.js
└── views
├── index.bemhtml.js
├── index.bemtree.js
├── layout.bemhtml.js
└── layout.bemtree.js
Plugins, engines, middlewares
Engine
Very simple async render engine
/**
* At least one name/ext definition required in params or engine
* @method engine
* @param {String} [name] optional name of engine
* @param {String} [ext] optional extension of engine
* @param {Object|Function} engine can be function or object with render, name, extension properties
*/
// canonical
bem.engine('even-simpler', '.espl.js', function (name, options, cb) {
cb(null, 'rendered result');
});
// name will be espl
bem.engine('.espl.js', function (name, options, cb) {
cb(null, 'rendered result');
});
// ext will be .espl.js
bem.engine('espl', function (name, options, cb) {
cb(null, 'rendered result');
});
// via function
function evenSimpler(name, options, cb) {
cb(null, 'rendered result');
}
evenSimpler.extension = '.espl.js';
bem.engine(evenSimpler);
// via blackbox (function/object)
bem.engine(require('express-bem-even-simpler-engine'));
// via object
bem.engine({
extension: '.blo.js', // name will be 'blo'
targetExtensions: ['.blo.js'],
render: function (name, options, cb) {
cb(null, 'rendered result');
}
});
You should know that you should set by self default engine if you don't use .bindTo
method. Default engine is the first declared engine.
Like that:
// set first available engine as default
app.set('view engine', bem.defaultViewEngine);
// set concrete default engine
app.set('view engine', '.espl.js');
Middleware
Middlewares usually calls betweed express' View.prototype.render
and engine's .render
.
/**
* @method use
* @param {Function} middleware depends on arity it can be generator or middleware itself
* @param {Object} opts options passed to middlewares
*/
// using as simple middleware
bem.use(function (ctx, next) {
// current view
var view = this;
// slow down render
setTimeout(next, 2000);
});
// using as generator
bem.use(function (opts) {
// expressBem context
var bem = this;
/**
* @param {Object} ctx Object with name, options, cb properties that can be modified
* @param {Function} next done callback
*/
return function (ctx, next) {
// dump current extension and passed name to render
console.log(this.ext, ctx.name);
// fixup context
ctx.options.raw = 1;
// all is fine go ahead
next();
};
})
Plugin interface
It should have engines
(engine
if one) and/or middlewares
(middleware
) properties.
To load plugin into express-bem
instance just call usePlugin
method with some parameters:
/**
* @method usePlugin
* @param {String|Object|Function} plugin name, object or generator
* @param {Object} opts options passed to middlewares
*/
// by module require
bem.usePlugin(require('express-bem-module-name'), { /* options */ });
// by object declaration
bem.usePlugin({
middleware: function (opts) { // middleware generator
return function (ctx, next) {
console.log(ctx.options);
next();
};
}
}, { /* options for middleware */ });
// by function generator
bem.usePlugin(function () { // plugin generator
return {
engines: [{
extension: '.q.js',
render: function (name, options, cb) {
cb(null, name);
}
}, {
extension: '.w.js',
render: function (name, options, cb) {
cb(null, this.ext);
}
}]
};
});
License
MIT. See also License