archetype 1.0.0.alpha.2 → 1.0.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -3
  3. data/README.md +1 -1
  4. data/VERSION +1 -1
  5. data/lib/archetype.rb +4 -0
  6. data/lib/archetype/actions/migrate.rb +10 -0
  7. data/lib/archetype/extensions.rb +35 -1
  8. data/lib/archetype/functions/helpers.rb +8 -0
  9. data/lib/archetype/functions/styleguide_memoizer.rb +1 -1
  10. data/lib/archetype/sass_extensions/functions/environment.rb +1 -1
  11. data/lib/archetype/sass_extensions/functions/lists.rb +2 -1
  12. data/lib/archetype/sass_extensions/functions/styleguide.rb +45 -88
  13. data/lib/archetype/sass_extensions/functions/styleguide/components.rb +230 -1
  14. data/lib/archetype/sass_extensions/functions/styleguide/constants.rb +0 -1
  15. data/lib/archetype/sass_extensions/functions/styleguide/grammar.rb +66 -5
  16. data/lib/archetype/sass_extensions/functions/styleguide/helpers.rb +36 -1
  17. data/lib/archetype/sass_extensions/functions/styleguide/resolve.rb +12 -2
  18. data/lib/archetype/sass_extensions/functions/styleguide/styles.rb +6 -3
  19. data/lib/archetype/sass_extensions/functions/styleguide/themes.rb +2 -1
  20. data/lib/archetype/sass_extensions/functions/ui/glyphs.rb +1 -1
  21. data/lib/archetype/sass_extensions/functions/ui/scopes.rb +4 -4
  22. data/lib/archetype/sass_extensions/functions/util/debug.rb +1 -1
  23. data/lib/archetype/sass_extensions/functions/util/hacks.rb +4 -8
  24. data/lib/archetype/sass_extensions/functions/util/images.rb +11 -8
  25. data/lib/archetype/sass_extensions/functions/util/misc.rb +34 -1
  26. data/lib/archetype/sass_extensions/functions/util/spacing.rb +1 -1
  27. data/stylesheets/archetype/hacks/_hacks.scss +1 -1
  28. data/stylesheets/archetype/styleguide/_styleguide.scss +2 -0
  29. data/stylesheets/archetype/util/_styles.scss +165 -125
  30. data/stylesheets/archetype/util/_targeting.scss +62 -54
  31. data/templates/example/screen.scss +2 -0
  32. data/templates/project/manifest.rb +1 -1
  33. metadata +24 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 058c5fdcbd3d43e3cc2735abc2957391cc96e2c3
4
- data.tar.gz: 7189fefda56c56cfeac9585dd15bcb23a8650bd1
3
+ metadata.gz: 0a95aac68fb3b20d1e69b5bccc2f4c1b362a3ed8
4
+ data.tar.gz: d731565e005114023d24051c1400eea8f1df0df0
5
5
  SHA512:
6
- metadata.gz: 8b1938af856735dbb720e29c76bd4a26070d16649b930dea0fa490b299c126a12880c232e8569cfc005219d075abc9d1eb9d5d3ac653adfc97972ebc6ed2df50
7
- data.tar.gz: 7ae8ed526d4bff1c47b92cc343c1b7bc6a2743f5100c652eb85d25ba97eaad47139ecc1783e1e830c8aaea6642290ae83dc55342a93b6a7f0c4a21ddc5d74ebb
6
+ metadata.gz: 31d09ec8ee79bda6aaaecbfc642ad353bfebf4f5dda1123e26344733059155c83c37bf12618b6ab3881d940ef4d4b569443e9e9972db4c647545b88955cd5c65
7
+ data.tar.gz: 77fcf48a05921770ff38350fa3d43f0600e0e65c2fe2fd5e05f7bed6d35e468b3468db89b8218ead71556c8cadc655de995bed42cba5810bc7d166df970b50b7
@@ -1,11 +1,75 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0.alpha.3
4
+
5
+ ### Resolved Issues:
6
+
7
+ - allow `target-browser` to be called recursively, kinda
8
+ - Sass 3.4 compatibility
9
+
10
+ ### New Features:
11
+
12
+ - added some additional helper methods for working with styleguide components:
13
+ - `styleguide-remove-component`
14
+ - `styleguide-freeze-component` / `styleguide-thaw-component`
15
+ - `styleguide-freeze-all-components` / `styleguide-thaw-all-components`
16
+ - added `styleguide-components` to retrieve a list of currently registered components
17
+ - added `styleguide-component-variants` to retrieve a list of variants on a given component
18
+ - added `-styleguide-grammar` method for accessing the grammar used by styleguide
19
+ - allow special properties (with a `:`) in component definitions
20
+ - this allows multiple values per property, but also allows us to modify specific keys within variants / extensions without clobbering
21
+ ```
22
+ (
23
+ default: (
24
+ 'target-browser:color': (ie lte 8, color, red),
25
+ 'target-browser:width': (ie lte 9, width, 120px),
26
+ color: red,
27
+ 'color:1': green,
28
+ 'color:2': blue,
29
+ 'color:custom': #abc123
30
+ ),
31
+ variant: (
32
+ color: pink,
33
+ 'color:custom': #987fed,
34
+ 'target-browser:width': nil // we only want to modify the target-browser that's dealing with `width`, not the one for `color`
35
+ )
36
+ )
37
+ ```
38
+ - added `styleguide_debug` config option. when `true`, `styleguide*` methods will log debug information
39
+ - granular options include:
40
+ - `:get`, `:get_granular`, `:diff`, `:add`, `:extend`, `:remove`, `:freeze`, `:grammar`, `:drop`, `:inherit`, `:resolve`, `:extract`
41
+ - e.g. `styleguide_debug = [:add, :get, :grammar]`
42
+ - the `styleguide` mixin can now be called recursively, preserving the context correctly
43
+ ```
44
+ // e.g. instead of doing this...
45
+ .container {
46
+ @include styleguide(container);
47
+ h1 {
48
+ @include styleguide(headline in a container);
49
+ }
50
+ }
51
+ // you can simply do...
52
+ .container {
53
+ @include styleguide(container) {
54
+ h1 {
55
+ @include styleguide(headline);
56
+ }
57
+ }
58
+ }
59
+ ```
60
+ - added support for custom dynamic function calls from within styleguide component (the function should return a map)
61
+
62
+ ### Major Changes:
63
+
64
+ - removed `archetype-version` in favor of `feature-exists`, `variable-exists`, `function-exists`, and `mixin-exists`
65
+ - the `within` context keyword now matches all parent contexts (use `within` for global scope contexts, use `in` for local scope contexts -- direct parent)
66
+
3
67
  ## 1.0.0.alpha.2 (3/24/2014)
4
68
 
5
69
  ### Resolved Issues:
6
70
 
7
71
  - fixed broken gems
8
- - fix the `to-styles` to correctly apply overrides passed in via a content block when using smart content
72
+ - fixed `to-styles` to correctly apply overrides passed in via a content block when using smart content
9
73
 
10
74
  ## 1.0.0.alpha.1 (3/24/2014)
11
75
 
@@ -13,8 +77,8 @@
13
77
 
14
78
  - support Sass 3.3.0 and Compass 1.0.0
15
79
  - `content` is no longer improperly quoted if not needed
16
- - fix for IE7 `:before` glyphs not being positioned correctly
17
- - fix for IE7 potentially crashing with `Operation Aborted` due to glyph injection
80
+ - fixed IE7 `:before` glyphs not being positioned correctly
81
+ - fixed IE7 potentially crashing with `Operation Aborted` due to glyph injection
18
82
 
19
83
  ### New Features:
20
84
 
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Dependency Status](https://gemnasium.com/eoneill/archetype.svg)](https://gemnasium.com/eoneill/archetype)
5
5
 
6
6
  Archetype is a Compass/Sass based framework for authoring configurable, composable UI components and patterns.
7
- The natural language syntax that Archetype provides allows your designers and developers to discuss UI compositions using the same vocabulary.
7
+ The natural language syntax that Archetype provides allows designers and developer to discuss UI compositions using the same vocabulary.
8
8
 
9
9
  ## Resources
10
10
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha.2
1
+ 1.0.0.alpha.3
@@ -38,6 +38,10 @@ module Archetype
38
38
  Compass::Configuration.add_configuration_property(:archetype_meta, "any meta data you want made available to the environment") do
39
39
  {}
40
40
  end
41
+ # meta
42
+ Compass::Configuration.add_configuration_property(:styleguide_debug, "if true, detailed debugging is turned on for styleguide components") do
43
+ false
44
+ end
41
45
  end
42
46
 
43
47
  def self.name
@@ -2,6 +2,16 @@ description = "Check a set of files for migration and back-compat issues"
2
2
  if @description.nil?
3
3
  DELIMITER = "\n "
4
4
  DATA = {
5
+ '1.0.0.alpha.3' => {
6
+ :tests => {
7
+ :sacss => [
8
+ {
9
+ :pattern => /(archetype[_-]version)/m,
10
+ :message => 'function `$1` has been removed'
11
+ }
12
+ ]
13
+ }
14
+ },
5
15
  '1.0.0.alpha.1' => {
6
16
  :notice => %q{Archetype now requires Sass 3.3+ and Compass 0.13+},
7
17
  :tests => {
@@ -10,9 +10,13 @@ module Archetype
10
10
 
11
11
  ROOT_PATH = File.expand_path("../../../", __FILE__)
12
12
 
13
- def initialize(name)
13
+ def initialize(name, gemspec = nil, add_dependency = true)
14
+
15
+ @gemspec = gemspec
16
+ @add_dependency = add_dependency
14
17
 
15
18
  e = @extension = {}
19
+
16
20
  # we only care about the name, so strip off anything if we were given a file/path
17
21
  e[:name] = File.basename(name, '.gemspec').strip
18
22
  # the path to the extension
@@ -21,6 +25,10 @@ module Archetype
21
25
  e[:lib] = File.join(e[:path], 'lib')
22
26
 
23
27
  resolve_version
28
+
29
+ extend_gemspec
30
+
31
+ return @gemspec
24
32
  end
25
33
 
26
34
  def info(prop)
@@ -29,6 +37,32 @@ module Archetype
29
37
 
30
38
  private
31
39
 
40
+ def extend_gemspec()
41
+ unless @gemspec.nil?
42
+ ## Release Specific Information
43
+ @gemspec.version = info(:version)
44
+
45
+ ## most of these are just inheriting from the main archetype.gemspec
46
+ @gemspec.name = info(:name)
47
+ @gemspec.authors = info(:authors)
48
+ @gemspec.email = info(:email)
49
+ @gemspec.homepage = File.join(info(:homepage), 'extensions', info(:name))
50
+ @gemspec.license = info(:license)
51
+
52
+ ## Paths
53
+ @gemspec.require_paths = %w(lib)
54
+
55
+ # Gem Files
56
+ # by default, include everything but the gemspec
57
+ @gemspec.files = Dir.glob("**/*") - Dir.glob("**/*.gemspec")
58
+
59
+ if @add_dependency
60
+ # dependencies
61
+ @gemspec.add_dependency('archetype', "~> #{Archetype::VERSION}") # assume a dependency on the latest current version of Archetype
62
+ end
63
+ end
64
+ end
65
+
32
66
  def resolve_version
33
67
  # if a version.rb file exists within the extension, we'll get the version from that
34
68
  version_rb = File.join(@extension[:lib], @extension[:name], 'version.rb')
@@ -29,6 +29,14 @@ module Archetype::Functions::Helpers
29
29
  logger.record(:warning, msg)
30
30
  end
31
31
 
32
+ #
33
+ # provides a convenience interface for logging debug messages
34
+ # silently captures failures
35
+ #
36
+ def self.debug(msg)
37
+ logger.record(:debug, msg)
38
+ end
39
+
32
40
  #
33
41
  # convert an Archetype::Hash to a Sass::Script::Value::List
34
42
  #
@@ -20,7 +20,7 @@ private
20
20
  #
21
21
  def self.tokenize(theme, extensions, id, modifiers, state)
22
22
  return nil if extensions.nil? or id.nil?
23
- return "#{id}::#{(modifiers.to_a.sort + extensions).join('$')}::#{state}".hash
23
+ return "#{id}::#{(modifiers.to_a.sort + extensions).join('$')}::#{state}"
24
24
  end
25
25
 
26
26
  #
@@ -22,7 +22,7 @@ module Archetype::SassExtensions::Environment
22
22
  #
23
23
  def archetype_namespace(string)
24
24
  namespace = environment.var('CONFIG_NAMESPACE')
25
- return string if is_null(namespace).value
25
+ return string if helpers.is_null(namespace)
26
26
  return identifier(namespace.value + '_' + string.value)
27
27
  end
28
28
 
@@ -15,7 +15,7 @@ module Archetype::SassExtensions::Lists
15
15
  #
16
16
  def list_replace(list, idx = false, value = nil, separator = nil)
17
17
  # return early if the index is invalid (no operation)
18
- return list if (!idx || is_null(idx).value || idx.value == false)
18
+ return list if (!idx || helpers.is_null(idx) || idx.value == false)
19
19
  separator ||= list.separator if list.is_a?(Sass::Script::Value::List)
20
20
  # cast and zero-index $idx
21
21
  idx = (idx.value) - 1
@@ -188,6 +188,7 @@ module Archetype::SassExtensions::Lists
188
188
  # - {*} the nth item in the List
189
189
  #
190
190
  def nth_cyclic(list, n = 1)
191
+ n = 1 if helpers.is_null(n)
191
192
  n = n.to_i if n.is_a?(Sass::Script::Value::Number)
192
193
  list = list.to_a
193
194
  return list[(n - 1) % list.size]
@@ -11,91 +11,6 @@ end
11
11
  #
12
12
  module Archetype::SassExtensions::Styleguide
13
13
 
14
- #
15
- # interface for adding new components to the styleguide structure
16
- #
17
- # *Parameters*:
18
- # - <tt>$id</tt> {String} the component identifier
19
- # - <tt>$data</tt> {Map|List} the component data object
20
- # - <tt>$default</tt> {Map|List} the default data object (for extending)
21
- # - <tt>$theme</tt> {String} the theme to insert the component into
22
- # - <tt>$force</tt> {Boolean} if true, forcibly insert the component
23
- # *Returns*:
24
- # - {Boolean} whether or not the component was added
25
- #
26
- def styleguide_add_component(id, data, default = nil, theme = nil, force = false)
27
- @@archetype_styleguide_mutex.synchronize do
28
- theme = get_theme(theme)
29
- components = theme[:components]
30
- id = helpers.to_str(id)
31
- # if force was true, we have to invalidate the memoizer
32
- memoizer.clear(theme[:name]) if force
33
- # if we already have the component, don't create it again
34
- return Sass::Script::Bool.new(false) if component_exists(id, theme, nil, force)
35
- # otherwise add it
36
- components[id] = helpers.data_to_hash(default, 1, SPECIAL, ADDITIVES).merge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
37
- return Sass::Script::Bool.new(true)
38
- end
39
- end
40
- Sass::Script::Functions.declare :styleguide_add_component, [:id, :data]
41
- Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default]
42
- Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default, :theme]
43
-
44
- #
45
- # interface for extending an existing components in the styleguide structure
46
- #
47
- # *Parameters*:
48
- # - <tt>$id</tt> {String} the component identifier
49
- # - <tt>$data</tt> {List} the component data object
50
- # - <tt>$theme</tt> {String} the theme to insert the component into
51
- # - <tt>$extension</tt> {String} the name of the extension
52
- # - <tt>$force</tt> {Boolean} if true, forcibly extend the component
53
- # *Returns*:
54
- # - {Boolean} whether or not the component was extended
55
- #
56
- def styleguide_extend_component(id, data, theme = nil, extension = nil, force = false)
57
- @@archetype_styleguide_mutex.synchronize do
58
- theme = get_theme(theme)
59
- components = theme[:components]
60
- id = helpers.to_str(id)
61
- # if force was set, we'll create a random token for the name
62
- extension = rand(36**8).to_s(36) if force
63
- # convert the extension into a hash (if we don't have an extension, compose one out of its data)
64
- extension = helpers.to_str(extension || data).hash
65
- extensions = theme[:extensions]
66
- return Sass::Script::Bool.new(false) if component_exists(id, theme, extension, force)
67
- extensions.push(extension)
68
- components[id] = (components[id] ||= Archetype::Hash.new).rmerge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
69
- return Sass::Script::Bool.new(true)
70
- end
71
- end
72
- Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data]
73
- Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme]
74
- Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme, :extension]
75
-
76
- #
77
- # check whether or not a component (or a component extension) has already been defined
78
- #
79
- # *Parameters*:
80
- # - <tt>$id</tt> {String} the component identifier
81
- # - <tt>$data</tt> {List} the component data object
82
- # - <tt>$theme</tt> {String} the theme to insert the component into
83
- # - <tt>$extension</tt> {String} the name of the extension
84
- # - <tt>$force</tt> {Boolean} if true, forcibly extend the component
85
- # *Returns*:
86
- # - {Boolean} whether or not the component/extension exists
87
- #
88
- def styleguide_component_exists(id, theme = nil, extension = nil, force = false)
89
- @@archetype_styleguide_mutex.synchronize do
90
- extension = helpers.to_str(extension).hash if not extension.nil?
91
- return Sass::Script::Bool.new( component_exists(id, theme, extension, force) )
92
- end
93
- end
94
- Sass::Script::Functions.declare :styleguide_extend_component, [:id]
95
- Sass::Script::Functions.declare :styleguide_extend_component, [:id, :theme]
96
- Sass::Script::Functions.declare :styleguide_extend_component, [:id, :theme, :extension]
97
- Sass::Script::Functions.declare :styleguide_extend_component, [:id, :theme, :extension, :force]
98
-
99
14
  #
100
15
  # given a description of the component, convert it into CSS
101
16
  #
@@ -106,9 +21,18 @@ module Archetype::SassExtensions::Styleguide
106
21
  # - {Map} a map of styles
107
22
  #
108
23
  def _styleguide(description, state = nil, theme = nil)
109
- @@archetype_styleguide_mutex.synchronize do
24
+ extras = []
25
+ extras << "state: #{state}" unless (state.nil? or helpers.is_null(state))
26
+ extras << "theme: #{theme}" unless (theme.nil? or helpers.is_null(theme))
27
+ extras = extras.join(', ')
28
+ msg = "`#{description}`"
29
+ msg << " (#{extras})" unless extras.empty?
30
+ _styleguide_debug "fetching styles for #{msg}", :get
31
+ _styleguide_mutex_helper do
110
32
  styles = get_styles(description, theme, state)
111
33
  styles = resolve_runtime_locale_values(styles)
34
+ _styleguide_debug "got styles for #{msg}", :get
35
+ _styleguide_debug styles, :get
112
36
  # convert it back to a Sass:Map and carry on
113
37
  return helpers.hash_to_map(styles)
114
38
  end
@@ -124,7 +48,7 @@ module Archetype::SassExtensions::Styleguide
124
48
  # - {List} a key-value paired list of styles
125
49
  #
126
50
  def styleguide_diff(original, other)
127
- @@archetype_styleguide_mutex.synchronize do
51
+ _styleguide_mutex_helper do
128
52
  # normalize our input (for back-compat)
129
53
  original = normalize_styleguide_definition(original)
130
54
  other = normalize_styleguide_definition(other)
@@ -134,6 +58,8 @@ module Archetype::SassExtensions::Styleguide
134
58
  original_message = helpers.get_meta_message(original).sub(MESSAGE_PREFIX, '').sub(MESSAGE_SUFFIX, '')
135
59
  other_message = helpers.get_meta_message(other).sub(MESSAGE_PREFIX, '').sub(MESSAGE_SUFFIX, '')
136
60
  diff = helpers.add_meta_message(diff, "#{MESSAGE_PREFIX}#{original_message}` vs `#{other_message}#{MESSAGE_SUFFIX}")
61
+ _styleguide_debug "styleguide-diff", :diff
62
+ _styleguide_debug diff, :diff
137
63
  # and return it as a map
138
64
  return helpers.hash_to_map(diff)
139
65
  end
@@ -151,7 +77,7 @@ module Archetype::SassExtensions::Styleguide
151
77
  # - {List|Map|*} either a list/map of the values or the individual value itself
152
78
  #
153
79
  def styleguide_derived_style(definition, properties = [], format = 'auto', strict = false)
154
- @@archetype_styleguide_mutex.synchronize do
80
+ _styleguide_mutex_helper do
155
81
  # normalize our input
156
82
  definition = normalize_styleguide_definition(definition)
157
83
  # get the computed styles
@@ -159,4 +85,35 @@ module Archetype::SassExtensions::Styleguide
159
85
  end
160
86
  end
161
87
 
88
+ #
89
+ # updates the global styleguide context stack
90
+ #
91
+ # *Parameters*:
92
+ # - <tt>$definition</tt> {List} the description of the component, if not passed, removes the last item from the stack
93
+ #
94
+ def _styleguide_shift_context(definition = nil)
95
+ # get the current stack...
96
+ stack = styleguide_stack()
97
+ # if we have a definition to push onto it, do so...
98
+ if definition
99
+ stack << definition
100
+ # otherwise pop the last item off
101
+ else
102
+ stack.pop
103
+ end
104
+ # and update the stack
105
+ styleguide_stack(stack)
106
+ return bool(true)
107
+ end
108
+
109
+ private
110
+
111
+ def styleguide_stack(stack = nil)
112
+ if stack.nil?
113
+ return (environment.var('ARCHETYPE_STYLEGUIDE_STACK') || []).to_a.dup
114
+ else
115
+ environment.global_env.set_var('ARCHETYPE_STYLEGUIDE_STACK', list(stack, :comma))
116
+ end
117
+ end
118
+
162
119
  end
@@ -1,7 +1,236 @@
1
1
  module Archetype::SassExtensions::Styleguide
2
+ #
3
+ # interface for adding new components to the styleguide structure
4
+ #
5
+ # *Parameters*:
6
+ # - <tt>$id</tt> {String} the component identifier
7
+ # - <tt>$data</tt> {Map|List} the component data object
8
+ # - <tt>$default</tt> {Map|List} the default data object (for extending)
9
+ # - <tt>$theme</tt> {String} the theme to insert the component into
10
+ # - <tt>$force</tt> {Boolean} if true, forcibly insert the component
11
+ # *Returns*:
12
+ # - {Boolean} whether or not the component was added
13
+ #
14
+ def styleguide_add_component(id, data, default = nil, theme = nil, force = false)
15
+ _styleguide_debug "attempting to register component for `#{id}`", :add
16
+ _styleguide_mutex_helper(id, theme) do |id, theme|
17
+ components = theme[:components]
18
+ # if force was true, we have to invalidate the memoizer
19
+ memoizer.clear(theme[:name]) if force
20
+ # if we already have the component, don't create it again
21
+ if component_exists?(id, theme, nil, force) || component_is_frozen?(id, theme)
22
+ _styleguide_debug "skipping component registration for `#{id}`. the component is already registered or frozen", :add
23
+ return bool(false)
24
+ end
25
+ # otherwise add it
26
+ components[id] = helpers.data_to_hash(default, 1, SPECIAL, ADDITIVES).merge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
27
+ _styleguide_debug "successfully registered component `#{id}`", :add
28
+ _styleguide_debug components[id], :add
29
+ return bool(true)
30
+ end
31
+ end
32
+ Sass::Script::Functions.declare :styleguide_add_component, [:id, :data]
33
+ Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default]
34
+ Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default, :theme]
35
+
36
+ #
37
+ # interface for extending an existing components in the styleguide structure
38
+ #
39
+ # *Parameters*:
40
+ # - <tt>$id</tt> {String} the component identifier
41
+ # - <tt>$data</tt> {List} the component data object
42
+ # - <tt>$theme</tt> {String} the theme to insert the component into
43
+ # - <tt>$extension</tt> {String} the name of the extension
44
+ # - <tt>$force</tt> {Boolean} if true, forcibly extend the component
45
+ # *Returns*:
46
+ # - {Boolean} whether or not the component was extended
47
+ #
48
+ def styleguide_extend_component(id, data, theme = nil, extension = nil, force = false)
49
+ _styleguide_debug "attempting to extend component for `#{id}`", :extend
50
+ _styleguide_debug "extension name is `#{extension.to_sass}`", :extend unless extension.nil?
51
+ _styleguide_mutex_helper(id, theme) do |id, theme|
52
+ components = theme[:components]
53
+ # if force was set, we'll create a random token for the name
54
+ if force
55
+ extension = random_uid('extension')
56
+ _styleguide_debug "forcibly extending...", :extend
57
+ end
58
+ # use the extension name or a snapshot of the extension
59
+ extension = helpers.to_str(extension || data.to_sass)
60
+ extensions = theme[:extensions]
61
+ if component_exists?(id, theme, extension, force) || component_is_frozen?(id, theme)
62
+ _styleguide_debug "skipping component extension for `#{id}`. the extension is already registered or frozen", :extend
63
+ return bool(false)
64
+ end
65
+ extensions.push(extension)
66
+ components[id] = (components[id] ||= Archetype::Hash.new).rmerge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
67
+ _styleguide_debug "successfully extended component `#{id}`", :extend
68
+ _styleguide_debug components[id], :extend
69
+ return bool(true)
70
+ end
71
+ end
72
+ Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data]
73
+ Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme]
74
+ Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :extension]
75
+ Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme, :extension]
76
+
77
+ #
78
+ # check whether or not a component (or a component extension) has already been defined
79
+ #
80
+ # *Parameters*:
81
+ # - <tt>$id</tt> {String} the component identifier
82
+ # - <tt>$data</tt> {List} the component data object
83
+ # - <tt>$theme</tt> {String} the theme to insert the component into
84
+ # - <tt>$extension</tt> {String} the name of the extension
85
+ # - <tt>$force</tt> {Boolean} if true, forcibly extend the component
86
+ # *Returns*:
87
+ # - {Boolean} whether or not the component/extension exists
88
+ #
89
+ def styleguide_component_exists(id, theme = nil, extension = nil, force = false)
90
+ _styleguide_mutex_helper do
91
+ extension = helpers.to_str(extension) if not extension.nil?
92
+ return bool( component_exists?(id, theme, extension, force) )
93
+ end
94
+ end
95
+ Sass::Script::Functions.declare :styleguide_component_exists, [:id]
96
+ Sass::Script::Functions.declare :styleguide_component_exists, [:id, :theme]
97
+ Sass::Script::Functions.declare :styleguide_component_exists, [:id, :theme, :extension]
98
+ Sass::Script::Functions.declare :styleguide_component_exists, [:id, :theme, :extension, :force]
99
+
100
+ #
101
+ # removes a component definition
102
+ #
103
+ # *Parameters*
104
+ # - <tt>$id</tt> {String} the component identifier
105
+ # - <tt>$theme</tt> {String} the theme to insert the component into
106
+ #
107
+ def styleguide_remove_component(id, theme = nil)
108
+ _styleguide_debug "removing component `#{id}`", :remove
109
+ _styleguide_mutex_helper(id, theme) do |id, theme|
110
+ theme[:components].delete(id)
111
+ theme[:extensions].push(random_uid('remove'))
112
+ return bool(true)
113
+ end
114
+ end
115
+ Sass::Script::Functions.declare :styleguide_remove_component, [:id]
116
+ Sass::Script::Functions.declare :styleguide_remove_component, [:id, :theme]
117
+
118
+ #
119
+ # flags a component definition as "frozen" (locked)
120
+ #
121
+ # *Parameters*
122
+ # - <tt>$id</tt> {String} the component identifier
123
+ # - <tt>$theme</tt> {String} the theme to insert the component into
124
+ #
125
+ def styleguide_freeze_component(id, theme = nil)
126
+ _styleguide_debug "freezing component `#{id}`", :freeze
127
+ _styleguide_mutex_helper(id, theme) do |id, theme|
128
+ theme[:frozen] << id
129
+ return bool(true)
130
+ end
131
+ end
132
+ Sass::Script::Functions.declare :styleguide_freeze_component, [:id]
133
+ Sass::Script::Functions.declare :styleguide_freeze_component, [:id, :theme]
134
+
135
+ #
136
+ # freezes all registered components
137
+ #
138
+ # *Parameters*
139
+ # - <tt>$theme</tt> {String} the theme to insert the component into
140
+ #
141
+ def styleguide_freeze_all_components(theme = nil)
142
+ _styleguide_debug "freezing ALL components", :freeze
143
+ _styleguide_mutex_helper do
144
+ theme = get_theme(theme)
145
+ theme[:frozen] = Set.new(theme[:components].keys)
146
+ return bool(true)
147
+ end
148
+ end
149
+ Sass::Script::Functions.declare :styleguide_freeze_all_components, [:theme]
150
+
151
+ #
152
+ # "thaws" (unlocks) a frozen component
153
+ #
154
+ # *Parameters*
155
+ # - <tt>$id</tt> {String} the component identifier
156
+ # - <tt>$theme</tt> {String} the theme to insert the component into
157
+ #
158
+ def styleguide_thaw_component(id, theme = nil)
159
+ _styleguide_debug "thawing component `#{id}`", :freeze
160
+ _styleguide_mutex_helper(id, theme) do |id, theme|
161
+ theme[:frozen].delete(id)
162
+ return bool(true)
163
+ end
164
+ end
165
+ Sass::Script::Functions.declare :styleguide_thaw_component, [:id]
166
+ Sass::Script::Functions.declare :styleguide_thaw_component, [:id, :theme]
167
+
168
+ #
169
+ # freezes all registered components
170
+ #
171
+ # *Parameters*
172
+ # - <tt>$theme</tt> {String} the theme to insert the component into
173
+ #
174
+ def styleguide_thaw_all_components(theme = nil)
175
+ _styleguide_debug "thawing ALL components", :freeze
176
+ _styleguide_mutex_helper do
177
+ theme = get_theme(theme)
178
+ theme[:frozen].clear
179
+ return bool(true)
180
+ end
181
+ end
182
+ Sass::Script::Functions.declare :styleguide_thaw_all_components, [:theme]
183
+
184
+ #
185
+ # gets a list of all known components
186
+ #
187
+ # *Parameters*:
188
+ # - <tt>$theme</tt> {String} the theme to look within
189
+ # *Returns*:
190
+ # - {List} list of component identifiers
191
+ #
192
+ def styleguide_components(theme = nil)
193
+ theme = get_theme(theme)
194
+ keys = theme[:components].keys.map { |k| identifier(k) }
195
+ return list(keys, :comma)
196
+ end
197
+
198
+ #
199
+ # gets a list of all the current variants of a given component
200
+ #
201
+ # *Parameters*:
202
+ # - <tt>$id</tt> {String} the component identifier
203
+ # - <tt>$theme</tt> {String} the theme to look within
204
+ # *Returns*:
205
+ # - {List} list of component variants
206
+ #
207
+ def styleguide_component_variants(id, theme = nil)
208
+ id = helpers.to_str(id)
209
+ theme = get_theme(theme)
210
+ component = theme[:components][id]
211
+ return null if component.nil?
212
+ variants = component.keys
213
+ variants = variants.map { |k| identifier(k) }
214
+ return list(variants, :comma)
215
+ end
2
216
 
3
217
  private
4
218
 
219
+ #
220
+ # TODO - doc
221
+ #
222
+ def random_uid(str = '')
223
+ return rand(36**8).to_s(36) + str
224
+ end
225
+
226
+ def component_is_frozen?(id, theme, warn = true)
227
+ if theme[:frozen].include?(id)
228
+ helpers.warn "[#{Archetype.name}:styleguide:frozen] the component `#{id}` has been frozen and cannot be modified" if warn
229
+ return true
230
+ end
231
+ return false
232
+ end
233
+
5
234
  #
6
235
  # check whether or not a component (or a component extension) has already been defined
7
236
  #
@@ -13,7 +242,7 @@ module Archetype::SassExtensions::Styleguide
13
242
  # *Returns*:
14
243
  # - {Boolean} whether or not the component/extension exists
15
244
  #
16
- def component_exists(id, theme = nil, extension = nil, force = false)
245
+ def component_exists?(id, theme = nil, extension = nil, force = false)
17
246
  status = false
18
247
  theme = get_theme(theme) if not theme.is_a? Hash
19
248
  id = helpers.to_str(id)