module Archetype::SassExtensions::Styleguide
#
# interface for adding new components to the styleguide structure
#
# *Parameters*:
# - $id {String} the component identifier
# - $data {Map|List} the component data object
# - $default {Map|List} the default data object (for extending)
# - $theme {String} the theme to insert the component into
# - $force {Boolean} if true, forcibly insert the component
# *Returns*:
# - {Boolean} whether or not the component was added
#
def styleguide_add_component(id, data, default = nil, theme = nil, force = false)
_styleguide_debug "attempting to register component for `#{id}`", :add
_styleguide_mutex_helper(id, theme) do |id, theme|
components = theme[:components]
# if force was true, we have to invalidate the memoizer
memoizer.clear(theme[:name]) if force
# if we already have the component, don't create it again
if component_exists?(id, theme, nil, force) || component_is_frozen?(id, theme)
_styleguide_debug "skipping component registration for `#{id}`. the component is already registered or frozen", :add
return bool(false)
end
# otherwise add it
components[id] = helpers.data_to_hash(default, 1, SPECIAL, ADDITIVES).merge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
_styleguide_debug "successfully registered component `#{id}`", :add
_styleguide_debug components[id], :add
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_add_component, [:id, :data]
Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default]
Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default, :theme]
#
# interface for extending an existing components in the styleguide structure
#
# *Parameters*:
# - $id {String} the component identifier
# - $data {List} the component data object
# - $theme {String} the theme to insert the component into
# - $extension {String} the name of the extension
# - $force {Boolean} if true, forcibly extend the component
# *Returns*:
# - {Boolean} whether or not the component was extended
#
def styleguide_extend_component(id, data, theme = nil, extension = nil, force = false)
_styleguide_debug "attempting to extend component for `#{id}`", :extend
_styleguide_debug "extension name is `#{extension.to_sass}`", :extend unless extension.nil?
_styleguide_mutex_helper(id, theme) do |id, theme|
components = theme[:components]
# if force was set, we'll create a random token for the name
if force
extension = random_uid('extension')
_styleguide_debug "forcibly extending...", :extend
end
# use the extension name or a snapshot of the extension
extension = helpers.to_str(extension || data.to_sass)
extensions = theme[:extensions]
if component_exists?(id, theme, extension, force) || component_is_frozen?(id, theme)
_styleguide_debug "skipping component extension for `#{id}`. the extension is already registered or frozen", :extend
return bool(false)
end
extensions.push(extension)
components[id] = (components[id] ||= Archetype::Hash.new).rmerge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
_styleguide_debug "successfully extended component `#{id}`", :extend
_styleguide_debug components[id], :extend
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data]
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme]
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :extension]
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme, :extension]
#
# check whether or not a component (or a component extension) has already been defined
#
# *Parameters*:
# - $id {String} the component identifier
# - $data {List} the component data object
# - $theme {String} the theme to insert the component into
# - $extension {String} the name of the extension
# - $force {Boolean} if true, forcibly extend the component
# *Returns*:
# - {Boolean} whether or not the component/extension exists
#
def styleguide_component_exists(id, theme = nil, extension = nil, force = false)
_styleguide_mutex_helper do
extension = helpers.to_str(extension) if not extension.nil?
return bool( component_exists?(id, theme, extension, force) )
end
end
Sass::Script::Functions.declare :styleguide_component_exists, [:id]
Sass::Script::Functions.declare :styleguide_component_exists, [:id, :theme]
Sass::Script::Functions.declare :styleguide_component_exists, [:id, :theme, :extension]
Sass::Script::Functions.declare :styleguide_component_exists, [:id, :theme, :extension, :force]
#
# removes a component definition
#
# *Parameters*
# - $id {String} the component identifier
# - $theme {String} the theme to insert the component into
#
def styleguide_remove_component(id, theme = nil)
_styleguide_debug "removing component `#{id}`", :remove
_styleguide_mutex_helper(id, theme) do |id, theme|
theme[:components].delete(id)
theme[:extensions].push(random_uid('remove'))
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_remove_component, [:id]
Sass::Script::Functions.declare :styleguide_remove_component, [:id, :theme]
#
# flags a component definition as "frozen" (locked)
#
# *Parameters*
# - $id {String} the component identifier
# - $theme {String} the theme to insert the component into
#
def styleguide_freeze_component(id, theme = nil)
_styleguide_debug "freezing component `#{id}`", :freeze
_styleguide_mutex_helper(id, theme) do |id, theme|
theme[:frozen] << id
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_freeze_component, [:id]
Sass::Script::Functions.declare :styleguide_freeze_component, [:id, :theme]
#
# freezes all registered components
#
# *Parameters*
# - $theme {String} the theme to insert the component into
#
def styleguide_freeze_all_components(theme = nil)
_styleguide_debug "freezing ALL components", :freeze
_styleguide_mutex_helper do
theme = get_theme(theme)
theme[:frozen] = Set.new(theme[:components].keys)
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_freeze_all_components, [:theme]
#
# "thaws" (unlocks) a frozen component
#
# *Parameters*
# - $id {String} the component identifier
# - $theme {String} the theme to insert the component into
#
def styleguide_thaw_component(id, theme = nil)
_styleguide_debug "thawing component `#{id}`", :freeze
_styleguide_mutex_helper(id, theme) do |id, theme|
theme[:frozen].delete(id)
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_thaw_component, [:id]
Sass::Script::Functions.declare :styleguide_thaw_component, [:id, :theme]
#
# freezes all registered components
#
# *Parameters*
# - $theme {String} the theme to insert the component into
#
def styleguide_thaw_all_components(theme = nil)
_styleguide_debug "thawing ALL components", :freeze
_styleguide_mutex_helper do
theme = get_theme(theme)
theme[:frozen].clear
return bool(true)
end
end
Sass::Script::Functions.declare :styleguide_thaw_all_components, [:theme]
#
# gets a list of all known components
#
# *Parameters*:
# - $theme {String} the theme to look within
# *Returns*:
# - {List} list of component identifiers
#
def styleguide_components(theme = nil)
theme = get_theme(theme)
keys = theme[:components].keys.map { |k| identifier(k) }
return list(keys, :comma)
end
#
# gets a list of all the current variants of a given component
#
# *Parameters*:
# - $id {String} the component identifier
# - $theme {String} the theme to look within
# *Returns*:
# - {List} list of component variants
#
def styleguide_component_variants(id, theme = nil)
id = helpers.to_str(id)
theme = get_theme(theme)
component = theme[:components][id]
return null if component.nil?
variants = component.keys
variants = variants.map { |k| identifier(k) }
return list(variants, :comma)
end
private
#
# TODO - doc
#
def random_uid(str = '')
return rand(36**8).to_s(36) + str
end
def component_is_frozen?(id, theme, warn = true)
if theme[:frozen].include?(id)
helpers.warn "[#{Archetype.name}:styleguide:frozen] the component `#{id}` has been frozen and cannot be modified" if warn
return true
end
return false
end
#
# check whether or not a component (or a component extension) has already been defined
#
# *Parameters*:
# - id {String} the component identifier
# - theme {String} the theme to insert the component into
# - extension {String} the name of the extension
# - force {Boolean} if true, forcibly extend the component
# *Returns*:
# - {Boolean} whether or not the component/extension exists
#
def component_exists?(id, theme = nil, extension = nil, force = false)
status = false
theme = get_theme(theme) if not theme.is_a? Hash
id = helpers.to_str(id)
# determine the status of the component
status = (extension.nil?) ? (not theme[:components][id].nil?) : theme[:extensions].include?(extension)
return (status and not force and Compass.configuration.memoize)
end
end