archetype 0.0.1.pre.13 → 1.0.0.alpha.1

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 (253) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -24
  3. data/README.md +11 -5
  4. data/VERSION +1 -0
  5. data/lib/archetype.rb +30 -18
  6. data/lib/archetype/actions/migrate.rb +152 -0
  7. data/lib/archetype/actions/theme.rb +6 -7
  8. data/lib/archetype/executor.rb +21 -7
  9. data/lib/archetype/extensions.rb +57 -0
  10. data/lib/archetype/functions.rb +2 -3
  11. data/lib/archetype/functions/css.rb +70 -0
  12. data/lib/archetype/functions/css/constants.rb +247 -0
  13. data/lib/archetype/functions/css/helpers.rb +265 -0
  14. data/lib/archetype/functions/css/routers.rb +28 -0
  15. data/lib/archetype/functions/css/routers/animation.rb +55 -0
  16. data/lib/archetype/functions/css/routers/background.rb +38 -0
  17. data/lib/archetype/functions/css/routers/border.rb +151 -0
  18. data/lib/archetype/functions/css/routers/list.rb +63 -0
  19. data/lib/archetype/functions/css/routers/margin_padding.rb +40 -0
  20. data/lib/archetype/functions/css/routers/outline.rb +56 -0
  21. data/lib/archetype/functions/css/routers/overflow.rb +11 -0
  22. data/lib/archetype/functions/css/routers/target.rb +38 -0
  23. data/lib/archetype/functions/css/routers/transition.rb +48 -0
  24. data/lib/archetype/functions/css/shorthands.rb +43 -0
  25. data/lib/archetype/functions/css/shorthands/animation.rb +18 -0
  26. data/lib/archetype/functions/css/shorthands/background.rb +68 -0
  27. data/lib/archetype/functions/css/shorthands/border.rb +102 -0
  28. data/lib/archetype/functions/hash.rb +3 -149
  29. data/lib/archetype/functions/hash/extend.rb +74 -0
  30. data/lib/archetype/functions/hash/shim.rb +48 -0
  31. data/lib/archetype/functions/helpers.rb +231 -22
  32. data/lib/archetype/functions/styleguide_memoizer.rb +18 -1
  33. data/lib/archetype/sass_extensions.rb +1 -3
  34. data/lib/archetype/sass_extensions/functions.rb +15 -1
  35. data/lib/archetype/sass_extensions/functions/environment.rb +152 -1
  36. data/lib/archetype/sass_extensions/functions/lists.rb +95 -45
  37. data/lib/archetype/sass_extensions/functions/locale.rb +107 -28
  38. data/lib/archetype/sass_extensions/functions/numbers.rb +118 -4
  39. data/lib/archetype/sass_extensions/functions/strings.rb +53 -0
  40. data/lib/archetype/sass_extensions/functions/styleguide.rb +43 -375
  41. data/lib/archetype/sass_extensions/functions/styleguide/components.rb +25 -0
  42. data/lib/archetype/sass_extensions/functions/styleguide/constants.rb +27 -0
  43. data/lib/archetype/sass_extensions/functions/styleguide/grammar.rb +80 -0
  44. data/lib/archetype/sass_extensions/functions/styleguide/helpers.rb +36 -0
  45. data/lib/archetype/sass_extensions/functions/styleguide/resolve.rb +159 -0
  46. data/lib/archetype/sass_extensions/functions/styleguide/styles.rb +146 -0
  47. data/lib/archetype/sass_extensions/functions/styleguide/themes.rb +40 -0
  48. data/lib/archetype/sass_extensions/functions/ui.rb +7 -57
  49. data/lib/archetype/sass_extensions/functions/ui/glyphs.rb +118 -0
  50. data/lib/archetype/sass_extensions/functions/ui/scopes.rb +96 -0
  51. data/lib/archetype/sass_extensions/functions/util.rb +14 -0
  52. data/lib/archetype/sass_extensions/functions/util/debug.rb +22 -0
  53. data/lib/archetype/sass_extensions/functions/util/hacks.rb +44 -0
  54. data/lib/archetype/sass_extensions/functions/util/images.rb +132 -0
  55. data/lib/archetype/sass_extensions/functions/util/misc.rb +220 -0
  56. data/lib/archetype/sass_extensions/functions/util/spacing.rb +83 -0
  57. data/lib/archetype/sass_extensions/functions/version.rb +12 -17
  58. data/lib/archetype/version.rb +1 -1
  59. data/stylesheets/archetype/_config.scss +1 -389
  60. data/stylesheets/archetype/_core.scss +15 -0
  61. data/stylesheets/archetype/_hacks.scss +4 -120
  62. data/stylesheets/archetype/_init.scss +4 -22
  63. data/stylesheets/archetype/_required.scss +3 -0
  64. data/stylesheets/archetype/_reset.scss +3 -0
  65. data/stylesheets/archetype/_styleguide.scss +2 -6
  66. data/stylesheets/archetype/_ui.scss +2 -358
  67. data/stylesheets/archetype/_util.scss +3 -10
  68. data/stylesheets/archetype/config/_core.scss +14 -0
  69. data/stylesheets/archetype/config/_environment.scss +19 -0
  70. data/stylesheets/archetype/config/_formatting.scss +63 -0
  71. data/stylesheets/archetype/config/_glyphs.scss +252 -0
  72. data/stylesheets/archetype/config/_resets.scss +7 -0
  73. data/stylesheets/archetype/config/_resolution.scss +3 -0
  74. data/stylesheets/archetype/config/_spacing.scss +5 -0
  75. data/stylesheets/archetype/config/_targeting.scss +18 -0
  76. data/stylesheets/archetype/config/_theme.scss +3 -0
  77. data/stylesheets/archetype/config/_typography.scss +56 -0
  78. data/stylesheets/archetype/config/_units.scss +2 -0
  79. data/stylesheets/archetype/config/_vars.scss +10 -0
  80. data/stylesheets/archetype/hacks/_core.scss +4 -0
  81. data/stylesheets/archetype/hacks/_hacks.scss +160 -0
  82. data/stylesheets/archetype/hacks/_init.scss +2 -0
  83. data/stylesheets/archetype/styleguide/_core.scss +4 -0
  84. data/stylesheets/archetype/styleguide/_init.scss +1 -0
  85. data/stylesheets/archetype/styleguide/_styleguide.scss +41 -18
  86. data/stylesheets/archetype/ui/_accessibility.scss +41 -0
  87. data/stylesheets/archetype/ui/_breakpoints.scss +19 -0
  88. data/stylesheets/archetype/ui/_core.scss +10 -0
  89. data/stylesheets/archetype/ui/_elements.scss +98 -0
  90. data/stylesheets/archetype/ui/_glyphs.scss +244 -0
  91. data/stylesheets/archetype/ui/_init.scss +5 -0
  92. data/stylesheets/archetype/ui/_layout.scss +37 -0
  93. data/stylesheets/archetype/ui/_locale.scss +12 -0
  94. data/stylesheets/archetype/ui/_scopes.scss +42 -0
  95. data/stylesheets/archetype/util/_core.scss +8 -0
  96. data/stylesheets/archetype/util/_debug.scss +9 -21
  97. data/stylesheets/archetype/util/_init.scss +1 -0
  98. data/stylesheets/archetype/util/_misc.scss +21 -86
  99. data/stylesheets/archetype/util/_spacing.scss +9 -40
  100. data/stylesheets/archetype/util/_styles.scss +189 -178
  101. data/stylesheets/archetype/util/_targeting.scss +51 -68
  102. data/templates/example/manifest.rb +2 -2
  103. data/templates/example/screen.scss +0 -1
  104. data/templates/project/manifest.rb +3 -8
  105. metadata +93 -263
  106. data/bin/archetype +0 -3
  107. data/lib/archetype/sass_extensions/monkey_patches.rb +0 -3
  108. data/lib/archetype/sass_extensions/monkey_patches/handle_include_loop.rb +0 -13
  109. data/stylesheets/archetype/_base.scss +0 -54
  110. data/stylesheets/archetype/_grid.scss +0 -3
  111. data/stylesheets/archetype/base/_h5bp.scss +0 -307
  112. data/stylesheets/archetype/base/_hybrid.scss +0 -25
  113. data/stylesheets/archetype/base/_normalize.scss +0 -634
  114. data/stylesheets/archetype/base/_reset.scss +0 -72
  115. data/stylesheets/archetype/grid/_config.scss +0 -14
  116. data/stylesheets/archetype/grid/_grid.scss +0 -391
  117. data/stylesheets/archetype/styleguide/_components.scss +0 -25
  118. data/stylesheets/archetype/styleguide/_helpers.scss +0 -215
  119. data/stylesheets/archetype/styleguide/_primitives.scss +0 -10
  120. data/stylesheets/archetype/styleguide/components/_alerts.scss +0 -59
  121. data/stylesheets/archetype/styleguide/components/_annotations.scss +0 -27
  122. data/stylesheets/archetype/styleguide/components/_bristol.scss +0 -15
  123. data/stylesheets/archetype/styleguide/components/_button_groups.scss +0 -47
  124. data/stylesheets/archetype/styleguide/components/_button_toolbars.scss +0 -17
  125. data/stylesheets/archetype/styleguide/components/_buttons.scss +0 -339
  126. data/stylesheets/archetype/styleguide/components/_canvas.scss +0 -15
  127. data/stylesheets/archetype/styleguide/components/_carets.scss +0 -336
  128. data/stylesheets/archetype/styleguide/components/_closes.scss +0 -63
  129. data/stylesheets/archetype/styleguide/components/_container.scss +0 -27
  130. data/stylesheets/archetype/styleguide/components/_copy.scss +0 -85
  131. data/stylesheets/archetype/styleguide/components/_flyouts.scss +0 -52
  132. data/stylesheets/archetype/styleguide/components/_headings.scss +0 -33
  133. data/stylesheets/archetype/styleguide/components/_headlines.scss +0 -64
  134. data/stylesheets/archetype/styleguide/components/_hovercards.scss +0 -27
  135. data/stylesheets/archetype/styleguide/components/_icons.scss +0 -17
  136. data/stylesheets/archetype/styleguide/components/_identities.scss +0 -34
  137. data/stylesheets/archetype/styleguide/components/_links.scss +0 -68
  138. data/stylesheets/archetype/styleguide/components/_loaders.scss +0 -154
  139. data/stylesheets/archetype/styleguide/components/_menu_items.scss +0 -31
  140. data/stylesheets/archetype/styleguide/components/_module.scss +0 -15
  141. data/stylesheets/archetype/styleguide/components/_pullquotes.scss +0 -29
  142. data/stylesheets/archetype/styleguide/components/_punchcut.scss +0 -18
  143. data/stylesheets/archetype/styleguide/components/_tooltips.scss +0 -28
  144. data/stylesheets/archetype/styleguide/primitives/_animations.scss +0 -17
  145. data/stylesheets/archetype/styleguide/primitives/_dimensions.scss +0 -50
  146. data/stylesheets/archetype/styleguide/primitives/_glyphs.scss +0 -11
  147. data/stylesheets/archetype/styleguide/primitives/_misc.scss +0 -8
  148. data/stylesheets/archetype/styleguide/primitives/_palettes.scss +0 -94
  149. data/stylesheets/archetype/styleguide/primitives/_shadows.scss +0 -23
  150. data/stylesheets/archetype/styleguide/primitives/_sprites.scss +0 -46
  151. data/stylesheets/archetype/styleguide/primitives/_textures.scss +0 -10
  152. data/stylesheets/archetype/styleguide/primitives/_typography.scss +0 -56
  153. data/stylesheets/archetype/util/_lists.scss +0 -57
  154. data/stylesheets/archetype/util/_rtl.scss +0 -279
  155. data/stylesheets/archetype/util/_units.scss +0 -18
  156. data/templates/project/screen.scss +0 -1
  157. data/templates/project/vendor/archetype/animations/loaders/large/large.png +0 -0
  158. data/templates/project/vendor/archetype/animations/loaders/large/large_dark.png +0 -0
  159. data/templates/project/vendor/archetype/animations/loaders/large/large_dark_static.png +0 -0
  160. data/templates/project/vendor/archetype/animations/loaders/large/large_static.png +0 -0
  161. data/templates/project/vendor/archetype/animations/loaders/medium/medium.png +0 -0
  162. data/templates/project/vendor/archetype/animations/loaders/medium/medium_dark.png +0 -0
  163. data/templates/project/vendor/archetype/animations/loaders/medium/medium_dark_static.png +0 -0
  164. data/templates/project/vendor/archetype/animations/loaders/medium/medium_static.png +0 -0
  165. data/templates/project/vendor/archetype/animations/loaders/small/small.png +0 -0
  166. data/templates/project/vendor/archetype/animations/loaders/small/small_dark.png +0 -0
  167. data/templates/project/vendor/archetype/animations/loaders/small/small_dark_static.png +0 -0
  168. data/templates/project/vendor/archetype/animations/loaders/small/small_static.png +0 -0
  169. data/templates/project/vendor/archetype/fontawesome-webfont.eot +0 -0
  170. data/templates/project/vendor/archetype/fontawesome-webfont.svg +0 -255
  171. data/templates/project/vendor/archetype/fontawesome-webfont.ttf +0 -0
  172. data/templates/project/vendor/archetype/fontawesome-webfont.woff +0 -0
  173. data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.eot +0 -0
  174. data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.svg +0 -255
  175. data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.ttf +0 -0
  176. data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.woff +0 -0
  177. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders-s7889ccc8c1.png +0 -0
  178. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large.png +0 -0
  179. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large_dark.png +0 -0
  180. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large_dark_static.png +0 -0
  181. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large_static.png +0 -0
  182. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium.png +0 -0
  183. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium_dark.png +0 -0
  184. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium_dark_static.png +0 -0
  185. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium_static.png +0 -0
  186. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small.png +0 -0
  187. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small_dark.png +0 -0
  188. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small_dark_static.png +0 -0
  189. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small_static.png +0 -0
  190. data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/sprites/hovercard_tip.png +0 -0
  191. data/test/fixtures/stylesheets/archetype/config.rb +0 -21
  192. data/test/fixtures/stylesheets/archetype/source/b.scss +0 -9
  193. data/test/fixtures/stylesheets/archetype/source/base.scss +0 -3
  194. data/test/fixtures/stylesheets/archetype/source/hacks/ie_pseudo.scss +0 -13
  195. data/test/fixtures/stylesheets/archetype/source/hacks/transparent_focusable.scss +0 -5
  196. data/test/fixtures/stylesheets/archetype/source/locale.scss +0 -43
  197. data/test/fixtures/stylesheets/archetype/source/styleguide/alerts.scss +0 -21
  198. data/test/fixtures/stylesheets/archetype/source/styleguide/buttons.scss +0 -18
  199. data/test/fixtures/stylesheets/archetype/source/styleguide/drop.scss +0 -101
  200. data/test/fixtures/stylesheets/archetype/source/styleguide/extend.scss +0 -24
  201. data/test/fixtures/stylesheets/archetype/source/styleguide/fallback_styles.scss +0 -23
  202. data/test/fixtures/stylesheets/archetype/source/styleguide/invalid_structures.scss +0 -85
  203. data/test/fixtures/stylesheets/archetype/source/styleguide/multi_value.scss +0 -18
  204. data/test/fixtures/stylesheets/archetype/source/styleguide/nested_styleguides.scss +0 -40
  205. data/test/fixtures/stylesheets/archetype/source/styleguide/selective_state.scss +0 -22
  206. data/test/fixtures/stylesheets/archetype/source/ui/glyph_icon.scss +0 -35
  207. data/test/fixtures/stylesheets/archetype/source/ui/hide_element.scss +0 -5
  208. data/test/fixtures/stylesheets/archetype/source/ui/stroke.scss +0 -13
  209. data/test/fixtures/stylesheets/archetype/source/ui/triangle.scss +0 -13
  210. data/test/fixtures/stylesheets/archetype/source/utilities/associative.scss +0 -24
  211. data/test/fixtures/stylesheets/archetype/source/utilities/custom_output_styler.scss +0 -22
  212. data/test/fixtures/stylesheets/archetype/source/utilities/if-set.scss +0 -16
  213. data/test/fixtures/stylesheets/archetype/source/utilities/spacing/horizontal-spacing.scss +0 -27
  214. data/test/fixtures/stylesheets/archetype/source/utilities/spacing/vertical-spacing.scss +0 -27
  215. data/test/fixtures/stylesheets/archetype/source/utilities/styles/filter.scss +0 -9
  216. data/test/fixtures/stylesheets/archetype/source/utilities/styles/font-family.scss +0 -9
  217. data/test/fixtures/stylesheets/archetype/source/utilities/styles/z-index.scss +0 -18
  218. data/test/fixtures/stylesheets/archetype/source/utilities/targeting/target-browser.scss +0 -77
  219. data/test/fixtures/stylesheets/archetype/source/utilities/targeting/target-os.scss +0 -42
  220. data/test/fixtures/stylesheets/archetype/tmp/b.css +0 -14
  221. data/test/fixtures/stylesheets/archetype/tmp/base.css +0 -349
  222. data/test/fixtures/stylesheets/archetype/tmp/hacks/ie_pseudo.css +0 -11
  223. data/test/fixtures/stylesheets/archetype/tmp/hacks/transparent_focusable.css +0 -4
  224. data/test/fixtures/stylesheets/archetype/tmp/locale.css +0 -23
  225. data/test/fixtures/stylesheets/archetype/tmp/styleguide/alerts.css +0 -711
  226. data/test/fixtures/stylesheets/archetype/tmp/styleguide/buttons.css +0 -2119
  227. data/test/fixtures/stylesheets/archetype/tmp/styleguide/drop.css +0 -63
  228. data/test/fixtures/stylesheets/archetype/tmp/styleguide/extend.css +0 -11
  229. data/test/fixtures/stylesheets/archetype/tmp/styleguide/fallback_styles.css +0 -10
  230. data/test/fixtures/stylesheets/archetype/tmp/styleguide/invalid_structures.css +0 -21
  231. data/test/fixtures/stylesheets/archetype/tmp/styleguide/multi_value.css +0 -13
  232. data/test/fixtures/stylesheets/archetype/tmp/styleguide/nested_styleguides.css +0 -28
  233. data/test/fixtures/stylesheets/archetype/tmp/styleguide/selective_state.css +0 -177
  234. data/test/fixtures/stylesheets/archetype/tmp/ui/glyph_icon.css +0 -127
  235. data/test/fixtures/stylesheets/archetype/tmp/ui/hide_element.css +0 -8
  236. data/test/fixtures/stylesheets/archetype/tmp/ui/stroke.css +0 -17
  237. data/test/fixtures/stylesheets/archetype/tmp/ui/triangle.css +0 -35
  238. data/test/fixtures/stylesheets/archetype/tmp/utilities/associative.css +0 -9
  239. data/test/fixtures/stylesheets/archetype/tmp/utilities/custom_output_styler.css +0 -8
  240. data/test/fixtures/stylesheets/archetype/tmp/utilities/if-set.css +0 -9
  241. data/test/fixtures/stylesheets/archetype/tmp/utilities/spacing/horizontal-spacing.css +0 -29
  242. data/test/fixtures/stylesheets/archetype/tmp/utilities/spacing/vertical-spacing.css +0 -29
  243. data/test/fixtures/stylesheets/archetype/tmp/utilities/styles/filter.css +0 -11
  244. data/test/fixtures/stylesheets/archetype/tmp/utilities/styles/font-family.css +0 -16
  245. data/test/fixtures/stylesheets/archetype/tmp/utilities/styles/z-index.css +0 -15
  246. data/test/fixtures/stylesheets/archetype/tmp/utilities/targeting/target-browser.css +0 -105
  247. data/test/fixtures/stylesheets/archetype/tmp/utilities/targeting/target-os.css +0 -55
  248. data/test/helpers/diff.rb +0 -49
  249. data/test/helpers/io.rb +0 -36
  250. data/test/helpers/test_case.rb +0 -62
  251. data/test/integrations/archetype_test.rb +0 -126
  252. data/test/test_helper.rb +0 -26
  253. data/test/units/sass_extensions_test.rb +0 -200
@@ -11,16 +11,12 @@ module Archetype::SassExtensions::Locale
11
11
  # - {String|Boolean} the current locale or whether or not the current locale is in the test set
12
12
  #
13
13
  def locale(locales = nil)
14
- locale = (Compass.configuration.locale || 'en_US').to_s
14
+ locale = get_locale(locale)
15
15
  # if the locales are nil, just return the current locale
16
- return Sass::Script::String.new(locale) if locales.nil?
16
+ return identifier(locale) if locales.nil?
17
17
  locales = locales.to_a.collect{|i| i.to_s}
18
- # add wild card support for language or territory
19
- match = locale.match(LOCALE_PATTERN)
20
- # language with wildcard territory
21
- language = match[1] + '_'
22
- # territory with wildcard language
23
- territory = '_' + match[2]
18
+ # normalize the pieces of the locale
19
+ locale = normalize_locale(locale)
24
20
  # for each item, look it up in the alias list
25
21
  locales.each do |key|
26
22
  if a = locale_aliases[key]
@@ -28,35 +24,123 @@ module Archetype::SassExtensions::Locale
28
24
  locales.concat(a)
29
25
  end
30
26
  end
31
- return Sass::Script::Bool.new(locales.include?(locale) || locales.include?(language) || locales.include?(territory))
27
+ return Sass::Script::Bool.new(
28
+ locales.include?(locale) ||
29
+ locales.include?("#{locale[:language]}_#{locale[:territory]}") ||
30
+ locales.include?(locale[:language] + '_') ||
31
+ locales.include?('_' + locale[:territory])
32
+ )
32
33
  end
34
+ alias_method :lang, :locale
33
35
 
34
36
  #
35
- # test a list of locales against the current locale (this is now just an alias for locales(), for back-compat)
37
+ # returns the locale language code
36
38
  #
37
39
  # *Parameters*:
38
- # - <tt>$locales</tt> {List} the list of locales to test
40
+ # - <tt>$locale</tt> {String} the locale to examine
41
+ # *Returns*:
42
+ # - {String|Null} the language code within the locale string
43
+ #
44
+ def locale_language(locale = nil)
45
+ return get_locale_piece(locale, :language)
46
+ end
47
+
48
+ #
49
+ # returns the locale territory code
50
+ #
51
+ # *Parameters*:
52
+ # - <tt>$locale</tt> {String} the locale to examine
53
+ # *Returns*:
54
+ # - {String|Null} the territory code within the locale string
55
+ #
56
+ def locale_territory(locale = nil)
57
+ return get_locale_piece(locale, :territory)
58
+ end
59
+ alias_method :locale_country, :locale_territory
60
+
61
+ #
62
+ # returns the locale modifier
63
+ #
64
+ # *Parameters*:
65
+ # - <tt>$locale</tt> {String} the locale to examine
39
66
  # *Returns*:
40
- # - {Boolean} is the current locale in the list or not
67
+ # - {String|Null} the modifier code within the locale string
41
68
  #
42
- def lang(locales)
43
- return locale(locales)
69
+ def locale_modifier(locale = nil)
70
+ return get_locale_piece(locale, :modifier)
44
71
  end
45
72
 
46
73
  #
47
- # get the current reading direction
74
+ # temporarily switch the interface locale
48
75
  #
76
+ # *Parameters*:
77
+ # - <tt>$code</tt> {String} the locale code to switch to
49
78
  # *Returns*:
50
- # - {String} is the current reading direction [ltr|rtl]
79
+ # - {String} the previously set locale code
51
80
  #
52
- def reading_direction
53
- direction = Compass.configuration.reading || 'ltr'
54
- return Sass::Script::String.new(direction == 'rlt' ? 'rtl' : 'ltr')
81
+ def switch_locale(locale)
82
+ previous = identifier(get_locale())
83
+ environment.global_env.set_var('CONFIG_LOCALE', locale)
84
+ return previous
55
85
  end
56
86
 
57
87
  private
58
88
 
59
- LOCALE_PATTERN = /([a-z]{2})[-_]?([a-z]{2}?)/i
89
+ # pieces of the locale code
90
+ # (1) language
91
+ # (2) territory
92
+ # (3) encoding (not currently used)
93
+ # (4) modifier (e.g. @Cyrillic)
94
+ LOCALE_PATTERN = /\"?([a-z]{2})?[-_]?([a-z]{2})?(\.[^@]*)?(?:\@([^\"]+))?\"?/i
95
+
96
+ #
97
+ # normalizes the locale string into an object
98
+ #
99
+ # *Parameters*:
100
+ # - <tt>locale</tt> {String} the locale to normalize
101
+ # *Returns*:
102
+ # - {Hash} the normalized locale object
103
+ #
104
+ def normalize_locale(locale = nil)
105
+ match = get_locale(locale).match(LOCALE_PATTERN) || []
106
+ return {
107
+ :language => match[1].nil? ? nil : match[1].downcase,
108
+ :territory => match[2].nil? ? nil : match[2].upcase,
109
+ :encoding => match[3],
110
+ :modifier => match[4]
111
+ }
112
+ end
113
+
114
+ #
115
+ # get the locale from the given input
116
+ # if nil, will use either the current global locale in $CONFIG_LOCALE or the locale set on the compiler
117
+ #
118
+ # *Parameters*:
119
+ # - <tt>locale</tt> {Sass::String} the locale to use
120
+ # *Returns*:
121
+ # - {String} the locale string
122
+ #
123
+ def get_locale(locale = nil)
124
+ return (locale || environment.var('CONFIG_LOCALE') || Compass.configuration.locale || 'en_US').to_s
125
+ end
126
+
127
+ #
128
+ # returns a normalized piece of the locale
129
+ #
130
+ # *Parameters*:
131
+ # - <tt>locale</tt> {String} the locale to examine
132
+ # - <tt>piece</tt> {Symbol} the piece of the locale to extract
133
+ # *Returns*:
134
+ # - {Sass::String} a string of the locale piece requested
135
+ #
136
+ def get_locale_piece(locale = nil, piece = :language)
137
+ piece = normalize_locale(locale)[piece]
138
+ if piece.nil?
139
+ return null
140
+ else
141
+ return identifier(piece)
142
+ end
143
+ end
60
144
 
61
145
  #
62
146
  # provides an alias mapping for locale names
@@ -64,14 +148,9 @@ private
64
148
  # *Returns*:
65
149
  # - {Hash} a hash of aliases
66
150
  #
67
- # TODO - make this easily extensible
68
151
  def locale_aliases
69
- if @locale_aliases.nil?
70
- a = {
71
- 'CJK' => ['ja_JP', 'ko_KR', 'zh_TW', 'zh_CN']
72
- }
73
- @locale_aliases = a
74
- end
75
- return @locale_aliases
152
+ @locale_aliases ||= {
153
+ 'CJK' => ['ja_JP', 'ko_KR', 'zh_TW', 'zh_CN']
154
+ }.merge(Compass.configuration.locale_aliases || {})
76
155
  end
77
156
  end
@@ -1,7 +1,14 @@
1
1
  #
2
- # This module provides a set of Sass functions for working with Sass::Number
2
+ # This module provides a set of Sass functions for working with Sass::Script::Value::Number
3
3
  #
4
4
  module Archetype::SassExtensions::Numbers
5
+
6
+ RESOLUTIONS = {
7
+ 'dpi' => 96.0, # dots per inch
8
+ 'dpcm' => 2.54 * 96.0, # dots per centimeter
9
+ 'dppx' => 1.0 # dots per pixel
10
+ }
11
+
5
12
  #
6
13
  # remove the units from a number
7
14
  #
@@ -12,8 +19,115 @@ module Archetype::SassExtensions::Numbers
12
19
  #
13
20
  def strip_units(number)
14
21
  value = 0
15
- value = number.value.to_f if number.is_a?(Sass::Script::String)
16
- value = number.value if number.is_a?(Sass::Script::Number)
17
- return Sass::Script::Number.new(value)
22
+ value = number.value.to_f if number.is_a?(Sass::Script::Value::String)
23
+ value = number.value if number.is_a?(Sass::Script::Value::Number)
24
+ return number(value)
25
+ end
26
+
27
+ #
28
+ # converts a decimal number into a fraction
29
+ # credit goes to Christopher Lord (https://github.com/clord/fraction)
30
+ #
31
+ # *Parameters*:
32
+ # - <tt>$number</tt> {Number} the number to convert
33
+ # *Returns*:
34
+ # - {String} the number represented as a fraction
35
+ #
36
+ def to_fraction(number)
37
+ assert_type number, :Number
38
+ numerator = m22 = 1
39
+ m12 = denominator = 0
40
+ x = number.value
41
+ while denominator * (ai = x.to_i) + m22 <= 10
42
+ m12, numerator = [numerator, (numerator * ai + m12).to_i]
43
+ m22, denominator = [denominator, (denominator * ai + m22).to_i]
44
+ break if (x == ai) || (x - ai).abs < 0.000000000001
45
+ x = 1.0 / (x - ai)
46
+ end
47
+ return identifier(numerator.to_s + '/' + denominator.to_s)
48
+ end
49
+
50
+ #
51
+ # converts any valid resolution value into a given resolution
52
+ #
53
+ # *Parameters*:
54
+ # - <tt>$number</tt> {Number} the resolution to convert from
55
+ # - <tt>$unit</tt> {String} the destination unit to convert to
56
+ # *Returns*:
57
+ # - {Number} the resolution in the destination unit
58
+ #
59
+ def resolution_to_x(number, unit = 'ratio')
60
+ assert_type number, :Number
61
+ ratio = 'ratio'
62
+
63
+ to = (unit.respond_to?(:value) ? unit.value : unit).to_s
64
+ from = number.unit_str.to_s
65
+ unitless = number.unitless?
66
+
67
+ # nothing to do if we're already in the correct format
68
+ return number if ((from == to) || (unitless && to == ratio))
69
+
70
+ # if we don't understand the unit...
71
+ if RESOLUTIONS[from].nil? and not unitless
72
+ # warn
73
+ helpers.warn("[#{Archetype.name}:resolution] don't know how to convert `#{number}` to a #{to}")
74
+ # and return zero
75
+ return number(0)
76
+ end
77
+
78
+ # convert it to a unitless ratio
79
+ number = number.value.to_f / (RESOLUTIONS[from] || 1.0)
80
+ # return early if we're looking for a ratio
81
+ return number(number) if to == ratio
82
+ # otherwise convert to desination unit
83
+ return number(number * RESOLUTIONS[to], to)
84
+ end
85
+
86
+ #
87
+ # converts any valid resolution value into a ratio
88
+ #
89
+ # *Parameters*:
90
+ # - <tt>$number</tt> {Number} the resolution to convert
91
+ # *Returns*:
92
+ # - {Number} the resolution as a ratio
93
+ #
94
+ def resolution_to_ratio(number)
95
+ return resolution_to_x(number, 'ratio')
96
+ end
97
+
98
+ #
99
+ # converts any valid resolution value into dppx (dots per pixel)
100
+ #
101
+ # *Parameters*:
102
+ # - <tt>$number</tt> {Number} the resolution to convert
103
+ # *Returns*:
104
+ # - {Number} the resolution as dppx
105
+ #
106
+ def resolution_to_dppx(number)
107
+ return resolution_to_x(number, 'dppx')
108
+ end
109
+
110
+ #
111
+ # converts any valid resolution value into dpi (dots per inch)
112
+ #
113
+ # *Parameters*:
114
+ # - <tt>$number</tt> {Number} the resolution to convert
115
+ # *Returns*:
116
+ # - {Number} the resolution as dpi
117
+ #
118
+ def resolution_to_dpi(number)
119
+ return resolution_to_x(number, 'dpi')
120
+ end
121
+
122
+ #
123
+ # converts any valid resolution value into dpcm (dots per centimeters)
124
+ #
125
+ # *Parameters*:
126
+ # - <tt>$number</tt> {Number} the resolution to convert
127
+ # *Returns*:
128
+ # - {Number} the resolution as dpcm
129
+ #
130
+ def resolution_to_dpcm(number)
131
+ return resolution_to_x(number, 'dpcm')
18
132
  end
19
133
  end
@@ -0,0 +1,53 @@
1
+ #
2
+ # This module provides a set of Sass functions for working with Sass::Script::Value::String
3
+ #
4
+ module Archetype::SassExtensions::Strings
5
+ #
6
+ # replace a substring within a string
7
+ #
8
+ # *Parameters*:
9
+ # - <tt>$haystack</tt> {String} the string to search within
10
+ # - <tt>$needle</tt> {String} the string to match
11
+ # - <tt>$replacement</tt> {String} the string to substitute in
12
+ # - <tt>$all</tt> {Boolean} whether or not to replace all occurances
13
+ # *Returns*:
14
+ # - {String} the string with replaced value
15
+ #
16
+ def str_replace(haystack, needle, replacement, all = false)
17
+ method = all ? :gsub : :sub
18
+ str = helpers.to_str(haystack, ' ', :quotes)
19
+ needle = helpers.to_str(needle, ' ', :quotes)
20
+ replacement = helpers.to_str(replacement, ' ', :quotes)
21
+ str = str.method(method).call(needle, replacement)
22
+ return identifier(str)
23
+ end
24
+ Sass::Script::Functions.declare :str_replace, [:haystack, :needle, :replacement]
25
+ Sass::Script::Functions.declare :str_replace, [:haystack, :needle, :replacement, :all]
26
+
27
+ #
28
+ # given a string and a map of key-values, replace any {key}'s with the associated value
29
+ #
30
+ # *Parameters*:
31
+ # - <tt>$str</tt> {String} the string to subsititute within
32
+ # - <tt>$subsitutions</tt> {Map} the map of key-value pairs to substitute
33
+ # *Returns*:
34
+ # - {String} the string with substituted values
35
+ #
36
+ def str_substitute(str, subsitutions = nil)
37
+ return identifier('') if str == null
38
+ return str if subsitutions.nil?
39
+ subsitutions = subsitutions.to_h
40
+ str = helpers.to_str(str, ' ', :quotes)
41
+ # for each key-value pair...
42
+ subsitutions.each do |key, value|
43
+ # replace all instances of the placeholder `{key}` with the value
44
+ begin
45
+ str = str.gsub("{#{key}}", helpers.to_str(value, ' ', :quotes))
46
+ rescue
47
+ end
48
+ end
49
+ identifier(str)
50
+ end
51
+ Sass::Script::Functions.declare :str_substitute, [:string]
52
+ Sass::Script::Functions.declare :str_substitute, [:string, :subsitutions]
53
+ end
@@ -1,37 +1,23 @@
1
- require 'archetype/functions/helpers'
2
1
  require 'archetype/functions/styleguide_memoizer'
3
2
  require 'thread'
4
3
 
4
+ %w(components constants grammar helpers resolve styles themes).each do |dep|
5
+ require "archetype/sass_extensions/functions/styleguide/#{dep}"
6
+ end
7
+
5
8
  #
6
9
  # This is the magic of Archetype. This module provides the interfaces for constructing,
7
10
  # extending, and retrieving reusable UI components
8
11
  #
9
12
  module Archetype::SassExtensions::Styleguide
10
13
 
11
- # :stopdoc:
12
- INHERIT = 'inherit'
13
- STYLEGUIDE = 'styleguide'
14
- DROP = 'drop'
15
- DEFAULT = 'default'
16
- REGEX = 'regex'
17
- SPECIAL = %w(states selectors)
18
- DROPALL = %w(all true)
19
- # these are unique CSS keys that can be exploited to provide fallback functionality by providing a second value
20
- # e.g color: red; color: rgba(255,0,0, 0.8);
21
- FALLBACKS = %w(background background-image background-color border border-bottom border-bottom-color border-color border-left border-left-color border-right border-right-color border-top border-top-color clip color layer-background-color outline outline-color white-space extend)
22
- # these are mixins that make sense to run multiple times within a block
23
- MULTIMIXINS = %w(target-browser)
24
- ADDITIVES = FALLBACKS + [DROP, INHERIT, STYLEGUIDE] + MULTIMIXINS
25
- @@archetype_styleguide_mutex = Mutex.new
26
- # :startdoc:
27
-
28
14
  #
29
15
  # interface for adding new components to the styleguide structure
30
16
  #
31
17
  # *Parameters*:
32
18
  # - <tt>$id</tt> {String} the component identifier
33
- # - <tt>$data</tt> {List} the component data object
34
- # - <tt>$default</tt> {List} the default data object (for extending)
19
+ # - <tt>$data</tt> {Map|List} the component data object
20
+ # - <tt>$default</tt> {Map|List} the default data object (for extending)
35
21
  # - <tt>$theme</tt> {String} the theme to insert the component into
36
22
  # - <tt>$force</tt> {Boolean} if true, forcibly insert the component
37
23
  # *Returns*:
@@ -47,7 +33,7 @@ module Archetype::SassExtensions::Styleguide
47
33
  # if we already have the component, don't create it again
48
34
  return Sass::Script::Bool.new(false) if component_exists(id, theme, nil, force)
49
35
  # otherwise add it
50
- components[id] = helpers.list_to_hash(default, 1, SPECIAL, ADDITIVES).merge(helpers.list_to_hash(data, 1, SPECIAL, ADDITIVES))
36
+ components[id] = helpers.data_to_hash(default, 1, SPECIAL, ADDITIVES).merge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
51
37
  return Sass::Script::Bool.new(true)
52
38
  end
53
39
  end
@@ -75,11 +61,11 @@ module Archetype::SassExtensions::Styleguide
75
61
  # if force was set, we'll create a random token for the name
76
62
  extension = rand(36**8).to_s(36) if force
77
63
  # convert the extension into a hash (if we don't have an extension, compose one out of its data)
78
- extension = helpers.to_str(extension || data)
64
+ extension = helpers.to_str(extension || data).hash
79
65
  extensions = theme[:extensions]
80
66
  return Sass::Script::Bool.new(false) if component_exists(id, theme, extension, force)
81
67
  extensions.push(extension)
82
- components[id] = (components[id] ||= Archetype::Hash.new).rmerge(helpers.list_to_hash(data, 1, SPECIAL, ADDITIVES))
68
+ components[id] = (components[id] ||= Archetype::Hash.new).rmerge(helpers.data_to_hash(data, 1, SPECIAL, ADDITIVES))
83
69
  return Sass::Script::Bool.new(true)
84
70
  end
85
71
  end
@@ -101,7 +87,7 @@ module Archetype::SassExtensions::Styleguide
101
87
  #
102
88
  def styleguide_component_exists(id, theme = nil, extension = nil, force = false)
103
89
  @@archetype_styleguide_mutex.synchronize do
104
- extension = helpers.to_str(extension) if not extension.nil?
90
+ extension = helpers.to_str(extension).hash if not extension.nil?
105
91
  return Sass::Script::Bool.new( component_exists(id, theme, extension, force) )
106
92
  end
107
93
  end
@@ -114,381 +100,63 @@ module Archetype::SassExtensions::Styleguide
114
100
  # given a description of the component, convert it into CSS
115
101
  #
116
102
  # *Parameters*:
117
- # - <tt>$description</tt> {String|List} the description of the component
103
+ # - <tt>$description</tt> {String|List|Map} the description of the component
118
104
  # - <tt>$theme</tt> {String} the theme to use
119
105
  # *Returns*:
120
- # - {List} a key-value paired list of styles
106
+ # - {Map} a map of styles
121
107
  #
122
- def styleguide(description, state = 'false', theme = nil)
108
+ def _styleguide(description, state = nil, theme = nil)
123
109
  @@archetype_styleguide_mutex.synchronize do
124
- # convert it back to a Sass:List and carry on
125
- return helpers.hash_to_list(get_styles(description, theme, state), 0)
110
+ styles = get_styles(description, theme, state)
111
+ styles = resolve_runtime_locale_values(styles)
112
+ # convert it back to a Sass:Map and carry on
113
+ return helpers.hash_to_map(styles)
126
114
  end
127
115
  end
128
116
 
129
117
  #
130
- # output the CSS differences between components
118
+ # returns the CSS differences between components
131
119
  #
132
120
  # *Parameters*:
133
- # - <tt>$original</tt> {String|List} the description of the original component
134
- # - <tt>$other</tt> {String|List} the description of the new component
135
- # - <tt>$theme</tt> {String} the theme to use
121
+ # - <tt>$original</tt> {String|List|Map} the description or map representation of the original component
122
+ # - <tt>$other</tt> {String|List|Map} the description or map representation of the new component
136
123
  # *Returns*:
137
124
  # - {List} a key-value paired list of styles
138
125
  #
139
- def styleguide_diff(original, other, theme = nil)
126
+ def styleguide_diff(original, other)
140
127
  @@archetype_styleguide_mutex.synchronize do
141
- original = get_styles(original, theme)
142
- other = get_styles(other, theme)
128
+ # normalize our input (for back-compat)
129
+ original = normalize_styleguide_definition(original)
130
+ other = normalize_styleguide_definition(other)
131
+ # compute the difference
143
132
  diff = original.diff(other)
144
- return helpers.hash_to_list(diff, 0)
145
- end
146
- end
147
-
148
- private
149
- def helpers
150
- @helpers ||= Archetype::Functions::Helpers
151
- end
152
- def memoizer
153
- Archetype::Functions::StyleguideMemoizer
154
- end
155
-
156
- #
157
- # given a sentence, deconstruct it into it's identifier and verbages
158
- #
159
- # *Parameters*:
160
- # - <tt>sentence</tt> {String|List} the sentence describing the component
161
- # - <tt>theme</tt> {String} the theme to use
162
- # - <tt>state</tt> {String} the name of a state to return
163
- # *Returns*:
164
- # - {Array} an array containing the identifer, modifiers, and a token
165
- #
166
- def grammar(sentence, theme = nil, state = 'false')
167
- theme = get_theme(theme)
168
- components = theme[:components]
169
- # get a list of valid ids
170
- styleguideIds = components.keys
171
- sentence = sentence.split if sentence.is_a? String
172
- sentence = sentence.to_a
173
- id = nil
174
- modifiers = []
175
- if not sentence.empty?
176
- prefix = ''
177
- order = ''
178
- # these define various attributes for modifiers (e.g. `button with a shadow`)
179
- extras = %w(on with without)
180
- # these are things that are useless to us, so we just leave them out
181
- ignore = %w(a an also the this that is was it)
182
- # these are our context switches (e.g. `headline in a button`)
183
- contexts = %w(in)
184
- sentence.each do |item|
185
- item = item.value
186
- # find the ID
187
- if id.nil? and styleguideIds.include?(item) and prefix.empty? and order.empty?
188
- id = item
189
- # if it's a `context`, we need to increase the depth and reset the prefix
190
- elsif contexts.include?(item)
191
- order = "#{item}-#{order}"
192
- prefix = ''
193
- # if it's an `extra`, we update the prefix
194
- elsif extras.include?(item)
195
- prefix = "#{item}-"
196
- # finally, check that it's not on the ignore (useless) list. if it is, we just skip over it
197
- # (maybe this should be the first thing we check?)
198
- elsif not ignore.include?(item)
199
- modifiers.push("#{order}#{prefix}#{item}")
200
- end
201
- end
202
- end
203
- # if there was no id, return a list of valid IDs for reporting
204
- modifiers = styleguideIds if id.nil?
205
- # get the list of currenty installed component extensions
206
- extensions = theme[:extensions] if not id.nil?
207
- # TODO - low - eoneill: make sure we always want to return unique modifiers
208
- # i can't think of a case where we wouldn't want to remove dups
209
- # maybe in the case where we're looking for strict keys on the lookup?
210
- modifiers = modifiers.uniq
211
- token = memoizer.tokenize(theme[:name], extensions, id, modifiers, state)
212
- return id, modifiers, token
213
- end
214
-
215
- #
216
- # interface for extracting styles in the styleguide references
217
- #
218
- # *Parameters*:
219
- # - <tt>id</tt> {String} the component identifier
220
- # - <tt>modifiers</tt> {Array} the component modifiers
221
- # - <tt>strict</tt> {Boolean} is it a strict lookup?
222
- # - <tt>theme</tt> {String} the theme to use
223
- # - <tt>context</tt> {Hash} the context to work in
224
- # *Returns*:
225
- # - {Hash} a hash of the extracted styles
226
- #
227
- def extract_styles(id, modifiers, strict = false, theme = nil, context = nil)
228
- theme = get_theme(theme)
229
- context ||= theme[:components][id] || Archetype::Hash.new
230
- modifiers = helpers.to_str(modifiers)
231
- return Archetype::Hash.new if context.nil? or context.empty?
232
- # push on the defaults first
233
- out = (strict ? resolve_dependents(id, context[modifiers], theme[:name], context) : context[DEFAULT]) || Archetype::Hash.new
234
- out = out.clone
235
- # if it's not strict, find anything that matched
236
- if not strict
237
- modifiers = modifiers.split
238
- context.each do |key, definition|
239
- definition = [key, definition]
240
- modifier = definition[0]
241
- if modifier != DEFAULT
242
- match = true
243
- modifier = modifier.split
244
- if modifier[0] == REGEX
245
- # if it's a regex pattern, test if it matches
246
- match = modifiers.join(' ') =~ /#{modifier[1].gsub(/\A"|"\Z/, '')}/i
247
- else
248
- # otherwise, if the modifier isn't in our list of modifiers, it's not valid and just move on
249
- modifier.each { |i| match = false if not modifiers.include?(i) }
250
- end
251
- # if it matched, process it
252
- if match
253
- tmp = resolve_dependents(id, definition[1], theme[:name], nil, out)
254
- out, tmp = post_resolve_drops(out, tmp)
255
- out = out.rmerge(tmp)
256
- end
257
- end
258
- end
259
- end
260
- # recompose the special keys and extract any nested/inherited styles
261
- # this lets us define special states and elements
262
- SPECIAL.each do |special_key|
263
- if out.is_a? Hash
264
- special = out[special_key] || Archetype::Hash.new
265
- if special == 'nil'
266
- out[special_key] = Archetype::Hash.new
267
- else
268
- tmp = Archetype::Hash.new
269
- special.each { |key, value| tmp[key] = extract_styles(key, key, true, theme[:name], special) }
270
- out[special_key] = tmp if not tmp.empty?
271
- end
272
- end
273
- end
274
- # check for nested styleguides
275
- styleguide = out[STYLEGUIDE]
276
- if not (styleguide.nil? or styleguide.empty?)
277
- styles = get_styles(styleguide, theme[:name])
278
- out.delete(STYLEGUIDE)
279
- out = styles.rmerge(out)
280
- end
281
- return out
282
- end
283
-
284
- #
285
- # given two objects, resolve the chain of dropped styles
286
- # this runs after having already resolved the dropped styles and merged
287
- #
288
- # *Parameters*:
289
- # - <tt>obj</tt> {Hash} the source object
290
- # - <tt>merger</tt> {Hash} the object to be merged in
291
- # *Returns*:
292
- # - {Array.<Hash>} the resulting `obj` and `merger` objects
293
- #
294
- def post_resolve_drops(obj, merger)
295
- return [obj, merger] if obj.nil? or merger.nil?
296
- drop = merger[DROP]
297
- keys = obj.keys
298
- if not drop.nil?
299
- drop.to_a.each do |key|
300
- key = helpers.to_str(key)
301
- obj.delete(key) if not SPECIAL.include?(key)
302
- end
303
- merger.delete(DROP)
304
- else
133
+ # convert the individual messages in a comparison
134
+ original_message = helpers.get_meta_message(original).sub(MESSAGE_PREFIX, '').sub(MESSAGE_SUFFIX, '')
135
+ other_message = helpers.get_meta_message(other).sub(MESSAGE_PREFIX, '').sub(MESSAGE_SUFFIX, '')
136
+ diff = helpers.add_meta_message(diff, "#{MESSAGE_PREFIX}#{original_message}` vs `#{other_message}#{MESSAGE_SUFFIX}")
137
+ # and return it as a map
138
+ return helpers.hash_to_map(diff)
305
139
  end
306
- SPECIAL.each do |special|
307
- if obj[special].is_a?(Hash) and merger[special].is_a?(Hash)
308
- obj[special], merger[special] = post_resolve_drops(obj[special], merger[special])
309
- end
310
- end
311
- return [obj, merger]
312
140
  end
313
141
 
314
142
  #
315
- # given two objects, resolve the chain of dropped styles
143
+ # given a styleguide definition or object, extract specified styles
316
144
  #
317
145
  # *Parameters*:
318
- # - <tt>value</tt> {Hash} the source object
319
- # - <tt>obj</tt> {Hash} the object to be merged in
320
- # - <tt>is_special</tt> {Boolean} whether this is from a SPECIAL branch of a Hash
146
+ # - <tt>$definition</tt> {String|List} the description of the component
147
+ # - <tt>$properties</tt> {String|List} the properties to extract the derived styles for
148
+ # - <tt>$format</tt> {String} the format to return the results in [auto|map|list]
149
+ # - <tt>$strict</tt> {Boolean} if true, will only return an exact match, and not try to extrapolate the value
321
150
  # *Returns*:
322
- # - {Array.<Hash>} the resulting value
151
+ # - {List|Map|*} either a list/map of the values or the individual value itself
323
152
  #
324
- def resolve_drops(value, obj, is_special = false)
325
- return value if not (value.is_a?(Hash) and obj.is_a?(Hash))
326
- keys = obj.keys
327
- drop = value[DROP]
328
- if not drop.nil?
329
- tmp = Archetype::Hash.new
330
- if DROPALL.include?(helpers.to_str(drop))
331
- if not keys.nil?
332
- keys.each do |key|
333
- if SPECIAL.include?(key)
334
- if not (obj[key].nil? or obj[key].empty?)
335
- tmp[key] = Archetype::Hash.new
336
- tmp[key][DROP] = obj[key].keys
337
- end
338
- else
339
- tmp[key] = 'nil'
340
- end
341
- end
342
- end
343
- else
344
- drop.to_a.each do |key|
345
- key = helpers.to_str(key)
346
- if SPECIAL.include?(key)
347
- if not (obj[key].nil? or obj[key].empty?)
348
- tmp[key] = Archetype::Hash.new
349
- tmp[key][DROP] = obj[key].keys
350
- end
351
- else
352
- tmp[key] = 'nil'
353
- end
354
- end
355
- end
356
- value.delete(DROP) if not is_special
357
- value = tmp.rmerge(value)
358
- end
359
- value.each do |key|
360
- value[key] = resolve_drops(value[key], obj[key], key, SPECIAL.include?(key)) if not value[key].nil?
361
- end
362
- return value
363
- end
364
-
365
- #
366
- # resolve any dependent references from the component
367
- #
368
- # *Parameters*:
369
- # - <tt>id</tt> {String} the component identifier
370
- # - <tt>value</tt> {Hash} the current value
371
- # - <tt>theme</tt> {String} the theme to use
372
- # - <tt>context</tt> {Hash} the context to work in
373
- # - <tt>keys</tt> {Array} list of the external keys
374
- # *Returns*:
375
- # - {Hash} a hash of the resolved styles
376
- #
377
- def resolve_dependents(id, value, theme = nil, context = nil, obj = nil)
378
- # we have to create a clone here as the passed in value is volatile and we're performing destructive changes
379
- value = value.clone
380
- # check that we're dealing with a hash
381
- if value.is_a?(Hash)
382
- # check for dropped styles
383
- value = resolve_drops(value, obj)
384
-
385
- # check for inheritance
386
- inherit = value[INHERIT]
387
- if not (inherit.nil? or inherit.empty?)
388
- # create a temporary object and extract the nested styles
389
- tmp = Archetype::Hash.new
390
- inherit.each { |related| tmp = tmp.rmerge(extract_styles(id, related, true, theme, context)) }
391
- # remove the inheritance key and update the styles
392
- value.delete(INHERIT)
393
- value = tmp.rmerge(value)
394
- end
395
- end
396
- # return whatever we got
397
- return value
398
- end
399
-
400
- #
401
- # keep a registry of styleguide themes
402
- #
403
- # *Parameters*:
404
- # - <tt>theme</tt> {String} the theme to use
405
- # *Returns*:
406
- # - {Hash} the theme
407
- #
408
- def get_theme(theme)
409
- theme_name = helpers.to_str(theme || 'archetype')
410
- @@styleguide_themes ||= {}
411
- themes = @@styleguide_themes[theme_name] ||= {}
412
- cleanup_old_themes!(themes, options[:css_filename]) if rand < 0.333 # cleanup 1/3 of the time.
413
- theme = themes[options[:css_filename]] ||= {}
414
- theme[:name] ||= theme_name
415
- theme[:components] ||= {}
416
- theme[:extensions] ||= []
417
- return theme
418
- end
419
-
420
- def cleanup_old_themes!(themes, css_filename)
421
- themes.keys.each do |key|
422
- if key != css_filename
423
- themes.delete(key)
424
- end
425
- end
426
- nil
427
- end
428
-
429
- #
430
- # driver method for converting a sentence into a list of styles
431
- #
432
- # *Parameters*:
433
- # - <tt>description</tt> {String|List} the description of the component
434
- # - <tt>theme</tt> {String} the theme to use
435
- # - <tt>state</tt> {String} the name of a state to return
436
- # *Returns*:
437
- # - {Hash} the styles
438
- #
439
- def get_styles(description, theme = nil, state = 'false')
440
- state = helpers.to_str(state)
441
- styles = Archetype::Hash.new
442
- description.to_a.each do |sentence|
443
- # get the grammar from the sentence
444
- id, modifiers, token = grammar(sentence, theme, state)
445
- if id
446
- # check memoizer
447
- memoized = memoizer.fetch(theme, token)
448
- if memoized
449
- styles = styles.rmerge(memoized)
450
- else
451
- # fetch additional styles
452
- extracted = extract_styles(id, modifiers, false, theme)
453
- # we can delete anything that had a value of `nil` as we won't be outputting those
454
- extracted.delete_if { |k,v| helpers.is_value(v, :nil) }
455
- styles = styles.rmerge(extracted)
456
- memoizer.add(theme, token, extracted)
457
- end
458
- elsif not helpers.is_value(sentence, :nil)
459
- helpers.logger.record(:warning, "[archetype:styleguide:missing_identifier] `#{helpers.to_str(sentence)}` does not contain an identifier. please specify one of: #{modifiers.sort.join(', ')}")
460
- end
461
- end
462
- # now that we've collected all of our styles, if we requested a single state, merge that state upstream
463
- if state != 'false' and styles['states']
464
- state = styles['states'][state]
465
- # remove any nested/special keys
466
- SPECIAL.each do |special|
467
- styles.delete(special)
468
- end
469
- styles = styles.merge(state) if not (state.nil? or state.empty?)
153
+ def styleguide_derived_style(definition, properties = [], format = 'auto', strict = false)
154
+ @@archetype_styleguide_mutex.synchronize do
155
+ # normalize our input
156
+ definition = normalize_styleguide_definition(definition)
157
+ # get the computed styles
158
+ return derived_style(definition, properties, format, strict)
470
159
  end
471
- return styles
472
160
  end
473
161
 
474
- #
475
- # check whether or not a component (or a component extension) has already been defined
476
- #
477
- # *Parameters*:
478
- # - <tt>$id</tt> {String} the component identifier
479
- # - <tt>$data</tt> {List} the component data object
480
- # - <tt>$theme</tt> {String} the theme to insert the component into
481
- # - <tt>$extension</tt> {String} the name of the extension
482
- # - <tt>$force</tt> {Boolean} if true, forcibly extend the component
483
- # *Returns*:
484
- # - {Boolean} whether or not the component/extension exists
485
- #
486
- def component_exists(id, theme = nil, extension = nil, force = false)
487
- status = false
488
- theme = get_theme(theme) if not theme.is_a? Hash
489
- id = helpers.to_str(id)
490
- # determine the status of the component
491
- status = (extension.nil?) ? (not theme[:components][id].nil?) : theme[:extensions].include?(extension)
492
- return (status and not force and Compass.configuration.memoize)
493
- end
494
162
  end