From 08e20dfcb361406bf26a44dc6c0c05a7d14362b0 Mon Sep 17 00:00:00 2001 From: reverend Date: Sun, 17 Jan 2021 15:57:17 +0100 Subject: [PATCH] Finaly a Tool to generate reusable BEM --- components/00_Global/_bemGenerator.styl | 332 ++++++++++++++---------- components/00_Global/_mebgenerator.styl | 135 ---------- 2 files changed, 192 insertions(+), 275 deletions(-) delete mode 100644 components/00_Global/_mebgenerator.styl diff --git a/components/00_Global/_bemGenerator.styl b/components/00_Global/_bemGenerator.styl index a0c76cf..f86399a 100644 --- a/components/00_Global/_bemGenerator.styl +++ b/components/00_Global/_bemGenerator.styl @@ -1,151 +1,203 @@ +// Storing the currents block properties and attributes +// to generate the block afterwards /* - * This is set of mixins to help generating - * CSS classes according to the Block__Element--Modifier pattern. - * It also helps nesting those classes in any fashion imaganible - * and still produces clean BEM CSS + * A method for iterating throug a + * list/array safely since this language sucks + * realy bad https://github.com/stylus/stylus/issues/1440 */ -@import './_laneHandling' +foreach(list, callback) + for entry in list + if entry != () + callback(entry) -_css-prefix = 'RV' +create_list() + return () () - -/* - * Generates a CSS class for an - * Block according to BEM - */ -RV-Block(block_name) - _pop_lane('element_aliases') - b = @block{ - {block} - & .{block_name}{ - for element_block in _pop_stack('elements_to_generate'){ - {element_block} - } +_block = {} +reset_block() + _block.elements = create_list() + _block.block_modifiers = create_list() + _block.alias = { + map: {} + stash: { + RV-Element: create_list() + RV-Element__Modifier: create_list() + RV-Block__Modifier: create_list() } - - &.{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 - {b} - 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) + if block_index <= 0 + return true - //Detect if the selector will be generated - //by an earlier call of RV-Block__Modifier - if not 'RV-Block__Modifier' in called-from - // Saving accumulated modifiers and blocks - 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') + for i in (1..block_index) + if called-from[i] in _bem_mixins + return false + return true - -/* - * Generates an CSS class for an element - * according to BEM. Also minds the element modifiers - * For more see RV-Element___Modifier +/* + * Taking the currently stashed names, mapping + * them to the given name under the called parent + * (using called-from) and returning the stashed blocks */ -RV-Element(element_name) - _push_onto_stack(block) - - //Detect if the selector will be generated - //by an earlier call of RV-Element - 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') +generate_aliases(actual_name) + level_type = split(' ', called-from)[0] + if actual_name == null + if length(_block.alias.stash[level_type]) > 2 + actual_name = _block.alias.stash[level_type][-1].name else - //Postfix, append to existing element - last_element_name = _get_last_name('RV-Element') - modifier_block = @block { - & .{block_name}__{last_element_name}.{block_name}__{last_element_name}--{element_modifier_name}{ - for current_block in _pop_stack(){ - {current_block} - } - } - } - _push_onto_stack(modifier_block, 'after_element_modifiers_to_generate') - \ No newline at end of file + warn('No name found for '+called-from) + + blocks = () + foreach(_block.alias.stash[level_type], @(alias){ + _block.alias.map[level_type+':'+alias.name] = actual_name + push(blocks, alias.block) + }) + + _block.alias.stash[level_type] = create_list() + 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) \ No newline at end of file diff --git a/components/00_Global/_mebgenerator.styl b/components/00_Global/_mebgenerator.styl deleted file mode 100644 index 212b1b4..0000000 --- a/components/00_Global/_mebgenerator.styl +++ /dev/null @@ -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