Skip to content

Instantly share code, notes, and snippets.

@danielguillan
Created June 18, 2014 09:06
Show Gist options
  • Save danielguillan/47ee4c6fba5f88cb348e to your computer and use it in GitHub Desktop.
Save danielguillan/47ee4c6fba5f88cb348e to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
// ----
// Sass (v3.3.8)
// Compass (v1.0.0.alpha.19)
// ----
// =============================================================================
// Experimenting with BEM maps
//
// Table of contents:
// 1. Demo BEM map
// 2. Getter functions
// 3. Setter functions
// 4. Exists functions
// 5. Mixins
// 6. Debug
//
// =============================================================================
// =============================================================================
// 1. Demo BEM map
// =============================================================================
$bem: (
blocks: (
flag: (
elements: (
body: (
modifiers: (
foo: (
modifies-block: true,
),
bar: (
modifies-block: true,
),
),
),
image: (
modifiers: (
foo: (
modifies-block: true,
),
bar: (
modifies-block: true,
),
),
),
),
modifiers: (
rev: (),
top: (),
bottom: (),
),
),
nav: (
elements: (),
modifiers: (
banner: (),
stacked: (),
)
),
)
);
// =============================================================================
// 2. Getter functions
// =============================================================================
// Get Blocks
// ---
// @access public
// ---
// @return {map | Null} all declared blocks
@function get-blocks() {
@return map-get($bem, blocks);
}
// Get Block
// ---
// @access public
// ---
// @requires get-blocks
// ---
// @param {*} $block-name - the name of the block
// @return {map | Null} the block map
@function get-block($block-name) {
$blocks: get-blocks();
@return map-get($blocks, $block-name);
}
// Get block names
@function get-block-names() {
$bem-blocks: get-blocks();
@return map-keys($bem-blocks);
}
// Get elements
@function get-elements($block-name) {
@if not block-exists($block-name) {
@return throw('Can\'t get elements for block `#{$block-name}`. Undefined block.');
}
$block: get-block($block-name);
@return map-get($block, elements);
}
// Get element
@function get-element($block-name, $element-name) {
$elements: get-elements($block-name);
@return map-get($elements, $element-name);
}
// Get element names
@function get-element-names($block-name) {
$elements: get-elements($block-name);
@if ($elements == null) {
@return null;
}
@return map-keys($elements);
}
// Get modifiers
@function get-modifiers($block-name, $element-name: null) {
@if not block-exists($block-name) {
@return throw('Can\'t get modifiers for block `#{$block-name}`. Undefined block.');
}
$block: get-block($block-name);
$modifiers: map-get($block, modifiers);
@if ($element-name) {
@if not element-exists($block-name, $element-name) {
@return throw('Can\'t get modifiers for element `#{element-name}`. Undefined element.');
}
$element: get-element($block-name, $element-name);
$modifiers: map-get($element, modifiers);
}
@return $modifiers;
}
// Get modifer names
@function get-modifier-names($block-name, $element-name: null) {
$modifiers: get-modifiers($block-name, $element-name);
@if ($modifiers == null) {
@return null;
}
@return map-keys($modifiers);
}
// Get modifier
@function get-modifier($block-name, $modifier-name, $element-name: null) {
$modifiers: ();
@if ($element-name) {
$modifiers: get-modifiers($block-name, $element-name);
} @else {
$modifiers: get-modifiers($block-name);
}
@return map-get($modifiers, $modifier-name);
}
// =============================================================================
// 3. Setter functions
// =============================================================================
// Set block
@function set-block($block-name) {
@if block-exists($block-name) {
@return throw('Block #{$block-name} has already been defined');
}
$new: (
blocks: (
#{$block-name}: (
elements: (),
modifiers: ()
)
)
);
$bem: map-merge-recursive($bem, $new);
@return get-block($block-name);
}
// Set element
@function set-element($block-name, $element-name) {
@if not block-exists($block-name) {
@return throw('Block #{$block-name} does not exist');
}
@if element-exists($block-name, $element-name) {
@return throw('Element #{$element-name} has already been defined for block #{$block-name}');
}
$new: (
blocks: (
#{$block-name}: (
elements: (
#{$element-name}: (
modifiers: ()
)
)
)
)
);
$bem: map-merge-recursive($bem, $new) !global;
@return get-element($block-name, $element-name);
}
// Set modifier
@function set-modifier($block-name, $modifier-name, $element-name: null, $modifies-block: false) {
@if not block-exists($block-name) {
@return throw('Block #{$block-name} does not exist');
}
@if $element-name {
@if not element-exists($block-name, $element-name) {
@return throw('Element #{element-name} does not exist in block {block-name}');
}
}
@if modifier-exists($block-name, $modifier-name, $element-name) {
@return throw('Modifier #{$modifier-name} has already been defined');
}
$new: ();
@if $element-name {
$new: (
blocks: (
#{$block-name}: (
elements: (
#{$element-name}: (
modifiers: (
#{$modifier-name}: (
modifies-block: $modifies-block
)
)
)
)
)
)
);
} @else {
$new: (
blocks: (
#{$block-name}: (
modifiers: (
#{$modifier-name}: (
)
)
)
)
);
}
$bem: map-merge-recursive($bem, $new) !global;
@if $element-name {
@return get-modifier($block-name, $modifier-name, $element-name);
} @else {
@return get-modifier($block-name, $modifier-name);
}
}
// =============================================================================
// 4. Exists
// =============================================================================
// Block exists
@function block-exists($block-name) {
@return not not get-block($block-name);
}
// Element exists
@function element-exists($block-name, $element-name) {
@return not not get-element($block-name, $element-name);
}
// Modifier exists
@function modifier-exists($block-name, $modifier-name, $element-name: null) {
@if ($element-name) {
@return not not get-modifier($block-name, $modifier-name, $element-name);
}
@return not not get-modifier($block-name, $modifier-name);
}
@function throw($message: 'BEM error...') {
@warn $message;
@return null;
}
@function map-merge-recursive($map1, $map2) {
$result: $map1;
@each $key, $value in $map2 {
@if map-get($result, $key) != null and type-of($value) == map and type-of(map-get($result, $key)) == map {
$value: map-merge-recursive(map-get($result, $key), $value);
}
$result: map-merge($result, ($key: $value));
}
@return $result;
}
// =============================================================================
// 5. Mixins
// =============================================================================
@mixin block($block-name) {
$new-block: set-block($block-name);
@if ($new-block) {
.#{$block-name} {
@content;
}
}
}
@mixin element($element-name, $block-name) {
//$block-name: get-current-block();
$new-element: set-element($block-name, $element-name);
@if ($new-element) {
&__#{$element-name} {
@content;
}
}
}
@mixin modifier($modifier-name, $block-name, $element-name: null, $modifies-block: false) {
$new-modifier: set-modifier($block-name, $modifier-name, $element-name, $modifies-block);
@if $new-modifier {
@if $element-name and $modifies-block == true {
@at-root .#{$block-name}--#{$modifier-name} .#{$element-name} {
@content;
}
} @else {
@at-root &--#{$modifier-name} {
@content;
}
}
}
}
@include block('person') {
name: 'Dani';
// TODO: we shouldn't neeed to pass the block
@include element('head', 'person') {
glasses: true;
// TODO: add element modifier + element-modifier that modifier block
@include modifier('facial-hair', 'person') {
moustache: true;
}
@include modifier('angry', 'person', 'head', true) {
eyes: frown;
}
}
// TODO: we shouldn't neeed to pass the block
@include modifier('beer', 'person') {
happy: true;
}
}
// =============================================================================
// 6. Debug
// =============================================================================
.debug {
/* demo map */
bem: inspect($bem);
/* Setters */
set-new-block: inspect(set-block('new-block'));
set-new-element: inspect(set-element(flag, new-element));
set-new-block-modifier: inspect(set-modifier(flag, new-modifier));
set-new-element-modifier: inspect(set-modifier(flag, new-element-modifier, body, true));
/* Getters */
get-blocks: inspect(get-blocks());
get-block-names: get-block-names();
get-flag: inspect(get-block(flag));
get-flag-elements: inspect(get-elements(flag));
get-flag-element-names: get-element-names(flag);
get-flag-modifiers: inspect(get-modifiers(flag));
get-flag-modifier-names: get-modifier-names(flag);
get-flag-body-element: inspect(get-element(flag, body));
get-flag-body-element-modifiers: inspect(get-modifiers(flag, body));
get-flag-body-element-modifier-names: get-modifier-names(flag, body);
get-flag-block-modifier-rev: inspect(get-modifier(flag, rev));
get-flag-element-body-modifier-foo: inspect(get-modifier(flag, foo, body));
/* Exists */
block-exists-true: block-exists(flag);
block-exists-false: block-exists(foo);
element-exists-true: element-exists(flag, body);
element-exists-false: element-exists(flag, foo);
modifier-exists-true: modifier-exists(flag, rev);
modifier-exists-false: modifier-exists(flag, foo);
element-modifier-exists-true: modifier-exists(flag, foo, body);
element-modifier-exists-false: modifier-exists(flag, rev, body);
/* Error handling, should not fail, warn the user and return `null` */
get-undefined-block: inspect(get-block(undefined));
get-undefined-element: inspect(get-element(flag, undefined));
get-undefined-block-for-element: inspect(get-elements(undefined));
get-undefined-block-for-element-names: inspect(get-element-names(undefined));
get-undefined-block-for-modifier: inspect(get-modifiers(undefined));
get-undefined-block-for-modifier-names: inspect(get-modifier-names(undefined));
get-undefined-element-for-modifier: inspect(get-modifiers(flag, undefined));
get-undefined-element-for-modifier-names: inspect(get-modifier-names(flag, undefined));
get-undefined-modifier-for-block: inspect(get-modifier(flag, undefined));
get-undefined-modifier-for-element: inspect(get-modifier(flag, undefined, body));
set-new-block-dublicate: inspect(set-block('new-block'));
set-new-element-duplicate: inspect(set-element(flag, new-element));
set-new-block-modifier-duplicate: inspect(set-modifier(flag, new-modifier));
set-new-element-modifier-duplicate: inspect(set-modifier(flag, new-element-modifier, body, true));
}
.person {
name: 'Dani';
}
.person__head {
glasses: true;
}
.person__head--facial-hair {
moustache: true;
}
.person--angry .head {
eyes: frown;
}
.person--beer {
happy: true;
}
.debug {
/* demo map */
bem: (blocks: ((flag: ((elements: ((body: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)))))), image: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)))))))), modifiers: ((rev: (), top: (), bottom: ())))), nav: ((elements: (), modifiers: ((banner: (), stacked: ())))), person: ((elements: ((head: ((modifiers: ((angry: ((modifies-block: true)))))))), modifiers: ((facial-hair: (), beer: ())))))));
/* Setters */
set-new-block: (elements: (), modifiers: ());
set-new-element: (modifiers: ());
set-new-block-modifier: ();
set-new-element-modifier: (modifies-block: true);
/* Getters */
get-blocks: (flag: ((elements: ((body: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)), new-element-modifier: ((modifies-block: true)))))), image: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)))))), new-element: ((modifiers: ())))), modifiers: ((rev: (), top: (), bottom: (), new-modifier: ())))), nav: ((elements: (), modifiers: ((banner: (), stacked: ())))), person: ((elements: ((head: ((modifiers: ((angry: ((modifies-block: true)))))))), modifiers: ((facial-hair: (), beer: ())))), new-block: ((elements: (), modifiers: ())));
get-block-names: flag, nav, person, new-block;
get-flag: (elements: ((body: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)), new-element-modifier: ((modifies-block: true)))))), image: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)))))), new-element: ((modifiers: ())))), modifiers: ((rev: (), top: (), bottom: (), new-modifier: ())));
get-flag-elements: (body: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)), new-element-modifier: ((modifies-block: true)))))), image: ((modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)))))), new-element: ((modifiers: ())));
get-flag-element-names: body, image, new-element;
get-flag-modifiers: (rev: (), top: (), bottom: (), new-modifier: ());
get-flag-modifier-names: rev, top, bottom, new-modifier;
get-flag-body-element: (modifiers: ((foo: ((modifies-block: true)), bar: ((modifies-block: true)), new-element-modifier: ((modifies-block: true)))));
get-flag-body-element-modifiers: (foo: ((modifies-block: true)), bar: ((modifies-block: true)), new-element-modifier: ((modifies-block: true)));
get-flag-body-element-modifier-names: foo, bar, new-element-modifier;
get-flag-block-modifier-rev: ();
get-flag-element-body-modifier-foo: (modifies-block: true);
/* Exists */
block-exists-true: true;
block-exists-false: false;
element-exists-true: true;
element-exists-false: false;
modifier-exists-true: true;
modifier-exists-false: false;
element-modifier-exists-true: true;
element-modifier-exists-false: false;
/* Error handling, should not fail, warn the user and return `null` */
get-undefined-block: null;
get-undefined-element: null;
get-undefined-block-for-element: null;
get-undefined-block-for-element-names: null;
get-undefined-block-for-modifier: null;
get-undefined-block-for-modifier-names: null;
get-undefined-element-for-modifier: null;
get-undefined-element-for-modifier-names: null;
get-undefined-modifier-for-block: null;
get-undefined-modifier-for-element: null;
set-new-block-dublicate: null;
set-new-element-duplicate: null;
set-new-block-modifier-duplicate: null;
set-new-element-modifier-duplicate: null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment