Tool for working with BEM entity representations: allows you to parse string representation and stringify object representation.
$ npm install --save @bem/naming
Parse
const bemNaming = require('@bem/naming');
bemNaming.parse('button__text'); // BemEntityName { block: 'button', elem: 'text' }
Stringify
const bemNaming = require('@bem/naming');
const BemEntityName = require('@bem/entity-name');
const entityName = new BemEntityName({ block: 'button', mod: 'checked' });
bemNaming.stringify(entityName); // String 'button_checked'
- Object representation
- String representation
- Common misconceptions
- Harry Roberts' naming convention
- React naming convention
- Custom naming convention
- API
The BemEntityName class describes the representation of a BEM entity name.
To define BEM entities, we often use a special string format that allows us to define exactly which entity is represented.
According to the original BEM naming convention, it looks like this:
'block[_block-mod-name[_block-mod-val]][__elem-name[_elem-mod-name[_elem-mod-val]]]'
(Parameters within square brackets are optional)
Examples:
- Block —
block-name
. - Block modifier —
block-name_mod-name_mod-val
. - Simple modifier of block —
block-name_mod
. - Block element —
block-name__elem-name
. - Element modifier —
block-name__elem-name_mod-name_mod-val
. - Simple modifier of element —
block-name__elem_mod
.
The original naming uses the following delimiters:
__
— to separate an element from a block_
— to separate a modifier name from a block or element and to separate a modifier value from a modifier name
The BEM methodology uses a flat structure inside blocks. This means that a BEM entity can't be represented as an element of another element, and the following string representation will be invalid:
'block__some-elem__sub-elem'
For more information, see the FAQ:
Why doesn't BEM recommend using elements within elements (block__elem1__elem2)?
Also, a BEM entity can't be a block modifier and an element modifier simultaneously, so the following string representation will be invalid:
'block_block-mod-name_block-mod-val__elem-name_elem-mod-name_elem-mod-val'
According to this convention elements are delimited with two underscores (__
), modifiers are delimited by two hyphens (--
), and values of modifiers are delimited by one underscore (_
).
Read more in the Guidelines.
Example:
const twoDashesNaming = require('@bem/naming')('two-dashes');
twoDashesNaming.parse('block__elem'); // { block: 'block', elem: 'elem' }
twoDashesNaming.parse('block--mod_val'); // { block: 'block',
// mod: { name: 'mod', val: 'val' } }
twoDashesNaming.stringify({
block: 'block',
elem: 'elem',
mod: 'mod'
});
// ➜ block__elem--mod
According to this convention elements are delimited with one hyphen (-
), modifiers are delimited by one underscore (_
), and values of modifiers are delimited by one underscore (_
).
You can explore this convention at bem-react-components.
Example:
const reactNaming = require('@bem/naming')('react');
reactNaming.parse('block-elem'); // BemEntityName { block: 'block', elem: 'elem' }
reactNaming.parse('block_mod_val'); // BemEntityName { block: 'block',
// mod: { name: 'mod', val: 'val' } }
reactNaming.stringify({
block: 'block',
elem: 'elem',
mod: 'mod'
});
// ➜ block-elem_mod
Use the bemNaming function to create an instance where you can manage your own naming convention.
Example:
const bemNaming = require('@bem/naming');
const myNaming = bemNaming({
delims: {
elem: '-',
mod: { name: '--', val: '_' }
},
wordPattern: '[a-zA-Z0-9]+' // because element and modifier's separators include
}); // hyphen in it, we need to exclude it from block,
// element and modifier's name
myNaming.parse('block--mod_val'); // BemEntityName
// { block: 'block',
// mod: { name: 'mod', val: 'val' } }
const BemEntityName = require('@bem/entity-name');
myNaming.stringify(new BemEntityName({
block: 'blockName',
elem: 'elemName',
mod: 'simpleElemMod'
}); // 'blockName-elemName--simpleElemMod'
- bemNaming({ delims: {elem, mod}, wordPattern })
- parse(str)
- stringify(obj)
- elemDelim
- modDelim
- modValDelim
Parameter | Type | Description | Default |
---|---|---|---|
delims |
object |
Defines delimeters for elem and/or mods | |
delims.elem |
string |
Separates element's name from block. | __ |
delims.mod |
string , { name: string, val: string } |
Separates modifier from block or element. | _ |
delims.mod.name |
string |
Separates a modifier name from a block or an element. | _ |
delims.mod.val |
string |
Separates the value of a modifier from the modifier name. | Default as the value of the mod.name . |
wordPattern |
string |
Defines which characters can be used in names of blocks, elements, and modifiers. | [a-z0-9]+(?:-[a-z0-9]+)* |
Parameter | Type | Description |
---|---|---|
str |
string |
BEM entity name representation. |
Parses the string into an instance of BemEntityName
.
Example:
const bemNaming = require('@bem/naming');
bemNaming.parse('block__elem_mod_val');
// ➜ BemEntityName {
// block: 'block',
// elem: 'elem',
// mod: { name: 'mod', val: 'val' }
// }
Parameter | Type | Description |
---|---|---|
entityName |
BemEntityName , object |
BEM entity name representation. |
Forms a string from the instance of BemEntityName
.
Example:
const bemNaming = require('@bem/naming');
const BemEntityName = require('@bem/entity-name');
bemNaming.stringify(new BemEntityName({
block: 'block',
elem: 'elem',
mod: { name: 'mod', val: 'val' }
});
// ➜ block__elem_mod_val
String to separate an element from a block.
String to separate a modifier name from a block or element.
String to separate a modifier value from the name of the modifier.
Code and documentation copyright 2014 YANDEX LLC. Code released under the Mozilla Public License 2.0.