npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

express-bem

v1.1.0

Published

bem bundles renderer for express

Downloads

9

Readme

express-bem

Build Status Coverage Status Dependency Status

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

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 to false will reload any template files each time
  • exec if set to false 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