Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including bempug with all npm packages installed. Try it out:

var bempug = require("bempug")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

bempug v1.1.1

Simple mixins to help you writing code on BEM methodology in pug or jade projects.


GitHub license npm npm

Simple mixins to help you writing code on BEM methodology in pug or jade projects.

You like BEM? Try BemGo — starter kit for developing BEM apps using Gulp and Webpack.


Install | Mixins | Examples | Helpers | Changelog


Install from npm:

npm i bempug -D

Then include index file to your pug or jade project:

include ../../node_modules/bempug/index


Block mixin:

+b( name, data, tag )
  • name String
  • data String or Object
    • data.m String — block modifier
    • data.p Boolean — disable parent mode
    • data.e Array or String — mix block with element
    • data.b Array or String — mix block with another block
    • data.t String — block tag
    • data.s String — block separators
  • tag String

If data argument is String it will be a modifier.

Element mixin:

+e( name, data, tag )
  • name String
  • data String or Object
    • data.m String — element modifier
    • data.p String — parent block
    • data.e Array or String — mix element with another element
    • data.b Array or String — mix element with block
    • data.t String — element tag
    • data.s String — element separators
  • tag String

If data argument is String it will be a modifier.


Block | Element | Modifier | Tag | Mix | Separators


Simple example:

+b( 'block' )
    +e( 'element' ) Text
<div class="block">
    <div class="block__element">Text</div>

You can to disable parent mode and element will ignore this block:

+b( 'header' )
    +b( 'grid', {p: false} ) // or short {p:0}
        +e( 'logo' ) Logo
<div class="header">
    <div class="grid">
        <div class="header__logo">Logo</div>


Element depends on parent block:

+b( 'content' )
    +e( 'layout' ) Content
<div class="content">
    <div class="content__layout">Content</div>

You can set parent block for element directly:

+b( 'content' )
    +e( 'layout', {p: 'page'} ) Content
<div class="content">
    <div class="page__layout">Content</div>


Block and element have modifier:

+b( 'alert', 'success' )
    +e( 'text', 'bolder' ) Success
<div class="alert alert--success">
    <div class="alert__text alert__text--bolder">Success</div>

Block and element have more than one modifier:

+b( 'alert', '' )
    +e( 'text', 'bolder.italic' ) Success
<div class="alert alert--success alert--active">
    <div class="alert__text alert__text--bolder alert__text--italic">Success</div>

Also, you can set modifiers in Object:

+b( 'alert', {m: ''} ) Success
<div class="alert alert--success alert--active">Success</div>


Default tag is div, but you can set it directly:

+b( 'news', {}, 'article' )
    +e( 'title', {}, 'h1' ) Title

// Or in data Object

+b( 'news', {t: 'article'} )
    +e( 'title', {t: 'h1'} ) Title
<article class="news">
    <h1 class="news__title">Title</h1>

Sometimes mixin can be smart and tag depends on parent or attributes:

+b( 'list', {t: 'ul'} )
    +e( 'item' ) My item 1
    +e( 'item' ) My item 2
    +e( 'item' ) My item 3

+b( 'link' )(href='')
    +b( 'text' ) My text
<ul class="list">
    <li class="list__item">My item 1</li>
    <li class="list__item">My item 2</li>
    <li class="list__item">My item 3</li>

<a class="link" href="">
    <span class="text">My text</span>

Also, you can use tagByName global option for set default tag by name:

- BEMPUG.tagByName = {list: 'ul', form: 'form', fields: 'fieldset'};

+b( 'list' )
    +e( 'item' ) Item
    +e( 'item' ) Item
+b( 'form' )
    +e( 'fields' ) Fields
<ul class="list">
    <li class="list__item">Item</li>
    <li class="list__item">Item</li>

<form class="form">
    <fieldset class="form__fields">Fields</fieldset>


Block is mixed with element:

+b( 'title', {e: 'article'} ) Title
<div class="title article__title">Title</div>

You can set name of element in mix with colon:

+b( 'title', {e: 'article:my-name'} ) Title
<div class="title article__my-name">Title</div>

Block is mixed with two elements:

+b( 'title', {e: ['article', 'content']} ) Title
<div class="title article__title content__title">Title</div>

Also, you can use ampersand & sign as parent block reference:

+b( 'news' )
    +b( 'title', {e: '&'} ) Title
    +b( 'text', {e: '&:description'} ) Text
<div class="news">
    <div class="title news__title">Title</div>
    <div class="text news__description">Text</div>

Block is mixed with element which has modifiers:

+b( 'title', {e: 'news|bolder.size-m'} ) Title
<div class="title news__title news__title--bolder news__title--size-m">Title</div>

Element is mixed with another element:

+b( 'footer' )
    +e( 'bottom', {e: 'page'} )
<div class="footer">
    <div class="footer__bottom page__bottom"></div>

Element is mixed with block:

+b( 'footer' )
    +e( 'bottom', {b: 'grid'} )
<div class="footer">
    <div class="footer__bottom grid"></div>

Block is mixed with another block:

+b( 'article', {b: 'news'} ) Content
<div class="article news">Content</div>

Block is mixed with another block which has modifiers:

+b( 'article', {b: 'news|first'} ) Content
<div class="article news news--first">Content</div>

Block is mixed with two blocks which have modifiers:

+b( 'article', {b: ['news|first','fixed|active']} ) Content
<div class="article news news--first fixed fixed--active">Content</div>


You can change global separators:

- BEMPUG.modifier = '_';
- BEMPUG.element = '__';

+b( 'alert', '' )
    +e( 'text', 'bolder.italic' ) Success
<div class="alert alert_success alert_active">
    <div class="alert__text alert__text_bolder alert__text_italic">Success</div>

Also, you can set separators for each block and ignore global settings 'modifier|element':

+b( 'news', {e: 'content', m: 'first', s: '---|___' } )
    +b( 'text', {e: true, m: 'bolder'} ) Text
<div class="news news---first content___news">
    <div class="text text---bolder news___text">Text</div>


Get current block | Get current parent | Callbacks

Get current block

You can get current block name:

+b( 'nav' )
    +e( 'item' )
        - console.log( BEMPUG.getCurrentBlock() ); // 'nav'
        +b( 'img' )
            - console.log( BEMPUG.getCurrentBlock() ); // 'img'

Get current parent

You can get current parent Object:

+b( 'html', 'no-js', 'html' )(lang='en')
    - console.log( BEMPUG.getCurrentParent() );
{ type: 'block',
  name: 'html',
  tag: 'html',
  attributes: { lang: 'en' },
  sep: { modifier: '--', element: '__' },
  classes: [ 'html', 'html--no-js' ],
  parent: {},
  selfClosing: false }


You can set beforeParse callback:

- BEMPUG.beforeParse[ 'input' ] = function( block ) {

    if ( typeof === 'undefined' ) = 'default';

+b( 'input', {m: 'search'} ) // Have modifier 'search'

+b( 'input' ) // No modifier, but we set modifier 'default' by callback
<input class="input input--search">
<input class="input input--default">

You can set afterParse callback:

- BEMPUG.afterParse[ 'page' ] = function( block ) {

    block.setTag( 'body' );
    block.addModifier( 'test' );
    block.attributes.itemscope = true;
    block.attributes.itemtype = '';

+b( 'page' ) My page
<body class="page page--test" itemscope itemtype="">My page</body>



  • Fixed: disable parent mode not work in cb
  • Fixed: name of element in mix with another element


  • Add: ampersand sign for mix
  • Add: mix element with blocks and another elements


  • Add: some global helpers
  • Add: before / after parse callback
  • Fixed: block and element separators work for any descendant
  • Fixed: default tag depends on parent tag for any descendant


  • Add: disable parent mode for blocks


  • Release version


Many thanks to Roman Komarov for the original idea.

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free