Finaly a Tool to generate reusable BEM
This commit is contained in:
parent
fac6fb4da5
commit
08e20dfcb3
@ -1,151 +1,203 @@
|
|||||||
|
// Storing the currents block properties and attributes
|
||||||
|
// to generate the block afterwards
|
||||||
/*
|
/*
|
||||||
* This is set of mixins to help generating
|
* A method for iterating throug a
|
||||||
* CSS classes according to the Block__Element--Modifier pattern.
|
* list/array safely since this language sucks
|
||||||
* It also helps nesting those classes in any fashion imaganible
|
* realy bad https://github.com/stylus/stylus/issues/1440
|
||||||
* and still produces clean BEM CSS
|
|
||||||
*/
|
*/
|
||||||
@import './_laneHandling'
|
foreach(list, callback)
|
||||||
|
for entry in list
|
||||||
|
if entry != ()
|
||||||
|
callback(entry)
|
||||||
|
|
||||||
_css-prefix = 'RV'
|
create_list()
|
||||||
|
return () ()
|
||||||
|
|
||||||
|
_block = {}
|
||||||
/*
|
reset_block()
|
||||||
* Generates a CSS class for an
|
_block.elements = create_list()
|
||||||
* Block according to BEM
|
_block.block_modifiers = create_list()
|
||||||
*/
|
_block.alias = {
|
||||||
RV-Block(block_name)
|
map: {}
|
||||||
_pop_lane('element_aliases')
|
stash: {
|
||||||
b = @block{
|
RV-Element: create_list()
|
||||||
{block}
|
RV-Element__Modifier: create_list()
|
||||||
& .{block_name}{
|
RV-Block__Modifier: create_list()
|
||||||
for element_block in _pop_stack('elements_to_generate'){
|
|
||||||
{element_block}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.{block_name}{
|
|
||||||
for modifier_block in _pop_stack('block_modifiers_to_generate'){
|
|
||||||
{modifier_block}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for modifier_block in _pop_stack('after_element_modifiers_to_generate'){
|
|
||||||
{modifier_block}
|
|
||||||
}
|
|
||||||
_reset_last_name('RV-Element')
|
|
||||||
_reset_last_name('RV-Element__Modifier')
|
|
||||||
_reset_last_name('RV-Block_Modifier')
|
|
||||||
}
|
}
|
||||||
|
_block.modifier_stash = create_list()
|
||||||
|
_block.element_stash = create_list()
|
||||||
|
|
||||||
|
// Calling the function to initiate the block
|
||||||
|
// for first use
|
||||||
|
reset_block()
|
||||||
|
|
||||||
|
_bem_mixins = 'RV-Block','RV-Element','RV-Modifier','RV-Element__Modifier','RV-Block__Modifier'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks if the caller of this funcion is a direct
|
||||||
|
* descendant of RV-Block. Checks for BEM-Mixins only.
|
||||||
|
* If any other function or mixin is between the last
|
||||||
|
* block and the caller, it will still count as an direct
|
||||||
|
* descendant of RV-Block
|
||||||
|
*/
|
||||||
|
is_direct_descendant_of_block()
|
||||||
|
block_index = index(called-from, 'RV-Block') - 1
|
||||||
|
|
||||||
if 'RV-Block' in called-from
|
if block_index <= 0
|
||||||
{b}
|
return true
|
||||||
else
|
|
||||||
.{block_name}
|
|
||||||
{b}
|
|
||||||
|
|
||||||
_reset_aliases()
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generates a CSS class for an block modifier
|
|
||||||
* according to BEM.
|
|
||||||
*/
|
|
||||||
RV-Block__Modifier(block_modifier_name)
|
|
||||||
_push_onto_stack(block)
|
|
||||||
|
|
||||||
//Detect if the selector will be generated
|
for i in (1..block_index)
|
||||||
//by an earlier call of RV-Block__Modifier
|
if called-from[i] in _bem_mixins
|
||||||
if not 'RV-Block__Modifier' in called-from
|
return false
|
||||||
// Saving accumulated modifiers and blocks
|
return true
|
||||||
if 'RV-Block' in called-from
|
|
||||||
elements = _pop_stack('block_modifier_elements_to_generate')
|
|
||||||
modifier_block = @block{
|
|
||||||
&--{block_modifier_name}{
|
|
||||||
for sub_block in _pop_stack(){
|
|
||||||
{sub_block}
|
|
||||||
}
|
|
||||||
& ^[-2..-2]{
|
|
||||||
for element in elements{
|
|
||||||
{element}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_push_onto_stack(modifier_block, 'block_modifiers_to_generate')
|
|
||||||
|
|
||||||
|
/*
|
||||||
/*
|
* Taking the currently stashed names, mapping
|
||||||
* Generates an CSS class for an element
|
* them to the given name under the called parent
|
||||||
* according to BEM. Also minds the element modifiers
|
* (using called-from) and returning the stashed blocks
|
||||||
* For more see RV-Element___Modifier
|
|
||||||
*/
|
*/
|
||||||
RV-Element(element_name)
|
generate_aliases(actual_name)
|
||||||
_push_onto_stack(block)
|
level_type = split(' ', called-from)[0]
|
||||||
|
if actual_name == null
|
||||||
//Detect if the selector will be generated
|
if length(_block.alias.stash[level_type]) > 2
|
||||||
//by an earlier call of RV-Element
|
actual_name = _block.alias.stash[level_type][-1].name
|
||||||
if not 'RV-Element' in called-from
|
|
||||||
// Saving accumulated modifiers and blocks
|
|
||||||
for alias in _pop_stack('element_aliases')
|
|
||||||
_set_alias(alias, element_name)
|
|
||||||
stack_name = 'elements_to_generate'
|
|
||||||
if 'RV-Block__Modifier' in called-from
|
|
||||||
stack_name = 'block_modifier_elements_to_generate'
|
|
||||||
|
|
||||||
element_name = _get_alias(element_name)
|
|
||||||
element_block = @block{
|
|
||||||
&__{element_name}{
|
|
||||||
for sub_block in _pop_stack(){
|
|
||||||
{sub_block}
|
|
||||||
}
|
|
||||||
&^[-3..-3]__{element_name}{
|
|
||||||
for modifier_block in _pop_stack('element_modifiers_to_generate'){
|
|
||||||
{modifier_block}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_push_onto_stack(element_block, stack_name)
|
|
||||||
_set_last_name(element_name)
|
|
||||||
else
|
|
||||||
_push_onto_stack(element_name, 'element_aliases')
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generates a CSS class for an element modifier
|
|
||||||
* according to BEM. These are ment to be part of the
|
|
||||||
* content block of an element and since child-mixins
|
|
||||||
* are called first there is no way of knowing what the
|
|
||||||
* current element is named. To solve this, we store
|
|
||||||
* a callback for the modifier and add the element name
|
|
||||||
* from RV-Element
|
|
||||||
*/
|
|
||||||
RV-Element__Modifier(element_modifier_name)
|
|
||||||
_push_onto_stack(block)
|
|
||||||
//Is this modifier beeing included by another modifier
|
|
||||||
if not 'RV-Element__Modifier' in called-from
|
|
||||||
//No, store all blocks under the give name
|
|
||||||
//Is this modifier beeing called in in- or postfix
|
|
||||||
if 'RV-Element' in called-from
|
|
||||||
//Infix, store for handling by element
|
|
||||||
modifier_block = @block{
|
|
||||||
&--{element_modifier_name}{
|
|
||||||
for current_block in _pop_stack(){
|
|
||||||
{current_block}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_push_onto_stack(modifier_block, 'element_modifiers_to_generate')
|
|
||||||
else
|
else
|
||||||
//Postfix, append to existing element
|
warn('No name found for '+called-from)
|
||||||
last_element_name = _get_last_name('RV-Element')
|
|
||||||
modifier_block = @block {
|
blocks = ()
|
||||||
& .{block_name}__{last_element_name}.{block_name}__{last_element_name}--{element_modifier_name}{
|
foreach(_block.alias.stash[level_type], @(alias){
|
||||||
for current_block in _pop_stack(){
|
_block.alias.map[level_type+':'+alias.name] = actual_name
|
||||||
{current_block}
|
push(blocks, alias.block)
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
_block.alias.stash[level_type] = create_list()
|
||||||
_push_onto_stack(modifier_block, 'after_element_modifiers_to_generate')
|
return {
|
||||||
|
name: actual_name
|
||||||
|
blocks: blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resolving the alias according to the level type
|
||||||
|
* (using called-from). Returning the given name
|
||||||
|
* when no alias is found
|
||||||
|
*/
|
||||||
|
resolve_alias(name)
|
||||||
|
level_type = split(' ', called-from)[0]
|
||||||
|
|
||||||
|
if level_type+':'+name in _block.alias.map
|
||||||
|
return _block.alias.map[level_type+':'+name]
|
||||||
|
else
|
||||||
|
return name
|
||||||
|
|
||||||
|
render_element_modifier(modifier)
|
||||||
|
&--{resolve_alias(modifier.name)}
|
||||||
|
foreach(modifier.blocks, @(block){
|
||||||
|
{block}
|
||||||
|
})
|
||||||
|
|
||||||
|
render_element(element)
|
||||||
|
&__{resolve_alias(element.name)}
|
||||||
|
foreach(element.blocks, @(block){
|
||||||
|
{block}
|
||||||
|
})
|
||||||
|
foreach(element.modifiers, @(modifier){
|
||||||
|
render_element_modifier(modifier)
|
||||||
|
})
|
||||||
|
|
||||||
|
render_block_modifier(modifier)
|
||||||
|
&--{resolve_alias(modifier.name)}
|
||||||
|
foreach(modifier.blocks, @(block){
|
||||||
|
{block}
|
||||||
|
})
|
||||||
|
& ^[-2..-2]{
|
||||||
|
foreach(modifier.elements, @(element){
|
||||||
|
render_element(element)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stashing the given block under the given
|
||||||
|
* name to be aliased by a late level
|
||||||
|
* (See generate_aliases)
|
||||||
|
*/
|
||||||
|
RV-Element--name(name)
|
||||||
|
push(_block.alias.stash.RV-Element, {
|
||||||
|
name: name
|
||||||
|
block: block
|
||||||
|
})
|
||||||
|
|
||||||
|
RV-Element__Modifier--name(name)
|
||||||
|
push(_block.alias.stash.RV-Element__Modifier, {
|
||||||
|
name: name
|
||||||
|
block: block
|
||||||
|
})
|
||||||
|
|
||||||
|
RV-Block__Modifier--name(name)
|
||||||
|
push(_block.alias.stash.RV-Block__Modifier, {
|
||||||
|
name: name
|
||||||
|
block: block
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
RV-Block(block_name)
|
||||||
|
& .{block_name}
|
||||||
|
{block}
|
||||||
|
foreach(_block.block_modifiers, @(modifier){
|
||||||
|
render_block_modifier(modifier)
|
||||||
|
})
|
||||||
|
foreach(_block.elements, @(element){
|
||||||
|
render_element(element)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
RV-Block__Modifier(modifier_name=null)
|
||||||
|
modifier_name = resolve_alias(modifier_name)
|
||||||
|
blocks = generate_aliases(modifier_name)
|
||||||
|
modifier_name = blocks.name
|
||||||
|
blocks = blocks.blocks
|
||||||
|
push(blocks, block)
|
||||||
|
|
||||||
|
modifier = {
|
||||||
|
name: modifier_name
|
||||||
|
blocks: blocks
|
||||||
|
elements: _block.element_stash
|
||||||
|
}
|
||||||
|
_block.element_stash = create_list()
|
||||||
|
|
||||||
|
push(_block.block_modifiers, modifier)
|
||||||
|
|
||||||
|
RV-Element(element_name=null)
|
||||||
|
element_name = resolve_alias(element_name)
|
||||||
|
blocks = generate_aliases(element_name)
|
||||||
|
|
||||||
|
element_name = blocks.name
|
||||||
|
blocks = blocks.blocks
|
||||||
|
push(blocks, block)
|
||||||
|
|
||||||
|
element = {
|
||||||
|
name: element_name
|
||||||
|
blocks: blocks
|
||||||
|
modifiers: _block.modifier_stash
|
||||||
|
}
|
||||||
|
_block.modifier_stash = create_list()
|
||||||
|
|
||||||
|
if is_direct_descendant_of_block()
|
||||||
|
push(_block.elements, element)
|
||||||
|
else
|
||||||
|
push(_block.element_stash, element)
|
||||||
|
|
||||||
|
|
||||||
|
RV-Element__Modifier(modifier_name=null)
|
||||||
|
modifier_name = resolve_alias(modifier_name)
|
||||||
|
blocks = generate_aliases(modifier_name)
|
||||||
|
modifier_name = blocks.name
|
||||||
|
blocks = blocks.blocks
|
||||||
|
push(blocks, block)
|
||||||
|
|
||||||
|
modifier = {
|
||||||
|
name: modifier_name
|
||||||
|
blocks: blocks
|
||||||
|
}
|
||||||
|
push(_block.modifier_stash, modifier)
|
@ -1,135 +0,0 @@
|
|||||||
_block = {
|
|
||||||
stack: {}
|
|
||||||
elements: {}
|
|
||||||
block_modifiers: {}
|
|
||||||
|
|
||||||
element_stack: () ()
|
|
||||||
element_modifier_stack: () ()
|
|
||||||
block_modifier_stack: () ()
|
|
||||||
|
|
||||||
current_elements: () ()
|
|
||||||
current_element_modifiers: () ()
|
|
||||||
current_block_modifiers: () ()
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_block()
|
|
||||||
_block.stack = {}
|
|
||||||
_block.elements = {}
|
|
||||||
_block.block_modifiers = {}
|
|
||||||
|
|
||||||
_block.element_stack = {}
|
|
||||||
_block.element_modifier_stack = {}
|
|
||||||
_block.block_modifier_stack = {}
|
|
||||||
|
|
||||||
_block.current_elements = () ()
|
|
||||||
_block.current_element_modifiers = () ()
|
|
||||||
_block.current_block_modifiers = () ()
|
|
||||||
|
|
||||||
|
|
||||||
_include = {
|
|
||||||
elements: {}
|
|
||||||
element_modifires: {}
|
|
||||||
block_modifiers: {}
|
|
||||||
|
|
||||||
element_stack: {}
|
|
||||||
element_modifier_stack: {}
|
|
||||||
block_modifier_stack: {}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_include()
|
|
||||||
_aliases.element_aliases = {}
|
|
||||||
_aliases.element_modifires_aliases = {}
|
|
||||||
_aliases.block_modifiers_aliases = {}
|
|
||||||
|
|
||||||
_aliases.element_alias_stack = {}
|
|
||||||
_aliases.element_modifires_alias_stack = {}
|
|
||||||
_aliases.block_modifiers_alias_stack = {}
|
|
||||||
|
|
||||||
_block_map = {}
|
|
||||||
|
|
||||||
RV-Include(block_name, alias = null)
|
|
||||||
|
|
||||||
|
|
||||||
RV-Squash()
|
|
||||||
{block}
|
|
||||||
|
|
||||||
RV-Block(block_name)
|
|
||||||
{block}
|
|
||||||
|
|
||||||
push(_block.elements, _block.current_elements)
|
|
||||||
push(_block.block_modifiers, _block.current_block_modifiers)
|
|
||||||
|
|
||||||
_block_map[block_name] = _block
|
|
||||||
|
|
||||||
reset_block()
|
|
||||||
|
|
||||||
|
|
||||||
RV-Element(element_name)
|
|
||||||
if 'RV-Include' in called-from
|
|
||||||
if 'RV-Element' in called-from
|
|
||||||
push(_include.element_stack, element_name)
|
|
||||||
else
|
|
||||||
for alias in _include.element_stack
|
|
||||||
_include.elements[alias] = element_name
|
|
||||||
_include.elements[element_name] = element_name
|
|
||||||
|
|
||||||
if 'RV-Element' in called-from
|
|
||||||
push(_state.element_stack, block)
|
|
||||||
else
|
|
||||||
element = {
|
|
||||||
type: 'RV-Element'
|
|
||||||
name: element_name
|
|
||||||
blocks: (block)
|
|
||||||
modifiers: _block.current_element_modifiers
|
|
||||||
}
|
|
||||||
_block.current_element_modifiers = () ()
|
|
||||||
|
|
||||||
for child in _block.element_stack
|
|
||||||
if child != ()
|
|
||||||
push(element.blocks, child)
|
|
||||||
_block.element_stack = () ()
|
|
||||||
|
|
||||||
if 'RV-Block__Modifier' in called-from
|
|
||||||
push(_block.current_elements, element)
|
|
||||||
else
|
|
||||||
_block.elements[elemante_name] = element
|
|
||||||
|
|
||||||
|
|
||||||
RV-Element__Modifier(modifier_name)
|
|
||||||
if 'RV-Element__Modifier' in called-from
|
|
||||||
push(_state.element_modifier_stack, block)
|
|
||||||
else
|
|
||||||
modifier = {
|
|
||||||
type: 'RV-Element__Modifier'
|
|
||||||
name: modifier_name
|
|
||||||
blocks: (block)
|
|
||||||
}
|
|
||||||
|
|
||||||
for child in _block.element_modifier_stack
|
|
||||||
if child != ()
|
|
||||||
push(modifier.blocks, child)
|
|
||||||
_block.element_modifier_stack = () ()
|
|
||||||
|
|
||||||
push(_block.current_element_modifiers, modifier)
|
|
||||||
|
|
||||||
RV-Block__Modifier(modifier_name)
|
|
||||||
if 'RV-Block__Modifier' in called-from
|
|
||||||
push(_block.block_modifier_stack, block)
|
|
||||||
else
|
|
||||||
modifier = {
|
|
||||||
type: 'RV-Block__Modifier'
|
|
||||||
name: modifier_name
|
|
||||||
blocks: (block)
|
|
||||||
elements: _block.current_elements
|
|
||||||
}
|
|
||||||
_block.current_elements = () ()
|
|
||||||
|
|
||||||
for child in _block.block_modifier_stack
|
|
||||||
if child != ()
|
|
||||||
push(modifier.blocks, child)
|
|
||||||
_block.block_modifier_stack = () ()
|
|
||||||
|
|
||||||
_block.block_modifiers[modifier_name] = modifier
|
|
Loading…
Reference in New Issue
Block a user