Skip to content

Instantly share code, notes, and snippets.

@brookjordan
Last active July 7, 2020 10:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brookjordan/dce6e41b39b692cad5c8bc7eac1256c8 to your computer and use it in GitHub Desktop.
Save brookjordan/dce6e41b39b692cad5c8bc7eac1256c8 to your computer and use it in GitHub Desktop.
Simple function to aid with building BEM-style class names
/**
* Used like:
* const cls = buildBEMBuilder("block-name");
*
* let blockClass = cls();
* // => "block-name"
*
* let modifiedBlockClass = cls({
* goodModifier: true,
* badModifier: false,
* });
* // => "block-name block-name--good-modifier"
*
* let elementClass = cls('an-element');
* // => "block-name__an-element"
*
* let modifiedElementClass = cls('an-element', {
* aModifier: true,
* anotherModifier: true,
* });
* // => "block-name__an-element block-name__an-element--a-modifier block-name__an-element--another-modifier"
**/
const FALSY_CHECKS = {
true(condition) { return condition !== true },
truthy(condition) { return !condition },
nullish(condition) { return condition === false || condition == null },
};
let modifierCheckStyle = Object.keys(FALSY_CHECKS)[0];
function dasherize(str) {
return str
.replace(/_/g, "-")
.replace(/[A-Z]/g, char => `-${char.toLowerCase()}`)
.replace(/^-+/g, "");
}
function buildBEMBuilder(_blockName) {
const blockName = dasherize(_blockName);
return function combineWithElementAndModifiers(element, modifiers = {}) {
if (!element) { return blockName; }
let elementClass = blockName;
if (typeof element === "string") {
elementClass += `__${dasherize(element)}`;
}
else if (typeof element === "object") {
modifiers = element;
}
if (!modifiers) { return elementClass; }
return Object.entries(modifiers)
.reduce((className, [modifier, useModifier]) => {
if (FALSY_CHECKS[modifierCheckStyle](useModifier)) { return className; }
return `${className} ${elementClass}--${dasherize(modifier)}`;
}, elementClass);
}
}
Object.defineProperty(bEMClassBuilder, "modifierCheckStyle", {
get() {
return modifierCheckStyle;
},
set(requestedCheckStyle) {
if (FALSY_CHECKS[requestedCheckStyle]) {
throw Error(
`invalid-truthy-check-style:
There is no truthy check style of “${requestedCheckStyle}”
Must be one of:
${
FALSY_CHECKS.map(a => `• ${a}`).join('\n')
}`.replace(/ /g, ''));
}
modifierCheckStyle = requestedCheckStyle;
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment