Mixin name based bem generator

This commit is contained in:
reverend 2021-03-19 12:00:07 +01:00
parent 3b03410b3c
commit 00f69e67c7
1 changed files with 122 additions and 106 deletions

View File

@ -1,8 +1,11 @@
_bem_context = { _bem_context = {
_alias_map: {} _alias_map: {}
_alias_stacks: { _alias_stacks: {
} },
known_names: {}
} }
//bem_debug = false !default
work_stack(stack, callback) work_stack(stack, callback)
while length(stack) > 0 while length(stack) > 0
@ -36,8 +39,9 @@ pop_last_alias()
return null return null
return pop(_bem_context._alias_stacks[level_name]) return pop(_bem_context._alias_stacks[level_name])
apply_alias_stack(name) apply_alias_stack(name, level_name=null)
level_name = called-from[1] if level_name == null
level_name = called-from[1]
if level_name in _bem_context._alias_stacks if level_name in _bem_context._alias_stacks
work_stack(_bem_context._alias_stacks[level_name], @(element){ work_stack(_bem_context._alias_stacks[level_name], @(element){
set_alias(element, name) set_alias(element, name)
@ -45,16 +49,10 @@ apply_alias_stack(name)
auto_name(delimiter) auto_name(delimiter, caller)
if length(called-from) < 3
return null
block_name = called-from[2]
if delimiter == null if delimiter == null
return block_name return caller
name = split(delimiter, block_name)[-1] return split(delimiter, caller)[-1]
if name in ('RV-Element' 'RV-Block' 'RV-Block--shorthand' 'RV-Element--modifier' 'RV-Block--modifier' 'RV-Generate')
return null
return name
is_nested(mixin_name=null) is_nested(mixin_name=null)
_free_hits = 0 _free_hits = 0
@ -71,8 +69,13 @@ is_nested(mixin_name=null)
_free_hits = _free_hits - 1 _free_hits = _free_hits - 1
return false return false
is_nested_in(parent_name) is_nested_in(parent_list=null)
return parent_name in called-from 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) not_nested_in(parent_name)
return !(parent_name in called-from) return !(parent_name in called-from)
@ -85,94 +88,130 @@ is_any_parent_nested()
return true return true
return false return false
RV-Level(name_delimiter, allowed_parent_levels=null, selector_callback, squash_if_parent_nested=false) string_contains(smaller, greater)
name = auto_name(name_delimiter) if smaller == null || greater == null
not_in_parent = true return true
for parent_level in allowed_parent_levels
not_in_parent = not_in_parent && not_nested_in(parent_level) if length(smaller) > length(greater)
if not_in_parent //|| is_nested_in('RV-Squash') return false
{block}
else if is_nested() for i in range(0, length(smaller) - 1)
store_alias(name) //p(i substr(smaller, i, 1) substr(greater, i, 1))
{block} if substr(smaller, i, 1) != substr(greater, i, 1)
else 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 if name == null
name = pop_last_alias() name = pop_last_alias()
name = lookup_alias(name) name = lookup_alias(name)
apply_alias_stack(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() if cindex != -1 && nested_in_super_parents && !(name in _bem_context.known_names)
{block} return
else else
selector_name = selector_callback(name) _bem_context.known_names[name] = name
if name == ''
selector_name = split(name_delimiter, selector_name)[0] define('current_selector', selector_name, true)
{selector_name} {selector_name}
{block} {block}
if bem_debug
// RV-Fan--horizontal RV-Fan--horizontal __ Base -- wurst --mixin_name mixin_name
// RV-BreakPoint__Item--outside RV-Fan--horizontal__Base RV-Fan--horizontal --name name
else if cindex <= 0
RV-Block(name) store_alias(name)
.{name}
{block} {block}
if bem_debug
_bem_context._alias_map = {} --mixin_name mixin_name
_bem_context._alias_stacks = {} --name name
RV-Generate() RV-Block(name=null)
{block} +RV-Level(null, @(name){
_bem_context._alias_map = {}
_bem_context._alias_stacks = {}
RV-Block()
+RV-Level(null, ('RV-Generate'), @(name){
define('current_block', name, true)
return '.'+name return '.'+name
}) }, name)
{block} {block}
_bem_context._alias_map = {}
_bem_context._alias_stacks = {}
_bem_context.known_names = {}
RV-Block--shorthand(name) RV-Block--shorthand(name)
+RV-Block(name) +RV-Block(name)
{block} {block}
RV-Element() RV-Element(name=null)
+RV-Level('__', ('RV-Generate' 'RV-Block--modifier'), @(name){ +RV-Level('__', @(name){
return '& .' + current_block +'__' + name return '& ^[0]__'+name
}) }, name)
{block} {block}
RV-Element--modifier() RV-Element--modifier(name=null)
+RV-Level('--', ('RV-Element'), @(name){return '&--' + name}, true) +RV-Level('--', @(name){
return '&--'+name
}, name, ('RV-Block--modifier'))
{block} {block}
RV-Block--modifier() RV-Block--modifier(name=null)
+RV-Level('--', ('RV-Generate' 'RV-Block--shorthand'), @(name){ +RV-Level('--', @(name){
'.' + current_block +'--' + name return '&--'+name
}, true) }, name)
if is_nested_in('RV-Block--shorthand') && length(called-from) > 0
mixin_name = split('--', called-from[0])[0]
convert(unquote(mixin_name)+'()')
{block} {block}
RV-Squash() RV-Squash()
{block} {block}
filter(list, value)
filtered = ()
for element in list
if element != value
push(filtered, element)
return filtered
_level_types = { _level_types = {
'': 'block' '': {
'__': 'element' name: 'block',
'--': 'modifier' 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) get_first_level_name(mixin_name)
@ -185,32 +224,9 @@ get_first_level_name(mixin_name)
return shortest_split return shortest_split
string_contains(smaller, greater) generate_selector(mixin_name)
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)
candidate = null candidate = null
candidate_level = null candidate_level = null
candidate_delimiter = null
// This is why humanity is doomed // This is why humanity is doomed
mixin_name = split('äöü', mixin_name)[0] mixin_name = split('äöü', mixin_name)[0]
@ -222,20 +238,20 @@ determine_level_type(mixin_name)
if candidate == null || length(candidate) > length(splited_level) if candidate == null || length(candidate) > length(splited_level)
candidate = splited_level candidate = splited_level
candidate_level = 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) //generate_selector(mixin_name)
block_name = get_first_level_name(mixin_name) // block_name = get_first_level_name(mixin_name)
level_info = determine_level_type(mixin_name) // level_info = determine_level_type(mixin_name)
return '&%s%s' % (level_info[2] level_info[0]) // return '&%s%s' % (level_info[2] level_info[0])
RV-BEM() RV-BEM()
call_stack = filter(called-from, 'RV-BEM') call_stack = split(' ', ''+called-from)
p(cs call_stack)
if is_contigious(call_stack) if is_contigious(call_stack)
{generate_selector(called-from[0])} {generate_selector(call_stack[0])}
{block} {block}
p('###') else
{block}