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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)