_bem_context = { _alias_map: {} _alias_stacks: { }, known_names: {} } bem_debug = false work_stack(stack, callback) while length(stack) > 0 entry = pop(stack) if entry != () callback(entry) set_alias(alias, name) if name != null && alias != null _bem_context._alias_map[alias] = name lookup_alias(name) if name in _bem_context._alias_map return _bem_context._alias_map[name] else return name store_alias(alias) level_name = called-from[1] if not level_name in _bem_context._alias_stacks _bem_context._alias_stacks[level_name] = () () if alias != null push(_bem_context._alias_stacks[level_name], alias) pop_last_alias() level_name = called-from[1] if not level_name in _bem_context._alias_stacks return null return pop(_bem_context._alias_stacks[level_name]) apply_alias_stack(name, level_name=null) if level_name == null level_name = called-from[1] if level_name in _bem_context._alias_stacks work_stack(_bem_context._alias_stacks[level_name], @(element){ set_alias(element, name) }) auto_name(delimiter, caller) if delimiter == null return caller return split(delimiter, caller)[-1] 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_list=null) if parent_list == null return false for parent in parent_list if parent in called-from return true return false not_nested_in(parent_name) return !(parent_name in called-from) is_any_parent_nested() //RV-Level RV-Element--modifier RV-Element RV-Block--modifier RV-BreakPoint--horizontal RV-Block--modifier RV-Fan--horizontal RV-Block for i in (length(called-from)...0) i = i - 1 if i != index(called-from, called-from[i]) return true return false string_contains(smaller, greater) if smaller == null || greater == null return true if length(smaller) > length(greater) return false for i in range(0, length(smaller) - 1) //p(i substr(smaller, i, 1) substr(greater, i, 1)) if substr(smaller, i, 1) != substr(greater, i, 1) return false return true contigious_index(call_stack) for i in range(0, length(call_stack) - 1) if !string_contains(call_stack[i+1], call_stack[i]) return i return -1 filter(list, value_list) filtered = () for element in list if not (element in value_list) push(filtered, element) return filtered RV-Level(name_delimiter, selector_callback, name=null) call_stack = split(' ', ''+called-from) call_stack = filter(call_stack, ('RV-Level' 'RV-Block' 'RV-Block--modifier' 'RV-Element' 'RV-Element--modifier' 'RV-Modifier')) mixin_name = call_stack[0] if name == null name = auto_name(name_delimiter, mixin_name) cindex = contigious_index(call_stack) if bem_debug --attempt mixin_name --cindex cindex --nested_in_super_parents nested_in_super_parents // TODO Clear up this logic if cindex != 0 if name == null name = pop_last_alias() name = lookup_alias(name) apply_alias_stack(name) selector_name = selector_callback(name) if name == '' selector_name = split(name_delimiter, selector_name)[0] if cindex > 0 && !(name in _bem_context.known_names) return else _bem_context.known_names[name] = name define('current_selector', selector_name, true) {selector_name} {block} if bem_debug --mixin_name mixin_name --name name else store_alias(name) {block} if bem_debug --mixin_name mixin_name --name name RV-Block(name=null) +RV-Level(null, @(name){ return '.'+name }, name) {block} if not is_nested('RV-Block') _bem_context._alias_map = {} _bem_context._alias_stacks = {} _bem_context.known_names = {} RV-Block--shorthand(name) +RV-Block(name) {block} RV-Element(name=null) +RV-Level('__', @(name){ return '& ^[0]__'+name }, name) {block} RV-Element--modifier(name=null) +RV-Level('--', @(name){ return '&--'+name }, name) {block} RV-Block--modifier(name=null) +RV-Level('--', @(name){ return '&--'+name }, name) {block}