0.1.15 • Published 6 years ago

auto-bem v0.1.15

Weekly downloads
3
License
-
Repository
github
Last release
6 years ago

Auto BEM for Components

Build Status NPM version

Framework-agnostic BEM Transformer API for HTML, CSS or Mask

Creates Scoped CSS by replacing selectors (block and elements) in CSS with unique names, and adding those names to the matched elements in HTML

:rocket: This module gives you only the functions. You may want to integrate them into your favorite Build-Tool.

:exclamation: Important: You can still use BEM methodology, but now you can be sure that the name collisions are not more possible, so you can feel yourself relaxed in planning the names for your blocks and elements.


1 Understand the idea

1.1 Block and Element

:exclamation: One HTML file ond CSS file per Block.

<div class='foo'>
    <header><span class='title'></span></header>
    <ul>
        <li class='item'></li>
    </ul>
</div>
.foo {}
.foo header > .title {}
.foo ul {}
.foo .item {}
/* LESS or SASS would look better */

The example above is not about how you should write your CSS, it only shows the idea about selector transformations. The output will be:

<div class='foo_SALT foo'>
    <header>
        <span class='foo_SALT__tag_header__child__title title'></span>
    </header>
    <ul class='foo_SALT__tag_ul'>
        <li class='foo_SALT__item item'></li>
    </ul>
</div>
.foo_SALT {}
.foo_SALT__tag_header__child__title {}
.foo_SALT__tag_ul {}
.foo_SALT__item {}

:sweat_drops: Notice:

  • CSS has only the generated class names
  • The generated classes are inserted into the HTML
  • Old CSS classes are preserved in HTML (in case you want later extend the styles from outside or find them from js.)
  • The elements should be present in HTML, otherwise the elements tag can't be found in HTML but it will be renamed in CSS, to ensure no collisions with other blocks/elements are present.

1.2 Modifiers

Two reasons for this decision:

  1. We leave the original modifier names in css, to toggle them in the runtime.
  2. (Imho section) Modifiers usually represent some state of the element or block, and, actually, this state can be block- or element-independent. For example: .is-visible, .is-active, .type-image, .theme-summer. Even when to 2 elements are on the same node, it doesn`t matter which one implements and supports the state.
<div class='foo is-selected'>
    <span class='title'></span>    
</div>
.foo.is-selected { /*...*/ }
.foo.is-selected .title { /*...*/ }

Outputs:

<div class='foo_SALT foo is-selected'>
    <span class='foo_SALT__title'></span>
</div>
.foo_SALT.is-selected { /*...*/ }
.foo_SALT.is-selected .foo_SALT__title { /*...*/ }

1.3 Host

The are two ways to define the block.

  1. With the root CSS name, like foo in the Block and Element example (HTML and CSS).
  2. Without the root CSS name, means the selectors are for elements. Then, to target the block, use :host css selector.
<div>
    <header><span class='title'></span></header>
    <ul>
        <li class='item'></li>
    </ul>
</div>
:host {}
header > .title {}
ul {}
.item {}

The output of the transformion with the defined filename, e.g. /some/path/to/MyComponent.html

<div class="MyComponent_SALT">
    <header>
        <span class='MyComponent_SALT__tag_header__child__title title'></span>
    </header>
    <ul class='MyComponent_SALT__tag_ul'>
        <li class='MyComponent_SALT__item item'></li>
    </ul>
</div>
.MyComponent_SALT {}
.MyComponent_SALT__tag_header__child__title {}
.MyComponent_SALT__tag_ul {}
.MyComponent_SALT__item  {}

1.4 Pseudo Selectors

Pseudo selectors are the same as the modifiers.


2 API

2.1 Require

var autoBem = require('auto-bem');

2.2 Transform

Transform both, CSS and the template, at once.

.transform(template: string, css: string, options: Options): Result

2.2.1 Options

KeyTypeDefaultDescription
scopeIdstringnullDefine your own block name. Per default we try to find the id by block name or the filename
scopeTypestring'block' | 'host'Per default we try to find out, if your css describes a block or host styles.
useSaltbooleantrueAdd a unique salt, when generating the block name, to ensure the block name is absolutely unique
templateTypestringhtmlFor now, we support html and mask syntax
filenamestringnullPath to the template. Primary, will be used to get the BlockName by FileName for the :host styles, otherwise only SALT will be generated

2.2.2 Result

Returns transformed template and styles.

{
    template: string,
    css: string
}

2.3 Two-Step Transform

Sometimes you may want to apply one stylesheet to different templates. There for create the BemCss instance of the stylesheet and apply it to different templates.

class BemCss {
    constructor (cssText: string, options?: StyleOptions),
    /* Transformed css */
    getStyle (),
    /* transform template */
    transformTemplate (template: string, options?: TemplateOptions)
}

StyleOptions = {
    scopeId?,
    scopeType?,
    useSalt?,
    filename?
};
TemplateOptions = {
    templateType?
};
let bemCss = new AutoBem.BemCss(myCssText, StyleOptions)

let cssText  = bemCss.getStyle();
let tmplText = bemCss.transformTemplate(template, TemplateOptions)

console.log(cssText, tmplText);

3 Tests

See the tests for more examples.


:heart: We love any kind of questions and suggestions.

:copyright: 2017 - MIT

0.1.15

6 years ago

0.1.13

6 years ago

0.1.12

6 years ago

0.1.11

7 years ago

0.1.10

7 years ago

0.1.9

7 years ago

0.1.8

7 years ago