/* * 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 */ _css-prefix = 'RV' _global_scope = { _selector_blocks_to_generate: {} _element-modifier: () _additional-element-modifier-blocks: () _last_element_name: null _blocks_to_generate: () _element_modifier_block_stack: () _element_block_stack: () _element_modifier_stack: {} } _block_building_lane = () _element_building_lange = () _work_lane(lane, callback) l = length(lane) for _ in (0..l) piece = pop(lane) callback(piece) /* * Gets the selector of the parent class */ _get_parent_selector() return split(' ', selector())[-1] /* * Gets the selector of the current block */ _get_block_selector() return unquote(split('__', _get_parent_selector())[0]) _get_element_selector() element--modifier = split('__', _get_parent_selector())[1] return unquote(split('--', element--modifier)[0]) /* * Generates a CSS class for an * Block according to BEM */ RV-Block(name) .{name} {block} for element_name, element in _global_scope['_selector_blocks_to_generate'] & .{name}__{element_name} for current_block in element.block_list {current_block} for modifier_name, modifier_block_list in element.modifier_list &--{modifier_name} for current_block in modifier_block_list {current_block} /* * Generates a CSS class for an block modifier * according to BEM. */ RV-Block__Modifier(name) if 'RV-Block__Modifier' in called-from {block} else &{_get_block_selector()}--{name} {block} /* * Generates an CSS class for an element * according to BEM. Also minds the element modifiers * For more see RV-Element___Modifier */ RV-Element(name) push(_global_scope['_element_block_stack'], block) current_block = _block_building_lane[-1] //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 element = {} element['block_list'] = _global_scope['_element_block_stack'] element['modifier_list'] = _global_scope['_element_modifier_stack'] //Reseting _global_scope['_element_block_stack'] = () _global_scope['_element_modifier_stack'] = {} //Saving element _global_scope['_selector_blocks_to_generate'][name] = element _global_scope['_last_element_name'] = name /* * 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(name) counter = 0 for fn in called-from if fn is 'RV-Element' counter += 1 if counter <= 1 element_modifier_block_stack = _global_scope['_element_modifier_block_stack'] append(element_modifier_block_stack, block) _global_scope['_element_modifier_block_stack'] = element_modifier_block_stack //Is this modifier beeing included by another modifier if not 'RV-Element__Modifier' in called-from //No //Is this modifier beeing called in in- or postfix if not 'RV-Element' in called-from //Yes last_element_name = _global_scope['_last_element_name'] //Accesing the last generated element and appending the modifier element = _global_scope['_selector_blocks_to_generate'][last_element_name] modifier_list = element['modifier_list'] modifier_list[name] = _global_scope['_element_modifier_block_stack'] element['modifier_list'] = modifier_list _global_scope['_selector_blocks_to_generate'][last_element_name] = element else //No _global_scope['_element_modifier_stack'][name] = _global_scope['_element_modifier_block_stack'] _global_scope['_element_modifier_block_stack'] = ()