stylobate
Version:
Framework for writing really abstract CSS in Stylus
272 lines (219 loc) • 10.9 kB
text/stylus
$stylobate_options = {
'warn_on_incorrect_notation': true
}
$selector_regex = '&|^[\/\.]|ROOT|(^|[^\w])(__|-)\w'
$stylobate_extends = {}
$stylobate_extends_without_defaults = {}
stylobate_extends($what, $target, $defaults = true)
$stylobate_extends[''+utilus_ident($what)] = $target
if !$defaults
$stylobate_extends_without_defaults[''+utilus_ident($what)] = true
$stylobate_defaults = {}
stylobate_defaults($what, $defaults...)
$stylobate_defaults['' + utilus_ident($what)] = $defaults
stylobate_params($this, $params)
$collected_params = {
parent: {},
arguments: clone($params)
}
prepend($collected_params.arguments, unquote(''))
_stylobate_collect_arguments($collected_params)
$this['modifiers'] = merge($collected_params.modifiers, $this.modifiers)
$this['elements'] = merge($collected_params.elements, $this.elements)
return $collected_params
stylobate_this()
$this = {
'parent': {}
'arguments': ()
'params': {}
'modifiers': {}
'elements': {}
'urls': (),
'selector': selector(),
'selectors': ()
}
$null_collected = utilus_collect_by_type(())
for $key in ('strings' 'idents' 'units' 'rgbas' 'booleans' 'functions' 'objects' 'arrays' 'colors')
$this[$key] = $null_collected[$key]
return $this
_stylobate_apply_defaults($this, $defaults)
$origin = $this.called_from
return false if not $origin
$new_args = clone($defaults)
$newthis = clone($this)
$newthis['called_from'] = $origin + '_'
$newthis['defaulted'] = true
for $param, $index in $new_args
unless $param == null
$found_param = utilus_get($this['arguments'], utilus_ident($param[0]))
if $found_param or (type($found_param) == 'string' and $found_param == '')
$new_args[$index] = ''
for $param, $index in $this.arguments
$testparam = utilus_ident($param)
$testparam = '' unless type($param) in ('ident' 'string' 'function' 'literal')
unless match('^[-_]', $testparam)
push($new_args, $param)
$newthis['arguments'] = clone($new_args)
_stylobate('', $origin + '_', $newthis)
_stylobate_collect_arguments($this)
if length($this.parent)
$this['params'] = $this['parent']['params']
$this['modifiers'] = $this['parent']['modifiers']
$this['elements'] = $this['parent']['elements']
$this['urls'] = $this['parent']['urls']
$this['selectors'] = $this['parent']['selectors']
else
$this['params'] = {}
$this['modifiers'] = {}
$this['elements'] = {}
$this['urls'] = ()
$this['selectors'] = ()
// Remove the item's name from the arguments
$this['arguments'][0] = unquote('')
// Collect the arguments, first step
$collected = utilus_collect_by_type($this['arguments'])
for $key in ('strings' 'idents' 'units' 'rgbas' 'booleans' 'functions' 'objects' 'arrays' 'colors')
$this[$key] = $collected[$key]
// Getting different params and stuff
if length($this['strings']) > 0
for $key in $this['strings']
// replace those checks with functions
if match('\.(png|jpg|svg|gif)\b|https?:\/\/|^data:', $key)
push($this['urls'], $key)
else if match($selector_regex, $key)
push($this['selectors'], $key)
else if $key != ''
// workaround for strange clone? bug
$workaround = $this['params']
$workaround[$key] = $key
if length($this['idents']) > 0
for $key in $this['idents']
// workaround for strange clone? bug
$workaround = $this['params']
$workaround['' + utilus_ident($key)] = utilus_ident($key)
if match('^(__|-[^\-])', $key)
$workaround = $this['elements']
$workaround[replace('^([_-]+)', '', '' + utilus_ident($key))] = '&'
else if match('^(_|--)', $key)
$workaround = $this['modifiers']
$workaround[replace('^([_-]+)', '', '' + utilus_ident($key))] = '&'
if length($this['functions']) > 0
for $key in $this['functions']
// workaround for strange clone? bug
$workaround = $this['params']
$workaround['' + utilus_ident($key)] = utilus_ident($key)
if match('^(__|-[^\-])', utilus_ident($key))
$workaround = $this['elements']
$workaround[replace('^([_-]+)', '', '' + utilus_ident($key))] = '&'
else if match('^(_|--)', utilus_ident($key))
$workaround = $this['modifiers']
$workaround[replace('^([_-]+)', '', '' + utilus_ident($key))] = '&'
if length($this['arrays']) > 0
for $index, $array in $this['arrays']
$key = utilus_ident($array[0])
$rest = ()
for $item, $index in $array
$rest = utilus_append($rest, $item) if $index > 0
$workaround = $this['params']
$workaround['' + $key] = $rest if $rest != ()
if match('^(__|-[^\-])', $key) and $rest != ()
$workaround = $this['elements']
$workaround[replace('^([_-]+)', '', '' + $key)] = utilus_ident($rest)
else if match('^(_|--)', $key) and $rest != ()
$workaround = $this['modifiers']
$workaround[replace('^([_-]+)', '','' + $key)] = utilus_ident($rest)
_stylobate($name, $params, $this = {
parent: {},
arguments: clone($params),
called_from: $name + $params[0],
selector: selector()
})
_stylobate_collect_arguments($this) unless $this.defaulted
// Check if the called stylobate extends anything, if so, call it first,
// and use the extended stylobate for subitems.
$skin_name = utilus_ident($params[0])
$extended_name_ending = replace('.*[^-_]+', '', $skin_name)
$extended_name = $stylobate_extends[$name + $skin_name] || $stylobate_extends[$name + replace('[_-]+$', '', $skin_name)]
$extended_name = utilus_ident($extended_name) + $extended_name_ending if $extended_name
if $extended_name
$this['is_extended'] = true
$skin_name = replace('^' + $name, '', $extended_name)
if !utilus_is_function($extended_name) and $extended_name_ending == ''
error('No stylobate function “' + $extended_name + '”')
stylobate_params($this, $stylobate_defaults[$extended_name]) if $extended_name in $stylobate_defaults and !($name + utilus_ident($params[0]) in $stylobate_extends_without_defaults)
{$extended_name}($this) if $extended_name and $extended_name_ending == ''
if $extended_name
_stylobate_apply_defaults($this, $stylobate_defaults[$extended_name]) if $extended_name in $stylobate_defaults and !($name + utilus_ident($params[0]) in $stylobate_extends_without_defaults)
if ($name + join('',$params) != '') and !utilus_is_function($name + utilus_ident($params[0])) and !$extended_name and !match('[_-]$', utilus_ident($params[0]))
error('No such “' + $name + '” — “' + utilus_ident($params[0]) + '”')
stylobate_params($this, $stylobate_defaults[$name + utilus_ident($params[0])]) if ($name + utilus_ident($params[0])) in $stylobate_defaults
{$name + utilus_ident($params[0])}($this) if utilus_is_function($name + utilus_ident($params[0]))
_stylobate_apply_defaults($this, $stylobate_defaults[$name + utilus_ident($params[0])]) if ($name + utilus_ident($params[0])) in $stylobate_defaults
for $subitem in $this.arguments
// There shouldn't be an `if` inside a {$selector}, 'cause
// there is a crazy stylus bug. When it would be fixed,
// revert this version to 669082fb35
$selector = ''
$foundsubitem = ''
if is_array($subitem)
if type($subitem[0]) in ('ident' 'string' 'function' 'literal')
$testsubitem = utilus_ident($subitem[0])
if match('^(\-|_)', $testsubitem)
$foundsubitem = $subitem
if type($subitem[1]) == 'string'
if match($selector_regex, $subitem[1])
$selector = $subitem[1]
else
$foundsubitem = ''
else
if type($subitem) in ('ident' 'string' 'function' 'literal')
if match('^(\-|_)', utilus_ident($subitem))
$foundsubitem = utilus_ident($subitem)
call_subitem()
$this_subitem = {
parent: $this,
arguments: clone($foundsubitem),
selector: selector()
}
_stylobate_collect_arguments($this_subitem)
$subitemname_prefix = ($extended_name ? '' : $name) + replace('[_-]+$', '', $extended_name ? $extended_name : $skin_name)
$subitemname_connector = replace('^([_-]+)[^_-].*$', '$1', utilus_ident($foundsubitem[0]))
$subitemname_connector_substitutes = {
'_': '--',
'--': '_',
'__': '-',
'-': '__'
}
$subitemname_postfix = utilus_ident(replace('^[_-]+', '', utilus_ident($foundsubitem[0])))
$subitemname = $subitemname_prefix + $subitemname_connector + $subitemname_postfix
$subitemname = '' unless utilus_is_function($subitemname)
if $subitemname == ''
$subitemname_connector = $subitemname_connector_substitutes['' + $subitemname_connector]
$subitemname = $subitemname_prefix + $subitemname_connector + $subitemname_postfix
$subitemname = '' unless utilus_is_function($subitemname)
if $stylobate_options.warn_on_incorrect_notation
warn('' + 'Incorrect notation for %s, using %s.' % ($subitemname_prefix ($subitemname_connector + $subitemname_postfix))) unless $subitemname == ''
// If there is extended subitem function, use it, otherwise
$subitemname_extended = ''
$subitemname_extended = $name + replace('[_-]+$', '', utilus_ident($params[0])) + utilus_ident($foundsubitem[0]) if $extended_name
$subitemname_extended = '' unless utilus_is_function($subitemname_extended)
// Push proper `called_from`
$this_subitem['called_from'] = $subitemname unless $subitemname_extended or !$subitemname
$this_subitem['called_from'] = $subitemname_extended if $subitemname_extended
stylobate_params($this, $stylobate_defaults[$subitemname]) if $subitemname in $stylobate_defaults and !$subitemname_extended
{$subitemname}($this_subitem) unless $subitemname_extended or !$subitemname
_stylobate_apply_defaults($this_subitem, $stylobate_defaults[$subitemname]) if $subitemname in $stylobate_defaults and !$subitemname_extended
stylobate_params($this, $stylobate_defaults[$subitemname_extended]) if $subitemname_extended in $stylobate_defaults and $subitemname_extended
{$subitemname_extended}($this_subitem) unless !$subitemname_extended
_stylobate_apply_defaults($this_subitem, $stylobate_defaults[$subitemname_extended]) if $subitemname_extended in $stylobate_defaults and $subitemname_extended
$selector = '' if $selector == '&'
{stylobate-selector($this, $selector)}
call_subitem() if $foundsubitem != '' and $selector != ''
if $selector == '' and $foundsubitem != ''
call_subitem()
stylobate_property($name, $params)
if utilus_is_comma_list($params)
for $item in $params
_stylobate($name, $item)
else
_stylobate($name, $params)