BEMHTML to BH Converter
Convert BEMHTML templates to BH format online. Supports strict mode validation, incompatibility detection, and generates ready-to-use bh.match() code.
About
BEMHTML and BH represent two distinct template engines in the BEM ecosystem. BEMHTML operates on xjst (eXtensible JavaScript Templates) with declarative pattern matching and context modification via apply, applyNext, and applyCtx. BH uses an imperative approach where ctx methods mutate the output directly. The impedance mismatch between these systems means not every BEMHTML construct has a BH equivalent. Incorrect manual conversion leads to silent rendering bugs that surface only in production. This tool parses BEMHTML source into an intermediate representation, maps predicate chains to bh.match selectors, and translates body modes (tag, attrs, js, content, mix, cls, bem) to their BH ctx method equivalents.
Strict mode is enabled by default. The converter accumulates every BH-incompatible feature it encounters and reports them as errors. Constructs like apply with modified context, applyCtx, and custom XJST modes have no direct BH mapping. Disabling strict mode allows best-effort conversion but sacrifices validation reliability. This tool approximates the behavior of the bemhtml-source-convert npm package. It handles common patterns: block/elem/mod predicates, standard modes, object spread in attrs, and JS params merging. Complex nested applyNext chains or runtime-computed predicates require manual review.
Formulas
BEMHTML template conversion follows a deterministic mapping from declarative predicates to imperative BH matchers. The core transformation rule maps a BEMHTML predicate chain to a BH selector string:
Where p is the predicate object extracted from BEMHTML source. block is the block name identifier. elem is an optional element name. mod / modVal represent modifier key-value pairs. Multiple modifiers on the same block generate separate bh.match calls.
Body mode transformation applies the mapping:
For attrs with merge semantics, the pattern becomes:
For js with conditional merge:
Strict mode validation checks each body statement against a compatibility set C = {tag, attrs, js, content, mix, cls, bem}. Any mode m ∉ C triggers an incompatibility warning. Any call to apply, applyCtx, or local triggers a strict mode error regardless of context.
Reference Data
| BEMHTML Mode | BH Method | Signature | Notes |
|---|---|---|---|
| tag | ctx.tag(value) | value: String | Direct mapping. Empty string produces no wrapper tag. |
| attrs | ctx.attr(key, val) or ctx.attrs(obj) | obj: Object | BH merges with ctx.extend. BEMHTML replaces entirely. |
| js | ctx.js(value) | value: Object | TRUE | Check json.js ≠ FALSE for merge pattern. |
| content | ctx.content(value) | value: BemJson | Direct mapping. Accepts arrays and objects. |
| mix | ctx.mix(value) | value: Array | Object | Direct mapping. |
| cls | ctx.cls(value) | value: String | Additional CSS classes. |
| bem | ctx.bem(value) | value: Boolean | FALSE disables BEM class generation. |
| def | No direct equivalent | - | Requires manual rewrite. applyBase is closest but semantically different. |
| apply | Not supported | - | Context modification has no BH equivalent. Strict mode error. |
| applyNext | ctx.applyBase() | - | Partial mapping only. BH applyBase re-applies same matcher, not next in chain. |
| applyCtx | Not supported | - | Replaces current node context. No BH mapping. Strict mode error. |
| local | Not supported | - | Temporary context modification. No BH mapping. |
| jsAttrName | bh.setOptions | jsAttrName: String | Default: "onclick". Alternative: "data-bem". |
| jsAttrScheme | bh.setOptions | jsAttrScheme: String | Default: "js". Alternative: "json". |
| Predicate: block | bh.match("blockName") | - | Direct mapping. |
| Predicate: block elem | bh.match("block__elem") | - | BEM notation with double underscore. |
| Predicate: mod key val | bh.match("block_key_val") | - | Single underscore separators. |
| Predicate: elemMod | bh.match("block__elem_key_val") | - | Combined elem + mod selector. |
| Boolean mod | bh.match("block_key") | - | No value means boolean modifier. |