npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bemerald

v0.0.2

Published

Pure-sass mixins & functions that make writing BEM a piece of cake

Downloads

2

Readme

BEMerald

Pure-sass functions and mixins to make writing BEM a piece of cake. Keeps things simple and handles tricky cases gracefully.

tl;dr

/** simple **/

@include Block(notification) {     // .notification {
  border: 1px solid #ccc;          //   border: 1px solid #ccc;
  padding: 20px;                   //   padding: 20px;
                                   // }
  @include Elem(link) {            // .notification__link {
    float: right;                  //   float: right;
  }                                // }
                                   // .notification--error {
  @include Mod(error) {            //   border-color: red;
    border-color: red;             // }
  }
}                                  
                              

/** more involved **/ 

@include B(myblock) {              //  .myblock {
  background: white;               //    background: white;
                                   //  }
  @include E(subelem) {            //  .myblock__subelem {
    color: blue;                   //    color: blue;
  }                                //  }
                                   //  .myblock:hover {
  &:hover {                        //    text-decoration: underline;
    text-decoration: underline;    //  }
                                   //  .myblock:hover .myblock__subelem {
    @include E(subelem) {          //    color: green;
      color: green;                //  }
    }                              //  .myblock--mymod {
  }                                //    background: green;
                                   //  }
  @include M(mymod) {              //  .myblock--mymod .myblock__subelem {
    background: green;             //    color: green;
                                   //  }
    @include E(subelem) {          //  .myblock--mymod:hover {
      color: green;                //    font-weight: bold;
    }                              //  }
                                   //  .myblock--mymod:hover .myblock__subelem {
    &:hover {                      //    color: red;
      font-weight: bold;           //  }
      
      @include E(subelem) {
        color: red;
      }
    }
  }
}

Installation

Right now you have 2 options:

  • Copy/paste the bemerald.scss file (it's all one self-contained file) into your project
  • Install via npm install bemerald and configure your builder to point to the node_modules folder

TODO: Provide easier installation & plugins for common build tools

Usage

in order of most commonly used...

Mixins

The build-in mixins allow you to write your SCSS in a nested way that feels very natural, but still get flat root-level selectors, as per BEM methodology.


@include Block($block) { ... }

Simply unrolls into a class-selector. Main purpose of using this mixin is to clearly denote the start of a BEM block.

@include Block(notification) {     //  .notification {
  position: relative;              //    position: relative;
  border: 1px solid #ccc;          //   border: 1px solid #ccc;
  padding: 10px;                   //    padding: 10px;
}                                  //  }

// Shorthand alias
@include B(notification) { ... }

@include Mod($mod) { ... }

Unrolls into a BEM block-modifier selector.

May be either:

  • String: Simple modifier string. mod results in .block--mod
  • Map: Modifier string with value. (mod: value) results in .block--mod-value

Notes:

  • This mixin does not generate element-modifiers. Use Elem(elem, $mod:mod).
  • Nesting a Mod inside a pseudo-selector is not supported, because what that should mean isn't clear.
@include Block(notification) {       //  .notification--error {
  // ...                             //    background: rgba(255, 0, 0, 0.15);
  @include Mod(error) {              //    border-color: red;
    background: rgba(red, 0.15);     //  }
    border-color: red;               
  }                                  
                                     
  @include Mod((theme: growl)) {     //  .notification--theme-growl {
    top: 0;                          //    top: 0;
    right: 0;                        //    right: 0;
    width: 200px;                    //    width: 200px;
    height: auto;                    //    height: auto;
  }                                  //  }
                                     
  @include Mod((theme: bar)) {       //  .notification--theme-bar {
    bottom: 0;                       //    bottom: 0;
    left: 0;                         //    left: 0;
    width: 100%;                     //    width: 100%;
    height: 200px;                   //    height: 200px;
  }                                  //  }
}

// Shorthand alias
@include M(error) { ... }

@include Elem($elem-name, $mod:null)

Unrolls into a proper BEM element selector, depending on the context:

  • Inside just a block, yields a root-level .block__elem
  • Inside a mod or pseudo-selector, yields a nested .block--mod .block__elem

If $mod is included, it is appended to the block selector, like .block__elem--mod. Multiple $mods are not supported.

@include Block(notification) {                   //  .notification__dismiss-btn {
  // ...                                         //    position: absolute;
  @include Elem(dismiss-btn) {                   //    right: 0;
    position: absolute;                          //    font-weight: bold;
    right: 0;                                    //  }
    font-weight: bold;                           
  }                                              
                                                 
  @include Elem(dismiss-btn, $mod:on-left) {     //  .notification__dismiss-btn--on-left {
    left: 0;                                     //    left: 0;
    right: auto;                                 //    right: auto;
  }                                              //  }
                                                 
  // Works inside mods:                          
  @include Mod(error) {                          //  .notification--error .notification__dismiss-btn {
    @include Elem(dismiss-btn) {                 //    display: none;
      display: none;                             //  }
    }                                            
  }                                              
                                                 
  // ... and pseudo-selectors
  &:hover {                                      //  .notification:hover .notification__dismiss-btn {
    @include Elem(dismiss-btn) {                 //    transform: scale(1.1);
      transform: scale(1.1);                     //  }
    }
  }
}

// Shorthand aliases (mixin and argument)
@include E(dismiss-btn, $m:on-left) { ... }

@include BEM($block, $elem:null, $mods:null)

Unrolls into a full BEM selector. See the bem-selector documentation for parameter details.

@include BEM(notification, $mod:error, $elem:dismiss-btn) {
  color: red;
}

//  .notification--error .notification__dismiss-btn {
//    color: red;
//  }

Functions

bem-selector($block, $elem:null, $mods:null)

Generates a full BEM selector.

  • $block: Required. A string block name.

  • $elem: Optional. A sub-element name. If $mod is not present, it is joined with $block. If $mod is present, it is nested under $block--$mod May be either:

    • String: Simple element name. Results in .block__elem
    • List: Pair like ($elem-name, $elem-mod) Applies the element-modifier to the subelement. Multiple elem-mods are not supported. Same types as $mod.
  • $mod: Optional. A block modifier. May be either:

    • String: Simple modifier string. Results in .block--mod
    • Map: ($modifier-name: $modifier-value). Results in .block--mod-val
  • $mods: Optional. List. Allows generating selectors for multiple mods at once. Each element of the list should be one of the allowed type for $mod

$s: bem-selector(block);                   //  .block

$s: bem-selector(block, $e:elem);          //  .block__elem
$s: bem-selector(block, $e:(elem,emod);    //  .block__elem--emod

$s: bem-selector(block, $m:mod);           //  .block--mod
$s: bem-selector(block, $m:(mod:val));     //  .block--mod-val
 
$s: bem-selector(block, $m:mod, $e:elem);  //  .block--mod .block__elem

$s: bem-selector(block, $m:(mod-a,(mod-b:bval)), $e:elem);
// .block--mod-a .block__elem, .block--mod-b-bval .block__elem

You could use it like...

#{bem-selector(block, $e:elem, $m:mod)} { 
  // this is exactly what the BEM mixin does
}

Shorthand Aliases

The provided mixins come with "shorthand aliases" so you can save some typing.

@include Block(b) { ... }
@include B(b) { ... }

@include Elem(e, $mod:m) { ... }
@include E(e, $m:m) { ... }

@include Mod(m) { ... }
@include M(m) { ... }

Development

One-time setup

npm install; npm install -g mocha;

Run tests

npm test

Runs tests located in /test

With love to...

  • Sass in general (duh - sass rocks)
  • libsass specifically (speed rocks)
  • true (tests rock)
  • SassMeister (instant feedback rocks, too)
  • You (also rock)

With love from...

Rafflecopter

License

Released under MIT license, same as Sass.

TODO

  • Provide easier installation & plugins for common build tools
  • test all functions. Right now at least bem--extract-block needs tests.
  • try to test mixins. Might be tricky since they use @at-root
  • automated test in various sass implementations?