New bemGenerator
This commit is contained in:
		@@ -1,249 +1,115 @@
 | 
			
		||||
// 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
 | 
			
		||||
_alias_map = {}
 | 
			
		||||
_alias_stack = () ()
 | 
			
		||||
			
 | 
			
		||||
work_stack(stack, callback)
 | 
			
		||||
	while length(stack) > 0
 | 
			
		||||
		entry = pop(_alias_stack)
 | 
			
		||||
		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
 | 
			
		||||
set_alias(alias, name)
 | 
			
		||||
	if name != null && alias != null
 | 
			
		||||
		_alias_map[alias] = name
 | 
			
		||||
	
 | 
			
		||||
	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]
 | 
			
		||||
lookup_alias(name)
 | 
			
		||||
	if not _alias_map
 | 
			
		||||
		return name
 | 
			
		||||
	if name in _alias_map
 | 
			
		||||
		return _alias_map[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}
 | 
			
		||||
store_alias(alias)
 | 
			
		||||
	if alias != null
 | 
			
		||||
		push(_alias_stack, alias)
 | 
			
		||||
	
 | 
			
		||||
RV-Block__Modifier--name(name)
 | 
			
		||||
	if 'RV-Squash' in called-from
 | 
			
		||||
pop_last_alias()
 | 
			
		||||
	return pop(_alias_stack)
 | 
			
		||||
	
 | 
			
		||||
apply_alias_stack(name)
 | 
			
		||||
	work_stack(_alias_stack, @(element){
 | 
			
		||||
		set_alias(element, name)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
auto_name(delimiter)
 | 
			
		||||
	if length(called-from) < 3
 | 
			
		||||
		return null
 | 
			
		||||
	name = split(delimiter, called-from[2])[-1]
 | 
			
		||||
	if name in ('RV-Element' 'RV-Block' 'RV-Element--modifier' 'RV-Block--modifier')
 | 
			
		||||
		return null
 | 
			
		||||
	return name
 | 
			
		||||
 | 
			
		||||
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_name)
 | 
			
		||||
	return parent_name in called-from
 | 
			
		||||
	
 | 
			
		||||
not_nested_in(parent_name)
 | 
			
		||||
	return !(parent_name in called-from)
 | 
			
		||||
 | 
			
		||||
RV-Level(name, name_delimiter, allowed_parent_levels, selector_callback)
 | 
			
		||||
	if name == null
 | 
			
		||||
		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 is_nested_in('RV-Squash') || not_in_parent
 | 
			
		||||
		{block}
 | 
			
		||||
	else if is_nested()
 | 
			
		||||
		store_alias(name)
 | 
			
		||||
		{block}
 | 
			
		||||
	else
 | 
			
		||||
		if 'RV-Block__Modifier' in called-from
 | 
			
		||||
			push(_block.alias.stash.RV-Block__Modifier, {
 | 
			
		||||
				name: name
 | 
			
		||||
				block: block
 | 
			
		||||
			})
 | 
			
		||||
		else
 | 
			
		||||
		if name == null
 | 
			
		||||
			name = pop_last_alias()
 | 
			
		||||
		name = lookup_alias(name)
 | 
			
		||||
		apply_alias_stack(name)
 | 
			
		||||
		
 | 
			
		||||
		{selector_callback(name)}
 | 
			
		||||
			{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)
 | 
			
		||||
RV-Block(name)
 | 
			
		||||
	.{name}
 | 
			
		||||
		+prefix-classes(name)
 | 
			
		||||
			{block}
 | 
			
		||||
			
 | 
			
		||||
	define('_alias_map', {}, true)
 | 
			
		||||
	define('_alias_stack', () (), true)
 | 
			
		||||
		
 | 
			
		||||
		modifier = {
 | 
			
		||||
			name: modifier_name
 | 
			
		||||
			blocks: blocks
 | 
			
		||||
			elements: _block.element_stash
 | 
			
		||||
RV-Element(name=null)
 | 
			
		||||
	+RV-Level(name, '__', ('RV-Block' 'RV-Block--modifier'), @(name){
 | 
			
		||||
		if is_nested_in('RV-Block--modifier') {
 | 
			
		||||
			return '& .__' + name
 | 
			
		||||
		}
 | 
			
		||||
		_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
 | 
			
		||||
		else {
 | 
			
		||||
			return '&__' + name
 | 
			
		||||
		}
 | 
			
		||||
		_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)
 | 
			
		||||
		
 | 
			
		||||
RV-Element--modifier(name=null)
 | 
			
		||||
	+RV-Level(name, '--', ('RV-Element'), @(name){return '&--' + name})
 | 
			
		||||
		{block}
 | 
			
		||||
		
 | 
			
		||||
RV-Block--modifier(name=null)
 | 
			
		||||
	+RV-Level(name, '--', ('RV-Block'), @(name){return '&--' + name})
 | 
			
		||||
		{block}
 | 
			
		||||
		
 | 
			
		||||
RV-Squash()
 | 
			
		||||
	{block}
 | 
			
		||||
		Reference in New Issue
	
	Block a user