From 00f69e67c74c8f5a4e42b10186b33d358432bfb4 Mon Sep 17 00:00:00 2001 From: reverend Date: Fri, 19 Mar 2021 12:00:07 +0100 Subject: [PATCH] Mixin name based bem generator --- components/00_Tools/_bemGenerator.styl | 228 +++++++++++++------------ 1 file changed, 122 insertions(+), 106 deletions(-) diff --git a/components/00_Tools/_bemGenerator.styl b/components/00_Tools/_bemGenerator.styl index c8e29ec..1d3baae 100644 --- a/components/00_Tools/_bemGenerator.styl +++ b/components/00_Tools/_bemGenerator.styl @@ -1,8 +1,11 @@ _bem_context = { _alias_map: {} _alias_stacks: { - } + }, + known_names: {} } + +//bem_debug = false !default work_stack(stack, callback) while length(stack) > 0 @@ -36,8 +39,9 @@ pop_last_alias() return null return pop(_bem_context._alias_stacks[level_name]) -apply_alias_stack(name) - level_name = called-from[1] +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) @@ -45,16 +49,10 @@ apply_alias_stack(name) -auto_name(delimiter) - if length(called-from) < 3 - return null - block_name = called-from[2] +auto_name(delimiter, caller) if delimiter == null - return block_name - name = split(delimiter, block_name)[-1] - if name in ('RV-Element' 'RV-Block' 'RV-Block--shorthand' 'RV-Element--modifier' 'RV-Block--modifier' 'RV-Generate') - return null - return name + return caller + return split(delimiter, caller)[-1] is_nested(mixin_name=null) _free_hits = 0 @@ -71,8 +69,13 @@ is_nested(mixin_name=null) _free_hits = _free_hits - 1 return false -is_nested_in(parent_name) - return parent_name in called-from +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) @@ -85,94 +88,130 @@ is_any_parent_nested() return true return false -RV-Level(name_delimiter, allowed_parent_levels=null, selector_callback, squash_if_parent_nested=false) - 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 not_in_parent //|| is_nested_in('RV-Squash') - {block} - else if is_nested() - store_alias(name) - {block} - else +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, super_parents=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) + nested_in_super_parents = is_nested_in(super_parents) + + if bem_debug + --attempt mixin_name + --cindex cindex + --nested_in_super_parents nested_in_super_parents + + // TODO Clear up this logic + if cindex == -1 || nested_in_super_parents 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 squash_if_parent_nested && is_any_parent_nested() - {block} + if cindex != -1 && nested_in_super_parents && !(name in _bem_context.known_names) + return else - selector_name = selector_callback(name) - if name == '' - selector_name = split(name_delimiter, selector_name)[0] + _bem_context.known_names[name] = name + + define('current_selector', selector_name, true) {selector_name} {block} - -// RV-Fan--horizontal RV-Fan--horizontal __ Base -- wurst -// RV-BreakPoint__Item--outside RV-Fan--horizontal__Base RV-Fan--horizontal - -RV-Block(name) - .{name} + if bem_debug + --mixin_name mixin_name + --name name + else if cindex <= 0 + store_alias(name) {block} - - _bem_context._alias_map = {} - _bem_context._alias_stacks = {} + if bem_debug + --mixin_name mixin_name + --name name -RV-Generate() - {block} - - _bem_context._alias_map = {} - _bem_context._alias_stacks = {} - -RV-Block() - +RV-Level(null, ('RV-Generate'), @(name){ - define('current_block', name, true) +RV-Block(name=null) + +RV-Level(null, @(name){ return '.'+name - }) + }, name) {block} + _bem_context._alias_map = {} + _bem_context._alias_stacks = {} + _bem_context.known_names = {} + + RV-Block--shorthand(name) +RV-Block(name) {block} -RV-Element() - +RV-Level('__', ('RV-Generate' 'RV-Block--modifier'), @(name){ - return '& .' + current_block +'__' + name - }) +RV-Element(name=null) + +RV-Level('__', @(name){ + return '& ^[0]__'+name + }, name) {block} -RV-Element--modifier() - +RV-Level('--', ('RV-Element'), @(name){return '&--' + name}, true) +RV-Element--modifier(name=null) + +RV-Level('--', @(name){ + return '&--'+name + }, name, ('RV-Block--modifier')) {block} -RV-Block--modifier() - +RV-Level('--', ('RV-Generate' 'RV-Block--shorthand'), @(name){ - '.' + current_block +'--' + name - }, true) - if is_nested_in('RV-Block--shorthand') && length(called-from) > 0 - mixin_name = split('--', called-from[0])[0] - convert(unquote(mixin_name)+'()') +RV-Block--modifier(name=null) + +RV-Level('--', @(name){ + return '&--'+name + }, name) {block} RV-Squash() {block} -filter(list, value) - filtered = () - for element in list - if element != value - push(filtered, element) - return filtered - _level_types = { - '': 'block' - '__': 'element' - '--': 'modifier' + '': { + name: 'block', + selector: @(mixin_name, level_name){return '.'+level_name} + }, + '__': { + name: 'element', + selector: @(mixin_name, level_name){return '&__'+level_name} + }, + '--': { + name: 'modifier', + selector: @(mixin_name, level_name){return '&--'+level_name} + }, } get_first_level_name(mixin_name) @@ -185,32 +224,9 @@ get_first_level_name(mixin_name) return shortest_split -string_contains(smaller, greater) - if smaller == null || greater == null - return false - - if length(smaller) > length(greater) - return false - - p('%s'%smaller length('%s'%smaller)) - - for i in range(0, length(smaller)) - if smaller[i] != greater[i] - return false - return true - -is_contigious(call_stack) - for i in range(0, length(call_stack) - 1) - p(call_stack[i+1] call_stack[i]) - p(string_contains(call_stack[i+1], call_stack[i])) - if !call_stack[i+1] in call_stack[i] - return false - return true - -determine_level_type(mixin_name) +generate_selector(mixin_name) candidate = null candidate_level = null - candidate_delimiter = null // This is why humanity is doomed mixin_name = split('äöü', mixin_name)[0] @@ -222,20 +238,20 @@ determine_level_type(mixin_name) if candidate == null || length(candidate) > length(splited_level) candidate = splited_level candidate_level = level - candidate_delimiter = delimiter - return unquote(candidate) candidate_level unquote(candidate_delimiter) + fn = candidate_level.selector + return fn(mixin_name, candidate) -generate_selector(mixin_name) - block_name = get_first_level_name(mixin_name) - level_info = determine_level_type(mixin_name) - return '&%s%s' % (level_info[2] level_info[0]) +//generate_selector(mixin_name) +// block_name = get_first_level_name(mixin_name) +// level_info = determine_level_type(mixin_name) +// return '&%s%s' % (level_info[2] level_info[0]) RV-BEM() - call_stack = filter(called-from, 'RV-BEM') - p(cs call_stack) + call_stack = split(' ', ''+called-from) if is_contigious(call_stack) - {generate_selector(called-from[0])} + {generate_selector(call_stack[0])} {block} - p('###') \ No newline at end of file + else + {block} \ No newline at end of file