UNPKG

b_

Version:
218 lines (193 loc) 6.56 kB
/* global define: true */ (/* istanbul ignore next */ function (root, factory) { 'use strict'; if (typeof exports === 'object') { // CommonJS module.exports = factory(); } else if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define([], factory); } else { // Browser globals root.b_ = factory(); } }) (this, function () { /** * * @param {object} [options] * @param {string} [options.tailSpace=''] * @param {string} [options.elementSeparator='__'] * @param {string} [options.modSeparator='_'] * @param {string} [options.modValueSeparator='_'] * @param {string} [options.classSeparator=' '] * @param {string} [options.isFullModifier=true] * @param {string} [options.isFullBoolValue=false] * * @constructor */ function BemFormatter(options) { // Case call BemFormatter() without new if (!(this instanceof BemFormatter)) { return createBemFormatter(options); } options = options || {}; this.tailSpace = options.tailSpace || ''; this.elementSeparator = options.elementSeparator || '__'; this.modSeparator = options.modSeparator || '_'; this.modValueSeparator = options.modValueSeparator || '_'; this.classSeparator = options.classSeparator || ' '; this.isFullModifier = typeof options.isFullModifier === 'undefined' ? true : options.isFullModifier; this.isFullBoolValue = typeof options.isFullBoolValue === 'undefined' ? false : options.isFullBoolValue; } BemFormatter.prototype = { /** * * @param {string} base * @param {string} modifierKey * @param {*} modifierValue * @returns {string} * @private */ _stringifyModifier: function (base, modifierKey, modifierValue) { var result = ''; // Ignore undefined values if (typeof modifierValue === 'undefined') { return result; } // If not using full bools ignore false values if (!this.isFullBoolValue && modifierValue === false) { return result; } // Makes block__elem_{modifierKey} result += this.classSeparator + base + this.modSeparator + modifierKey; // If not using full bools skip true `modifierValue` if (this.isFullBoolValue || modifierValue !== true) { // Makes block__elem_{modifierKey}_{modifierValue} result += this.modValueSeparator + String(modifierValue); } return result; }, /** * * @param {string} base * @param {object} modifiers * @returns {string} * @private */ _stringifyModifiers: function (base, modifiers) { var result = ''; if (!this.isFullModifier) { base = ''; } for (var modifierKey in modifiers) { if (!modifiers.hasOwnProperty(modifierKey)) { continue; } result += this._stringifyModifier(base, modifierKey, modifiers[modifierKey]); } return result; }, /** * * @param {string} block * @param {string} [element] * @param {object} [modifiers] */ stringify: function (block, element, modifiers) { var className = String(block); // case b_(block, modifiers) if (element && typeof element === 'object' && typeof modifiers === 'undefined') { modifiers = element; element = null; } if (element) { className += this.elementSeparator + String(element); } if (modifiers) { className += this._stringifyModifiers(className, modifiers); } return className + this.tailSpace; } }; /** * Return partially applied b_ * * @param {string} block * @param {string} [element] * @param {object} [modifiers] * @returns {Function} partially applied b_ * * @example * * ```jsx * var B = require('b_'); * var b = B.with('b-button'); * var e = B.with('b-button', 'elem'); * * function render() { * return ( * <div className={b()}> * <span className={b('icon', {type: 'add'})}></span> * <span className={b('text')}></span> * </div> * <div className={b({size: 'small'})}> * <span className={b('icon', {type: 'add'})}></span> * <span className={b('text')}></span> * </div> * ); * } * ``` */ function withMixin(block, element, modifiers) { return this.bind.apply(this, [null].concat(Array.prototype.slice.call(arguments))); } /** * @param {object} [options] * @returns {function} * * @private */ function createBemFormatter(options) { var bemFormatter = new BemFormatter(options); var b = bemFormatter.stringify.bind(bemFormatter); b['with'] = b.lock = withMixin; return b; } /** * * @type {function(this:BemFormatter)} * * @example * * var v = require('b_'); * * b('block'); // 'block' * b('block', {mod1: true, mod2: false, mod3: 'mod3'}); // 'block block_mod1 block_mod3_mod3' * b('block', 'elem'); // 'block__elem' * b('block', 'elem', {mod1: true, mod2: false, mod3: 'mod3'}); // 'block__elem block__elem_mod1 block__elem_mod3_mod3' */ var b = createBemFormatter(); /** * * @type {BemFormatter} * * @example * * var b = new (require('b_').B)({ * tailSpace: ' ', * elementSeparator: '-', * modSeparator: '--', * modValueSeparator: '-', * classSeparator: ' ' * }); * * b.stringify('block'); // 'block ' * b.stringify('block', {mod1: true, mod2: false, mod3: 'mod3'}); // 'block block--mod1 block--mod3-mod3 ' * b.stringify('block', 'elem'); // 'block-elem ' * b.stringify('block', 'elem', {mod1: true, mod2: false, mod3: 'mod3'}); // 'block-elem block-elem--mod1 block-elem--mod3-mod3' */ b.B = BemFormatter; return b; });