// 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 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 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] 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} RV-Block__Modifier--name(name) if 'RV-Squash' in called-from {block} else if 'RV-Block__Modifier' in called-from push(_block.alias.stash.RV-Block__Modifier, { name: name block: block }) else {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) 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) 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 } _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)