@dr/bem-helper
Advanced tools
Comparing version 1.2.1 to 1.2.2
@@ -38,3 +38,3 @@ const bem = require("../lib/index"); | ||
test("block with modifier with a number value", () => { | ||
test("block with modifier with a value of a number", () => { | ||
expect(bem("block", {modifier: 200})).toBe("block block--modifier-200"); | ||
@@ -100,3 +100,3 @@ }); | ||
test("block with modifier with a number value", () => { | ||
test("block with modifier with a value of a number", () => { | ||
expect(bem.single("block", {modifier: 200})).toBe("block--modifier-200"); | ||
@@ -121,2 +121,63 @@ }); | ||
}); | ||
}); | ||
describe("bem.scoped", () => { | ||
test("block", () => { | ||
expect(bem.scoped("block")).toBe("block"); | ||
}); | ||
test("block and element", () => { | ||
expect(bem.scoped("block", "element")).toBe("block__element"); | ||
}); | ||
test("block with modifier with a value of true", () => { | ||
expect(bem.scoped("block", {modifier: true})).toBe("block block--modifier"); | ||
}); | ||
test("block with modifier with a value of false", () => { | ||
expect(bem.scoped("block", {modifier: false})).toBe("block"); | ||
}); | ||
test("block with modifier with a value of null", () => { | ||
expect(bem.scoped("block", {modifier: null})).toBe("block"); | ||
}); | ||
test("block with modifier with a value of undefined", () => { | ||
var value; | ||
expect(bem.scoped("block", {modifier: value})).toBe("block"); | ||
}); | ||
test("block with modifier with a value of a string", () => { | ||
expect(bem.scoped("block", {modifier: "value"})).toBe("block block--modifier-value"); | ||
}); | ||
test("block with modifier with a value of an empty string", () => { | ||
expect(bem.scoped("block", {modifier: ""})).toBe("block"); | ||
}); | ||
test("block with modifier with a value of a number", () => { | ||
expect(bem.scoped("block", {modifier: 200})).toBe("block block--modifier-200"); | ||
}); | ||
test("block with modifier with a value of 0", () => { | ||
expect(bem.scoped("block", {modifier: 0})).toBe("block block--modifier-0"); | ||
}); | ||
test("block and element with modifier", () => { | ||
expect(bem.scoped("block", "element", {modifier: true})).toBe("block__element block__element--modifier"); | ||
}); | ||
test("block and element with multiple modifiers", () => { | ||
expect(bem.scoped("block", "element", {modifier1: true, modifier2: "value"})).toBe("block__element block__element--modifier1 block__element--modifier2-value"); | ||
}); | ||
test("block with modifier and element", () => { | ||
expect(bem.scoped("block", {modifier: true}, "element")).toBe("block__element block--modifier__element"); | ||
}); | ||
test("block with modifier and element with modifier", () => { | ||
expect(bem.scoped("block", {modifier: true}, "element", {modifier: true})).toBe("block__element block--modifier__element block__element--modifier block--modifier__element--modifier"); | ||
}); | ||
}); |
@@ -7,31 +7,60 @@ "use strict"; | ||
function bem() { | ||
return argParser.apply(undefined, arguments).join(" "); | ||
/* @flow */ | ||
/*:: type Modifiers = { [key: string]: any }; */ | ||
/*:: type Classnames = Array<string>; */ | ||
function bem() /*:any*/ /*:string*/{ | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
return argParser.apply(undefined, [false].concat(args)).join(" "); | ||
} | ||
bem.single = function () { | ||
return argParser.apply(undefined, arguments).pop(); | ||
function scoped() /*:any*/ /*:string*/{ | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
return argParser.apply(undefined, [true].concat(args)).join(" "); | ||
}; | ||
function argParser(block) { | ||
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
args[_key - 1] = arguments[_key]; | ||
function single() /*:any*/ /*:string*/{ | ||
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = arguments[_key3]; | ||
} | ||
return args.reduce(argReducer, [block]); | ||
return argParser.apply(undefined, [true].concat(args)).pop(); | ||
}; | ||
function argParser(scoped /*:boolean*/, block /*:string*/) /*:any*/ /*:Classnames*/{ | ||
for (var _len4 = arguments.length, args = Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) { | ||
args[_key4 - 2] = arguments[_key4]; | ||
} | ||
return args.reduce(argReducer(scoped), [block]); | ||
} | ||
function argReducer(result, value) { | ||
function argReducer(scoped /*:boolean*/) { | ||
if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === "object") { | ||
return result.concat(modifierParser(value).reduce(function (subresult, modifier) { | ||
return subresult.concat(prefix(result, modifier)); | ||
}, [])); | ||
} | ||
return function (result /*:any*/, value /*:any*/) /*:Classnames*/{ | ||
if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === "object") { | ||
return modifers(result, value, "--"); | ||
} | ||
return [value].concat(prefix(result, "__" + value)); | ||
var prefixed = concat(result, value, "__"); | ||
return scoped ? prefixed : [value].concat(prefixed); | ||
}; | ||
} | ||
function modifierParser(modifiers) { | ||
return Object.keys(modifiers).map(function (modifier) { | ||
function modifers(result /*:Classnames*/, value /*:Modifiers*/, delimiter /*:string*/) /*:Classnames*/{ | ||
return result.concat(modifierParser(value).reduce(function (subresult /*:Classnames*/, modifier /*:string*/) { | ||
return subresult.concat(concat(result, modifier, delimiter)); | ||
}, [])); | ||
} | ||
function modifierParser(modifiers /*:Modifiers*/) /*:Classnames*/{ | ||
return Object.keys(modifiers).map(function (modifier /*:string*/) { | ||
return [modifier, modifiers[modifier]]; | ||
@@ -41,9 +70,9 @@ }).reduce(modifierReducer, []); | ||
function modifierReducer(result, _ref) { | ||
function modifierReducer(result /*:Classnames*/, _ref) /*:Classnames*/{ | ||
var _ref2 = _slicedToArray(_ref, 2), | ||
modifier = _ref2[0], | ||
value = _ref2[1]; | ||
modifier /*:string*/ = _ref2[0], | ||
value /*:any*/ = _ref2[1]; | ||
if (value !== false && value !== "" && value !== null && typeof value !== "undefined") { | ||
result.push("--" + modifier + (value !== true ? "-" + value : "")); | ||
result.push("" + modifier + (value !== true ? "-" + value : "")); | ||
} | ||
@@ -53,8 +82,12 @@ return result; | ||
function prefix(prefixes, value) { | ||
return prefixes.map(function (prefix) { | ||
return "" + prefix + value; | ||
function concat(prefixes /*:Classnames*/, value /*:string*/, delimiter /*:string*/) /*:Classnames*/{ | ||
return prefixes.map(function (prefix /*:string*/) { | ||
return "" + prefix + delimiter + value; | ||
}); | ||
} | ||
module.exports = bem; | ||
module.exports = bem; | ||
module.exports.scoped = scoped; | ||
module.exports.single = single; |
{ | ||
"name": "@dr/bem-helper", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"description": "Helper to create BEM-style classnames", | ||
"main": "lib/index.js", | ||
"scripts": { | ||
"test": "jest", | ||
"test": "jest --no-watchman", | ||
"build": "babel src -d lib", | ||
"prepublish": "npm run build && npm test" | ||
"prepublish": "npm run build && npm test", | ||
"flow": "flow check" | ||
}, | ||
@@ -27,8 +28,10 @@ "repository": { | ||
"devDependencies": { | ||
"babel-cli": "^6.18.0", | ||
"babel-jest": "^17.0.2", | ||
"babel-polyfill": "^6.16.0", | ||
"babel-preset-es2015": "^6.18.0", | ||
"jest": "^17.0.2" | ||
"babel-cli": "^6.22.2", | ||
"babel-jest": "^18.0.0", | ||
"babel-plugin-transform-flow-comments": "^6.22.0", | ||
"babel-polyfill": "^6.22.0", | ||
"babel-preset-es2015": "^6.22.0", | ||
"flow-bin": "^0.38.0", | ||
"jest": "^18.1.0" | ||
} | ||
} |
@@ -5,2 +5,22 @@ # bem-helper | ||
```js | ||
var className = bem("block", "element", {modifier: true}); | ||
/* | ||
className == "element block__element element--modifier block__element--modifier" | ||
______________ ________________________ | ||
| | | | ||
______| _________________________| | | ||
\/ \/ | | ||
bem.scoped == "block__element block__element--modifier" | | ||
| | ||
_____________________________________________| | ||
\/ | ||
bem.single == "block__element--modifier" | ||
*/ | ||
``` | ||
## Install | ||
@@ -17,17 +37,21 @@ | ||
var className = bem("dr-module", "list"); | ||
// className === "list dr-module__list" | ||
var className = bem("block", "element"); | ||
// className === "element block__element" | ||
var className = bem("dr-module", { loaded: true }); | ||
// className === "dr-module dr-module--loaded" | ||
var className = bem("block", { modifier: true }); | ||
// className === "block block--modifier" | ||
// Get all applicable combinations for an element: | ||
var className = bem("dr-module", "list", { expanded: true }); | ||
// className === "list dr-module__list list--expanded dr-module__list--expanded" | ||
var className = bem("block", "element", { modifier: true }); | ||
// className === "element block__element element--modifier block__element--modifier" | ||
// Get all applicable combinations scoped combinations for an element: | ||
var className = bem.scoped("block", "element", { modifier: true }); | ||
// className === "block__element block__element--modifier" | ||
// Get a single classname for an element: | ||
var className = bem.single("dr-module", "list", { expanded: true }); | ||
// className === "dr-module__list--expanded" | ||
var className = bem.single("block", "element", { modifier: true }); | ||
// className === "block__element--modifier" | ||
@@ -38,9 +62,12 @@ | ||
// Get all applicable combinations for an element: | ||
var className = bem("dr-module", "list", { expanded: true, rated: 3 }); | ||
// className === "list dr-module__list list--expanded dr-module__list--expanded list--rated-3 dr-module__list--rated-3" | ||
var className = bem("block", "element", { modifier: "value", modifier2: false }); | ||
// className === "element block__element element--modifier block__element--modifier element--modifier-value block__element--modifier-value" | ||
// Get all applicable scoped combinations for an element: | ||
var className = bem.scoped("block", "element", { modifier: "value", modifier2: false }); | ||
// className === "block__element block__element--modifier block__element--modifier-value" | ||
// Get a single classname for an element: | ||
var className = bem.single("dr-module", "list", { rated: 3 }); | ||
// className === "dr-module__list--rated-3" | ||
var className = bem.single("block", "element", { modifier: "value" }); | ||
// className === "block__element--modifier-value" | ||
@@ -50,15 +77,21 @@ | ||
var block = "dr-module"; | ||
var block = "block"; | ||
var boundBem = bem.bind(null, block); | ||
// Get all applicable combinations for an element: | ||
var className = boundBem("element", { modifier: true }); | ||
// className === "element block__element element--modifier block__element--modifier" | ||
var boundScoped = bem.scoped.bind(null, block); | ||
// Get all applicable scoped combinations for an element: | ||
var className = boundBem("list", { expanded: true }); | ||
// className === "list dr-module__list list--expanded dr-module__list--expanded" | ||
var className = boundScoped("element", { modifier: true }); | ||
// className === "block__element block__element--modifier" | ||
var boundSingle = bem.single.bind(null, block); | ||
// Get a single scoped classname for an element: | ||
var className = boundSingle("list", { expanded: true }); | ||
// className === "dr-module__list--expanded" | ||
// Get a single classname for an element: | ||
var className = boundSingle("element", { modifier: true }); | ||
// className === "block__element--modifier" | ||
@@ -76,6 +109,10 @@ ``` | ||
* `block` (string) - The block element for the classname. | ||
* `...args` (string|object) - Optional. Elements are described by strings and modifiers are described by objects: keys are use as the modifier names and boolean values trigger whether the modifier is active, and any other type is used as a value; `{expanded: true}` > `"--expanded"`, `{rating: 3}` > `"--rating-3"`. | ||
* `...args` (string|object) - Optional. Elements are described by strings and modifiers are described by objects: keys are use as the modifier names and boolean values trigger whether the modifier is active, and any other type is used as a value; `{modifier: true}` > `"--modifier"`, `{modifier: "value"}` > `"--modifier-value"`. | ||
### bem.scoped | ||
Same as `bem` - but it returns a fully scoped classname. | ||
### bem.single | ||
Same as `bem` above - but it only returns a single classname. | ||
Same as `bem` - but it only returns a single classname. |
@@ -1,30 +0,49 @@ | ||
function bem (...args) { | ||
return argParser(...args).join(" "); | ||
/* @flow */ | ||
/*:: type Modifiers = { [key: string]: any }; */ | ||
/*:: type Classnames = Array<string>; */ | ||
function bem (...args/*:any*/) /*:string*/ { | ||
return argParser(false, ...args).join(" "); | ||
} | ||
bem.single = (...args) => argParser(...args).pop(); | ||
function scoped (...args/*:any*/) /*:string*/ { | ||
return argParser(true, ...args).join(" "); | ||
}; | ||
function argParser (block, ...args) { | ||
return args.reduce(argReducer, [block]); | ||
function single (...args/*:any*/) /*:string*/ { | ||
return argParser(true, ...args).pop(); | ||
}; | ||
function argParser (scoped/*:boolean*/, block/*:string*/, ...args/*:any*/) /*:Classnames*/ { | ||
return args.reduce(argReducer(scoped), [block]); | ||
} | ||
function argReducer (result, value) { | ||
function argReducer (scoped/*:boolean*/) { | ||
if (typeof value === "object") { | ||
return result.concat( | ||
modifierParser(value) | ||
.reduce( | ||
(subresult, modifier) => subresult.concat(prefix(result, modifier)), | ||
[] | ||
) | ||
); | ||
return function (result/*:any*/, value/*:any*/) /*:Classnames*/ { | ||
if (typeof value === "object") { | ||
return modifers(result, value, "--"); | ||
} | ||
var prefixed = concat(result, value, "__"); | ||
return (scoped) ? prefixed : [value].concat(prefixed); | ||
} | ||
return [value].concat(prefix(result, `__${value}`)); | ||
} | ||
function modifers(result/*:Classnames*/, value/*:Modifiers*/, delimiter/*:string*/) /*:Classnames*/ { | ||
return result.concat( | ||
modifierParser(value) | ||
.reduce( | ||
(subresult/*:Classnames*/, modifier/*:string*/) => subresult.concat(concat(result, modifier, delimiter)), | ||
[] | ||
) | ||
); | ||
} | ||
function modifierParser (modifiers) { | ||
function modifierParser (modifiers/*:Modifiers*/) /*:Classnames*/ { | ||
return Object.keys(modifiers).map( | ||
(modifier) => [modifier, modifiers[modifier]] | ||
(modifier/*:string*/) => [modifier, modifiers[modifier]] | ||
).reduce( | ||
@@ -36,5 +55,5 @@ modifierReducer, | ||
function modifierReducer (result, [modifier, value]) { | ||
function modifierReducer (result/*:Classnames*/, [modifier/*:string*/, value/*:any*/]) /*:Classnames*/ { | ||
if (value !== false && value !== "" && value !== null && typeof value !== "undefined") { | ||
result.push(`--${modifier}${(value !== true) ? `-${value}` : "" }`); | ||
result.push(`${modifier}${(value !== true) ? `-${value}` : "" }`); | ||
} | ||
@@ -44,5 +63,5 @@ return result; | ||
function prefix (prefixes, value) { | ||
function concat (prefixes/*:Classnames*/, value/*:string*/, delimiter/*:string*/) /*:Classnames*/ { | ||
return prefixes.map( | ||
(prefix) => `${prefix}${value}` | ||
(prefix/*:string*/) => `${prefix}${delimiter}${value}` | ||
); | ||
@@ -52,1 +71,5 @@ } | ||
module.exports = bem; | ||
module.exports.scoped = scoped; | ||
module.exports.single = single; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
111290
10
255
114
7