node package manager
Orgs are free. Discover, share, and reuse code in your team. Create a free org »


BEMHTML to BH conversion tool


Given the impedence mismatch between Bemhtml and Bh it does not seem possible to convert every template or guarantee that the applicative semantics of the source is preserved in the result. Bemhtml is much too expressive and lenient to deliver on such promise. The ability to apply templates in a modified context powered by xjst methods apply, applyNext, applyCtx employing the result is one feature prominantly missing in Bh. Its applyBase method carries a very particular meaning that doesn't map clearly on Bemhtml machinery and as of this writing appears to be broken anyway.

bemhtml-source-convert helps you port existing Bemhtml templates to Bh. Given the above disclaimer it is best viewed as an assistant that guides your conversion effort. Until there's a more direct mapping between Bemhtml and Bh we hope that in the best case it will produce a drop in replacement for your Bemhtml template, give you enough meat to avoid writing Bh from scratch on your average template, and offer meaningful feedback when conversion fails. Be sure to eyeball and test even the happy case when conversion succeeds.

Conversion is performed in a strict mode by default, that is the compiler will accumulate any bh-incompatible features and progress till the entire template's been read and converted or exception occured. In a strict mode it will always signal an error and report incompatibilities encountered. These often point at the code that's questionable or unnecessarily convoluted even in Bemhtml world and is ripe for refactoring. Passing -S flag to the binary or an optional second argument { strict: false } to Stx constructor will turn the strict mode off. Many more templates can be converted this way at the expense of valuable validation the compiler performs and reliability of the result. We do NOT recommend it.


$ npm install bemhtml-source-convert



$ bemhtml2bh -h
  bemhtml2bh [OPTIONS] [ARGS]
  -h, --help : Help
  -v, --verbose : Verbose mode
  -i INPUT, --input=INPUT : File to convert (default: stdin)
  -j BEMJSON, --json=BEMJSON : Apply templates to this bemjson file
  -s SETOPTIONS, --setOptions=SETOPTIONS : Set bh-template options (default: { "jsAttrName""onclick" , "jsAttrScheme""js" })
  -o OUTPUT, --output=OUTPUT : Output to file (default: stdout)
  -S, --strictOff : Ignore bh-incompatibility warnings, perform best-effort conversion


Convert this meaningless -i test/scratch.bemhtml

block node {
    mod 'size' 'big', tag: 'big'
    js: {param: 'p2'}
    attrs:  {node: 'yes'}

feeding it -j test/scratch.json

    "block" : "node",
    "attrs": {"a": "set"}

Hopefully this should produce a Bh template and HTML. You'll get a color-coded diff if generated Bh and original Bemhtml produce different HTML when applied to the same bemjson.

~/Documents/bemhtml-source-convert [master] $ bemhtml2bh -i test/scratch.bemhtml -j test/scratch.json
module.exports = function (bh) {
    bh.match('node_size_big'function (ctx, json) {
    bh.match('node'function (ctx, json) {
        ctx.js(json.js !== false ? ctx.extend(json.js, { 'param''p2' }) : false);
        ctx.attrs(ctx.extend('node''yes' }, ctx.attrs()));
Html produced
expected actual
<div a="set" class="i-bem node" data-bem="{&node="yes" onclick="return {&quot;node&quot;:{&quot;param&quot;:&quot;p2&quot;}}" node="yes"></;}}"></div>


Stx {constructor}

var stx = new Stx(stringOfBemhtml [, { strict: false }])
stx.bemhtml {Object}

Has properties:

  • src {String} also available as stx.src
  • match(json) apply template to bemjson. Also available as stx.match(json)
  • pp(options) pretty-print the template, accepts optional options argument (see stx.pp method) {Object}

Bh-template is generated when you first dereference this object. Has properties:

  • src {String}
  • match(json, options) apply the template to bemjson. Control global BH defaults by passing optional 2nd argument {json} e.g. {"jsAttrName": "data-bem" , "jsAttrScheme": "json"}
  • pp(options) pretty-print the template, accepts optional options argument (see stx.pp method)
stx.htmlDiff(json, options)

Apply each Bemhtml and generated Bh template to json. Optional 2nd argument is the same you'd pass to bh.match. Returns an {Object} with properties:

  • isEqual {Boolean} - true if both templates produce equivalent HTML
  • html {String} - html if isEqual, color-coded diff otherwise (ansi colors)
stx.pp(anyJavaScriptObject, { prompt: "", stringify: false })

Generic pretty-printer. Accepts optional 2nd argument {Object} with properties:

  • prompt {String} - prompt string e.g. name of the object, will be printed under the header
  • stringify {Boolean} - add indentation to the object's string representation but don't wrap it in header and footer


var Stx = require('bemhtml-source-convert').Stx,
    fs = require('fs'),
    stx = new Stx(fs.readFileSync('scratch.bemhtml', 'utf8')),
    bemjson = JSON.parse(fs.readFileSync('scratch.json', 'utf8'));
// pretty-print bemjson 
stx.pp(bemjson, { prompt: 'bemjson' });
// pretty-print bemhtml 
stx.bemhtml.pp({ prompt: 'bemhtml' });
// convert bemhtml into bh and pretty-print the result 
try {{ prompt: 'bh generated' });
} catch(e) {
// try applying both templates to bemjson showing colored diff if they 
// produce different HTML or HTML otherwise 
var diff = stx.htmlDiff(bemjson);
    diff.isEqual ? 'Html\n' : 'Html diff\n',
// write generated bh out