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 -DThen include index file to your pug or jade project:
include ../../node_modules/bempug/indexMixins
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.