Created
June 18, 2014 09:06
-
-
Save danielguillan/47ee4c6fba5f88cb348e to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---- | |
// 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)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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