diff --git a/components/00_Tools/_bemGenerator.styl b/components/00_Tools/_bemGenerator.styl index 1ac96e7..1990cd1 100644 --- a/components/00_Tools/_bemGenerator.styl +++ b/components/00_Tools/_bemGenerator.styl @@ -1,249 +1,115 @@ -// Storing the currents block properties and attributes -// to generate the block afterwards -/* - * A method for iterating throug a - * list/array safely since this language sucks - * realy bad https://github.com/stylus/stylus/issues/1440 - */ -foreach(list, callback) - for entry in list +_alias_map = {} +_alias_stack = () () + +work_stack(stack, callback) + while length(stack) > 0 + entry = pop(_alias_stack) if entry != () callback(entry) -create_list() - return () () - -_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.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 +set_alias(alias, name) + if name != null && alias != null + _alias_map[alias] = name - if block_index <= 0 - return true - - for i in (1..block_index) - if called-from[i] in _bem_mixins - return false - return true - -/* - * Checks if we are called inside a block - */ -is_in_block() - return 'RV-Block' in called-from - -/* - * Taking the currently stashed names, mapping - * them to the given name under the called parent - * (using called-from) and returning the stashed blocks - */ -generate_aliases(actual_name, level_type=null) - if level_type == null - 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 - 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=null) - if level_type == null - level_type = split(' ', called-from)[0] - - if level_type+':'+name in _block.alias.map - return _block.alias.map[level_type+':'+name] +lookup_alias(name) + if not _alias_map + return name + if name in _alias_map + return _alias_map[name] else return name -/* - * Renders an element modifier - */ -render_element_modifier(modifier) - &--{resolve_alias(modifier.name, 'RV-Element__Modifier')} - foreach(modifier.blocks, @(block){ - {block} - }) - -/* - * Renders an element - */ -render_element(element) - &__{resolve_alias(element.name, 'RV-Element')} - foreach(element.blocks, @(block){ - {block} - }) - foreach(element.modifiers, @(modifier){ - render_element_modifier(modifier) - }) - -/* - * Renders an block modifier, - */ -render_block_modifier(modifier) - &--{resolve_alias(modifier.name, 'RV-Block__Modifier')} - foreach(modifier.blocks, @(block){ - {block} - }) - & ^[-2..-2]{ - foreach(modifier.elements, @(element){ - render_element(element) - }) - } - - -RV-Squash() - {block} - -/* - * Stashing the given block under the given - * name to be aliased by a late level - * (See generate_aliases) - */ -RV-Element--name(name) - if 'RV-Squash' in called-from - {block} - else - if 'RV-Element' in called-from - push(_block.alias.stash.RV-Element, { - name: name - block: block - }) - else - {block} - -RV-Element__Modifier--name(name) - if 'RV-Squash' in called-from - {block} - else - if 'RV-Element__Modifier' in called-from - push(_block.alias.stash.RV-Element__Modifier, { - name: name - block: block - }) - else - {block} +store_alias(alias) + if alias != null + push(_alias_stack, alias) -RV-Block__Modifier--name(name) - if 'RV-Squash' in called-from +pop_last_alias() + return pop(_alias_stack) + +apply_alias_stack(name) + work_stack(_alias_stack, @(element){ + set_alias(element, name) + }) + +auto_name(delimiter) + if length(called-from) < 3 + return null + name = split(delimiter, called-from[2])[-1] + if name in ('RV-Element' 'RV-Block' 'RV-Element--modifier' 'RV-Block--modifier') + return null + return name + +is_nested(mixin_name=null) + _free_hits = 0 + if mixin_name == null + shift(called-from) + mixin_name = shift(called-from) + else + _free_hits = 1 + for parent in called-from + if parent == mixin_name + if _free_hits == 0 + return true + else + _free_hits = _free_hits - 1 + return false + +is_nested_in(parent_name) + return parent_name in called-from + +not_nested_in(parent_name) + return !(parent_name in called-from) + +RV-Level(name, name_delimiter, allowed_parent_levels, selector_callback) + if name == null + name = auto_name(name_delimiter) + not_in_parent = true + for parent_level in allowed_parent_levels + not_in_parent = not_in_parent && not_nested_in(parent_level) + + if is_nested_in('RV-Squash') || not_in_parent + {block} + else if is_nested() + store_alias(name) {block} else - if 'RV-Block__Modifier' in called-from - push(_block.alias.stash.RV-Block__Modifier, { - name: name - block: block - }) - else + if name == null + name = pop_last_alias() + name = lookup_alias(name) + apply_alias_stack(name) + + {selector_callback(name)} {block} -RV-Block(block_name) - & .{block_name} - foreach(_block.elements, @(element){ - render_element(element) - }) - foreach(_block.block_modifiers, @(modifier){ - render_block_modifier(modifier) - }) - {block} - - reset_block() - -RV-Block__Modifier(modifier_name=null) - if 'RV-Squash' in called-from - {block} - else - blocks = generate_aliases(modifier_name) - modifier_name = blocks.name - blocks = blocks.blocks - push(blocks, block) +RV-Block(name) + .{name} + +prefix-classes(name) + {block} + + define('_alias_map', {}, true) + define('_alias_stack', () (), true) - modifier = { - name: modifier_name - blocks: blocks - elements: _block.element_stash +RV-Element(name=null) + +RV-Level(name, '__', ('RV-Block' 'RV-Block--modifier'), @(name){ + if is_nested_in('RV-Block--modifier') { + return '& .__' + name } - _block.element_stash = create_list() - - push(_block.block_modifiers, modifier) - -RV-Element(element_name=null) - if 'RV-Squash' in called-from - {block} - else - 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 + else { + return '&__' + name } - _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) - if 'RV-Squash' in called-from + }) {block} - else - 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 + +RV-Element--modifier(name=null) + +RV-Level(name, '--', ('RV-Element'), @(name){return '&--' + name}) + {block} + +RV-Block--modifier(name=null) + +RV-Level(name, '--', ('RV-Block'), @(name){return '&--' + name}) + {block} + +RV-Squash() + {block} \ No newline at end of file