bempug v1.1.1
BemPug
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.
Anchors
Install | Mixins | Examples | Helpers | Changelog
Install
Install from npm:
npm i bempug -D
Then include index
file to your pug or jade project:
include ../../node_modules/bempug/index
Mixins
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
- data.m
- 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
- data.m
- tag
String
If data argument is String it will be a modifier.
Examples
Block | Element | Modifier | Tag | Mix | Separators
Block
Simple example:
+b( 'block' )
+e( 'element' ) Text
<div class="block">
<div class="block__element">Text</div>
</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>
</div>
</div>
Element
Element depends on parent block:
+b( 'content' )
+e( 'layout' ) Content
<div class="content">
<div class="content__layout">Content</div>
</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>
</div>
Modifier
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>
</div>
Block and element have more than one modifier:
+b( 'alert', 'success.active' )
+e( 'text', 'bolder.italic' ) Success
<div class="alert alert--success alert--active">
<div class="alert__text alert__text--bolder alert__text--italic">Success</div>
</div>
Also, you can set modifiers in Object
:
+b( 'alert', {m: 'success.active'} ) Success
<div class="alert alert--success alert--active">Success</div>
Tag
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>
</article>
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='https://www.npmjs.com/package/bempug')
+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>
</ul>
<a class="link" href="https://www.npmjs.com/package/bempug">
<span class="text">My text</span>
</a>
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>
</ul>
<form class="form">
<fieldset class="form__fields">Fields</fieldset>
</form>
Mix
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>
</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>
</div>
Element is mixed with block:
+b( 'footer' )
+e( 'bottom', {b: 'grid'} )
<div class="footer">
<div class="footer__bottom grid"></div>
</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>
Separators
You can change global separators:
- BEMPUG.modifier = '_';
- BEMPUG.element = '__';
+b( 'alert', 'success.active' )
+e( 'text', 'bolder.italic' ) Success
<div class="alert alert_success alert_active">
<div class="alert__text alert__text_bolder alert__text_italic">Success</div>
</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>
</div>
Helpers
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 }
Callbacks
You can set beforeParse
callback:
- BEMPUG.beforeParse[ 'input' ] = function( block ) {
if ( typeof block.data.m === 'undefined' ) block.data.m = '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 = 'http://schema.org/WebPage';
}
+b( 'page' ) My page
<body class="page page--test" itemscope itemtype="http://schema.org/WebPage">My page</body>
Changelog
1.1.1
- Fixed: disable parent mode not work in cb
- Fixed: name of element in mix with another element
1.1.0
- Add: ampersand sign for mix
- Add: mix element with blocks and another elements
1.0.2
- 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
1.0.1
- Add: disable parent mode for blocks
1.0.0
- Release version
Thanks
Many thanks to Roman Komarov for the original idea.