archetype 0.0.1.pre.1 → 0.0.1.pre.3.00dfd9a
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +88 -0
- data/LICENSE +16 -0
- data/README.md +87 -1
- data/VERSION.yml +6 -0
- data/lib/README.rdoc +4 -0
- data/lib/archetype.rb +45 -0
- data/lib/archetype/functions.rb +9 -0
- data/lib/archetype/functions/hash.rb +149 -0
- data/lib/archetype/functions/helpers.rb +125 -0
- data/lib/archetype/functions/styleguide_memoizer.rb +61 -0
- data/lib/archetype/sass_extensions.rb +6 -0
- data/lib/archetype/sass_extensions/functions.rb +14 -0
- data/lib/archetype/sass_extensions/functions/environment.rb +14 -0
- data/lib/archetype/sass_extensions/functions/lists.rb +284 -0
- data/lib/archetype/sass_extensions/functions/locale.rb +77 -0
- data/lib/archetype/sass_extensions/functions/numbers.rb +19 -0
- data/lib/archetype/sass_extensions/functions/styleguide.rb +406 -0
- data/lib/archetype/sass_extensions/functions/ui.rb +59 -0
- data/lib/archetype/sass_extensions/functions/version.rb +95 -0
- data/lib/archetype/version.rb +75 -0
- data/stylesheets/_archetype.scss +2 -0
- data/stylesheets/archetype/_base.scss +46 -0
- data/stylesheets/archetype/_config.scss +366 -0
- data/stylesheets/archetype/_grid.scss +3 -0
- data/stylesheets/archetype/_hacks.scss +72 -0
- data/stylesheets/archetype/_init.scss +23 -0
- data/stylesheets/archetype/_styleguide.scss +6 -0
- data/stylesheets/archetype/_ui.scss +326 -0
- data/stylesheets/archetype/_util.scss +12 -0
- data/stylesheets/archetype/base/_h5bp.scss +307 -0
- data/stylesheets/archetype/base/_hybrid.scss +25 -0
- data/stylesheets/archetype/base/_normalize.scss +595 -0
- data/stylesheets/archetype/base/_reset.scss +72 -0
- data/stylesheets/archetype/grid/_config.scss +14 -0
- data/stylesheets/archetype/grid/_grid.scss +391 -0
- data/stylesheets/archetype/styleguide/_components.scss +25 -0
- data/stylesheets/archetype/styleguide/_helpers.scss +215 -0
- data/stylesheets/archetype/styleguide/_primitives.scss +10 -0
- data/stylesheets/archetype/styleguide/_styleguide.scss +41 -0
- data/stylesheets/archetype/styleguide/components/_alerts.scss +59 -0
- data/stylesheets/archetype/styleguide/components/_annotations.scss +27 -0
- data/stylesheets/archetype/styleguide/components/_bristol.scss +15 -0
- data/stylesheets/archetype/styleguide/components/_button_groups.scss +47 -0
- data/stylesheets/archetype/styleguide/components/_button_toolbars.scss +17 -0
- data/stylesheets/archetype/styleguide/components/_buttons.scss +338 -0
- data/stylesheets/archetype/styleguide/components/_canvas.scss +15 -0
- data/stylesheets/archetype/styleguide/components/_carets.scss +336 -0
- data/stylesheets/archetype/styleguide/components/_closes.scss +63 -0
- data/stylesheets/archetype/styleguide/components/_container.scss +27 -0
- data/stylesheets/archetype/styleguide/components/_copy.scss +85 -0
- data/stylesheets/archetype/styleguide/components/_flyouts.scss +52 -0
- data/stylesheets/archetype/styleguide/components/_headings.scss +33 -0
- data/stylesheets/archetype/styleguide/components/_headlines.scss +63 -0
- data/stylesheets/archetype/styleguide/components/_hovercards.scss +27 -0
- data/stylesheets/archetype/styleguide/components/_icons.scss +17 -0
- data/stylesheets/archetype/styleguide/components/_identities.scss +34 -0
- data/stylesheets/archetype/styleguide/components/_links.scss +66 -0
- data/stylesheets/archetype/styleguide/components/_loaders.scss +154 -0
- data/stylesheets/archetype/styleguide/components/_menu_items.scss +31 -0
- data/stylesheets/archetype/styleguide/components/_module.scss +15 -0
- data/stylesheets/archetype/styleguide/components/_pullquotes.scss +29 -0
- data/stylesheets/archetype/styleguide/components/_punchcut.scss +18 -0
- data/stylesheets/archetype/styleguide/components/_tooltips.scss +28 -0
- data/stylesheets/archetype/styleguide/primitives/_animations.scss +17 -0
- data/stylesheets/archetype/styleguide/primitives/_dimensions.scss +50 -0
- data/stylesheets/archetype/styleguide/primitives/_glyphs.scss +11 -0
- data/stylesheets/archetype/styleguide/primitives/_misc.scss +8 -0
- data/stylesheets/archetype/styleguide/primitives/_palettes.scss +94 -0
- data/stylesheets/archetype/styleguide/primitives/_shadows.scss +23 -0
- data/stylesheets/archetype/styleguide/primitives/_sprites.scss +46 -0
- data/stylesheets/archetype/styleguide/primitives/_textures.scss +10 -0
- data/stylesheets/archetype/styleguide/primitives/_typography.scss +56 -0
- data/stylesheets/archetype/util/_debug.scss +40 -0
- data/stylesheets/archetype/util/_lists.scss +57 -0
- data/stylesheets/archetype/util/_misc.scss +108 -0
- data/stylesheets/archetype/util/_rtl.scss +279 -0
- data/stylesheets/archetype/util/_spacing.scss +78 -0
- data/stylesheets/archetype/util/_styles.scss +466 -0
- data/stylesheets/archetype/util/_targeting.scss +210 -0
- data/stylesheets/archetype/util/_units.scss +18 -0
- data/templates/example/index.html +40 -0
- data/templates/example/manifest.rb +13 -0
- data/templates/example/screen.scss +99 -0
- data/templates/example/vendor/archetype/animations/loaders/large/large.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/large/large_dark.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/large/large_dark_static.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/large/large_static.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/medium/medium.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/medium/medium_dark.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/medium/medium_dark_static.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/medium/medium_static.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/small/small.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/small/small_dark.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/small/small_dark_static.png +0 -0
- data/templates/example/vendor/archetype/animations/loaders/small/small_static.png +0 -0
- data/templates/example/vendor/archetype/fontawesome-webfont.eot +0 -0
- data/templates/example/vendor/archetype/fontawesome-webfont.svg +255 -0
- data/templates/example/vendor/archetype/fontawesome-webfont.ttf +0 -0
- data/templates/example/vendor/archetype/fontawesome-webfont.woff +0 -0
- data/templates/project/manifest.rb +9 -0
- data/templates/project/screen.scss +1 -0
- data/templates/project/vendor/archetype/animations/loaders/large/large.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/large/large_dark.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/large/large_dark_static.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/large/large_static.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/medium/medium.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/medium/medium_dark.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/medium/medium_dark_static.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/medium/medium_static.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/small/small.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/small/small_dark.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/small/small_dark_static.png +0 -0
- data/templates/project/vendor/archetype/animations/loaders/small/small_static.png +0 -0
- data/templates/project/vendor/archetype/fontawesome-webfont.eot +0 -0
- data/templates/project/vendor/archetype/fontawesome-webfont.svg +255 -0
- data/templates/project/vendor/archetype/fontawesome-webfont.ttf +0 -0
- data/templates/project/vendor/archetype/fontawesome-webfont.woff +0 -0
- data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.eot +0 -0
- data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.svg +255 -0
- data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/test/fixtures/stylesheets/archetype/assets/fonts/fontawesome-webfont.woff +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large_dark.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large_dark_static.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/large/large_static.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium_dark.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium_dark_static.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/medium/medium_static.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small_dark.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small_dark_static.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/animations/loaders/small/small_static.png +0 -0
- data/test/fixtures/stylesheets/archetype/assets/images/vendor/archetype/sprites/hovercard_tip.png +0 -0
- data/test/fixtures/stylesheets/archetype/config.rb +19 -0
- data/test/fixtures/stylesheets/archetype/expected/b.css +14 -0
- data/test/fixtures/stylesheets/archetype/expected/base.css +349 -0
- data/test/fixtures/stylesheets/archetype/expected/hacks/ie_pseudo.css +11 -0
- data/test/fixtures/stylesheets/archetype/expected/locale.css +23 -0
- data/test/fixtures/stylesheets/archetype/expected/styleguide/buttons.css +2091 -0
- data/test/fixtures/stylesheets/archetype/expected/styleguide/fallback_styles.css +9 -0
- data/test/fixtures/stylesheets/archetype/expected/styleguide/nested_styleguides.css +24 -0
- data/test/fixtures/stylesheets/archetype/expected/styleguide/selective_state.css +174 -0
- data/test/fixtures/stylesheets/archetype/expected/ui/glyph_icon.css +37 -0
- data/test/fixtures/stylesheets/archetype/expected/ui/hide_element.css +8 -0
- data/test/fixtures/stylesheets/archetype/expected/ui/stroke.css +17 -0
- data/test/fixtures/stylesheets/archetype/expected/ui/triangle.css +35 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/associative.css +9 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/if-set.css +9 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/spacing/horizontal-spacing.css +29 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/spacing/vertical-spacing.css +29 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/styles/filter.css +11 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/styles/font-family.css +16 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/styles/z-index.css +15 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/targeting/target-browser.css +100 -0
- data/test/fixtures/stylesheets/archetype/expected/utilities/targeting/target-os.css +55 -0
- data/test/fixtures/stylesheets/archetype/source/b.scss +9 -0
- data/test/fixtures/stylesheets/archetype/source/base.scss +3 -0
- data/test/fixtures/stylesheets/archetype/source/hacks/ie_pseudo.scss +13 -0
- data/test/fixtures/stylesheets/archetype/source/locale.scss +43 -0
- data/test/fixtures/stylesheets/archetype/source/styleguide/buttons.scss +18 -0
- data/test/fixtures/stylesheets/archetype/source/styleguide/fallback_styles.scss +22 -0
- data/test/fixtures/stylesheets/archetype/source/styleguide/nested_styleguides.scss +40 -0
- data/test/fixtures/stylesheets/archetype/source/styleguide/selective_state.scss +22 -0
- data/test/fixtures/stylesheets/archetype/source/ui/glyph_icon.scss +13 -0
- data/test/fixtures/stylesheets/archetype/source/ui/hide_element.scss +5 -0
- data/test/fixtures/stylesheets/archetype/source/ui/stroke.scss +13 -0
- data/test/fixtures/stylesheets/archetype/source/ui/triangle.scss +13 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/associative.scss +24 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/if-set.scss +16 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/spacing/horizontal-spacing.scss +27 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/spacing/vertical-spacing.scss +27 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/styles/filter.scss +9 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/styles/font-family.scss +9 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/styles/z-index.scss +18 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/targeting/target-browser.scss +70 -0
- data/test/fixtures/stylesheets/archetype/source/utilities/targeting/target-os.scss +42 -0
- data/test/helpers/diff.rb +49 -0
- data/test/helpers/io.rb +36 -0
- data/test/helpers/test_case.rb +62 -0
- data/test/integrations/archetype_test.rb +126 -0
- data/test/test_helper.rb +26 -0
- data/test/units/sass_extensions_test.rb +207 -0
- metadata +303 -15
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# This module provides a set of Sass functions for working with Sass::Number
|
3
|
+
#
|
4
|
+
module Archetype::SassExtensions::Numbers
|
5
|
+
#
|
6
|
+
# remove the units from a number
|
7
|
+
#
|
8
|
+
# *Parameters*:
|
9
|
+
# - <tt>$number</tt> {Number} the number to remove units from
|
10
|
+
# *Returns*:
|
11
|
+
# - {Number} the number without units
|
12
|
+
#
|
13
|
+
def strip_units(number)
|
14
|
+
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)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,406 @@
|
|
1
|
+
require 'archetype/functions/helpers'
|
2
|
+
require 'archetype/functions/styleguide_memoizer'
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This is the magic of Archetype. This module provides the interfaces for constructing,
|
7
|
+
# extending, and retrieving reusable UI components
|
8
|
+
#
|
9
|
+
module Archetype::SassExtensions::Styleguide
|
10
|
+
|
11
|
+
# :stopdoc:
|
12
|
+
INHERIT = 'inherit'
|
13
|
+
STYLEGUIDE = 'styleguide'
|
14
|
+
DROP = 'drop'
|
15
|
+
DEFAULT = 'default'
|
16
|
+
REGEX = 'regex'
|
17
|
+
SPECIAL = %w(states selectors)
|
18
|
+
# these are unique CSS keys that can be exploited to provide fallback functionality by providing a second value
|
19
|
+
# e.g color: red; color: rgba(255,0,0, 0.8);
|
20
|
+
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)
|
21
|
+
ADDITIVES = FALLBACKS + [DROP, INHERIT, STYLEGUIDE]
|
22
|
+
@@archetype_styleguide_mutex = Mutex.new
|
23
|
+
# :startdoc:
|
24
|
+
|
25
|
+
#
|
26
|
+
# interface for adding new components to the styleguide structure
|
27
|
+
#
|
28
|
+
# *Parameters*:
|
29
|
+
# - <tt>$id</tt> {String} the component identifier
|
30
|
+
# - <tt>$data</tt> {List} the component data object
|
31
|
+
# - <tt>$default</tt> {List} the default data object (for extending)
|
32
|
+
# - <tt>$theme</tt> {String} the theme to insert the component into
|
33
|
+
# - <tt>$force</tt> {Boolean} if true, forcibly insert the component
|
34
|
+
# *Returns*:
|
35
|
+
# - {Boolean} whether or not the component was added
|
36
|
+
#
|
37
|
+
def styleguide_add_component(id, data, default = nil, theme = nil, force = false)
|
38
|
+
@@archetype_styleguide_mutex.synchronize do
|
39
|
+
theme = get_theme(theme)
|
40
|
+
components = theme[:components]
|
41
|
+
id = helpers.to_str(id)
|
42
|
+
# if force was true, we have to invalidate the memoizer
|
43
|
+
memoizer.clear(theme[:name]) if force
|
44
|
+
# if we already have the component, don't create it again
|
45
|
+
return Sass::Script::Bool.new(false) if component_exists(id, theme, nil, force)
|
46
|
+
# otherwise add it
|
47
|
+
components[id] = helpers.list_to_hash(default, 1, SPECIAL, ADDITIVES).merge(helpers.list_to_hash(data, 1, SPECIAL, ADDITIVES))
|
48
|
+
return Sass::Script::Bool.new(true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
Sass::Script::Functions.declare :styleguide_add_component, [:id, :data]
|
52
|
+
Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default]
|
53
|
+
Sass::Script::Functions.declare :styleguide_add_component, [:id, :data, :default, :theme]
|
54
|
+
|
55
|
+
#
|
56
|
+
# interface for extending an existing components in the styleguide structure
|
57
|
+
#
|
58
|
+
# *Parameters*:
|
59
|
+
# - <tt>$id</tt> {String} the component identifier
|
60
|
+
# - <tt>$data</tt> {List} the component data object
|
61
|
+
# - <tt>$theme</tt> {String} the theme to insert the component into
|
62
|
+
# - <tt>$extension</tt> {String} the name of the extension
|
63
|
+
# - <tt>$force</tt> {Boolean} if true, forcibly extend the component
|
64
|
+
# *Returns*:
|
65
|
+
# - {Boolean} whether or not the component was extended
|
66
|
+
#
|
67
|
+
def styleguide_extend_component(id, data, theme = nil, extension = nil, force = false)
|
68
|
+
@@archetype_styleguide_mutex.synchronize do
|
69
|
+
theme = get_theme(theme)
|
70
|
+
components = theme[:components]
|
71
|
+
id = helpers.to_str(id)
|
72
|
+
# if force was set, we'll create a random token for the name
|
73
|
+
extension = rand(36**8).to_s(36) if force
|
74
|
+
# convert the extension into a hash (if we don't have an extension, compose one out of its data)
|
75
|
+
extension = helpers.to_str(extension || data).hash
|
76
|
+
extensions = theme[:extensions]
|
77
|
+
return Sass::Script::Bool.new(false) if component_exists(id, theme, extension, force)
|
78
|
+
extensions.push(extension)
|
79
|
+
components[id] = (components[id] ||= Archetype::Hash.new).rmerge(helpers.list_to_hash(data, 1, SPECIAL, ADDITIVES))
|
80
|
+
return Sass::Script::Bool.new(true)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data]
|
84
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme]
|
85
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :data, :theme, :extension]
|
86
|
+
|
87
|
+
#
|
88
|
+
# check whether or not a component (or a component extension) has already been defined
|
89
|
+
#
|
90
|
+
# *Parameters*:
|
91
|
+
# - <tt>$id</tt> {String} the component identifier
|
92
|
+
# - <tt>$data</tt> {List} the component data object
|
93
|
+
# - <tt>$theme</tt> {String} the theme to insert the component into
|
94
|
+
# - <tt>$extension</tt> {String} the name of the extension
|
95
|
+
# - <tt>$force</tt> {Boolean} if true, forcibly extend the component
|
96
|
+
# *Returns*:
|
97
|
+
# - {Boolean} whether or not the component/extension exists
|
98
|
+
#
|
99
|
+
def styleguide_component_exists(id, theme = nil, extension = nil, force = false)
|
100
|
+
@@archetype_styleguide_mutex.synchronize do
|
101
|
+
extension = helpers.to_str(extension).hash if not extension.nil?
|
102
|
+
return Sass::Script::Bool.new( component_exists(id, theme, extension, force) )
|
103
|
+
end
|
104
|
+
end
|
105
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id]
|
106
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :theme]
|
107
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :theme, :extension]
|
108
|
+
Sass::Script::Functions.declare :styleguide_extend_component, [:id, :theme, :extension, :force]
|
109
|
+
|
110
|
+
#
|
111
|
+
# given a description of the component, convert it into CSS
|
112
|
+
#
|
113
|
+
# *Parameters*:
|
114
|
+
# - <tt>$description</tt> {String|List} the description of the component
|
115
|
+
# - <tt>$theme</tt> {String} the theme to use
|
116
|
+
# *Returns*:
|
117
|
+
# - {List} a key-value paired list of styles
|
118
|
+
#
|
119
|
+
def styleguide(description, state = 'false', theme = nil)
|
120
|
+
@@archetype_styleguide_mutex.synchronize do
|
121
|
+
# convert it back to a Sass:List and carry on
|
122
|
+
return helpers.hash_to_list(get_styles(description, theme, state), 0)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# output the CSS differences between components
|
128
|
+
#
|
129
|
+
# *Parameters*:
|
130
|
+
# - <tt>$original</tt> {String|List} the description of the original component
|
131
|
+
# - <tt>$other</tt> {String|List} the description of the new component
|
132
|
+
# - <tt>$theme</tt> {String} the theme to use
|
133
|
+
# *Returns*:
|
134
|
+
# - {List} a key-value paired list of styles
|
135
|
+
#
|
136
|
+
def styleguide_diff(original, other, theme = nil)
|
137
|
+
@@archetype_styleguide_mutex.synchronize do
|
138
|
+
original = get_styles(original, theme)
|
139
|
+
other = get_styles(other, theme)
|
140
|
+
diff = original.diff(other)
|
141
|
+
return helpers.hash_to_list(diff, 0)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
def helpers
|
147
|
+
@helpers ||= Archetype::Functions::Helpers
|
148
|
+
end
|
149
|
+
def memoizer
|
150
|
+
Archetype::Functions::StyleguideMemoizer
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# given a sentence, deconstruct it into it's identifier and verbages
|
155
|
+
#
|
156
|
+
# *Parameters*:
|
157
|
+
# - <tt>sentence</tt> {String|List} the sentence describing the component
|
158
|
+
# - <tt>theme</tt> {String} the theme to use
|
159
|
+
# - <tt>state</tt> {String} the name of a state to return
|
160
|
+
# *Returns*:
|
161
|
+
# - {Array} an array containing the identifer, modifiers, and a token
|
162
|
+
#
|
163
|
+
def grammar(sentence, theme = nil, state = 'false')
|
164
|
+
theme = get_theme(theme)
|
165
|
+
components = theme[:components]
|
166
|
+
# get a list of valid ids
|
167
|
+
styleguideIds = components.keys
|
168
|
+
sentence = sentence.split if sentence.is_a? String
|
169
|
+
sentence = sentence.to_a
|
170
|
+
id = nil
|
171
|
+
modifiers = []
|
172
|
+
if not sentence.empty?
|
173
|
+
prefix = ''
|
174
|
+
order = ''
|
175
|
+
# these define various attributes for modifiers (e.g. `button with a shadow`)
|
176
|
+
extras = %w(on with without)
|
177
|
+
# these are things that are useless to us, so we just leave them out
|
178
|
+
ignore = %w(a an also the this that is was it)
|
179
|
+
# these are our context switches (e.g. `headline in a button`)
|
180
|
+
contexts = %w(in)
|
181
|
+
sentence.each do |item|
|
182
|
+
item = item.value
|
183
|
+
# find the ID
|
184
|
+
if id.nil? and styleguideIds.include?(item) and prefix.empty? and order.empty?
|
185
|
+
id = item
|
186
|
+
# if it's a `context`, we need to increase the depth and reset the prefix
|
187
|
+
elsif contexts.include?(item)
|
188
|
+
order = "#{item}-#{order}"
|
189
|
+
prefix = ''
|
190
|
+
# if it's an `extra`, we update the prefix
|
191
|
+
elsif extras.include?(item)
|
192
|
+
prefix = "#{item}-"
|
193
|
+
# finally, check that it's not on the ignore (useless) list. if it is, we just skip over it
|
194
|
+
# (maybe this should be the first thing we check?)
|
195
|
+
elsif not ignore.include?(item)
|
196
|
+
modifiers.push("#{order}#{prefix}#{item}")
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
# if there was no id, return a list of valid IDs for reporting
|
201
|
+
modifiers = styleguideIds if id.nil?
|
202
|
+
# get the list of currenty installed component extensions
|
203
|
+
extensions = theme[:extensions] if not id.nil?
|
204
|
+
# TODO - low - eoneill: make sure we always want to return unique modifiers
|
205
|
+
# i can't think of a case where we wouldn't want to remove dups
|
206
|
+
# maybe in the case where we're looking for strict keys on the lookup?
|
207
|
+
modifiers = modifiers.uniq
|
208
|
+
token = memoizer.tokenize(theme[:name], extensions, id, modifiers, state)
|
209
|
+
return id, modifiers, token
|
210
|
+
end
|
211
|
+
|
212
|
+
#
|
213
|
+
# interface for extracting styles in the styleguide references
|
214
|
+
#
|
215
|
+
# *Parameters*:
|
216
|
+
# - <tt>id</tt> {String} the component identifier
|
217
|
+
# - <tt>modifiers</tt> {Array} the component modifiers
|
218
|
+
# - <tt>strict</tt> {Boolean} is it a strict lookup?
|
219
|
+
# - <tt>theme</tt> {String} the theme to use
|
220
|
+
# - <tt>context</tt> {Hash} the context to work in
|
221
|
+
# *Returns*:
|
222
|
+
# - {Hash} a hash of the extracted styles
|
223
|
+
#
|
224
|
+
def extract_styles(id, modifiers, strict = false, theme = nil, context = nil)
|
225
|
+
theme = get_theme(theme)
|
226
|
+
context ||= theme[:components][id] || Archetype::Hash.new
|
227
|
+
modifiers = helpers.to_str(modifiers)
|
228
|
+
return Archetype::Hash.new if context.nil? or context.empty?
|
229
|
+
# push on the defaults first
|
230
|
+
out = (strict ? resolve_dependents(id, context[modifiers], theme[:name], context) : context[DEFAULT]) || Archetype::Hash.new
|
231
|
+
out = out.clone
|
232
|
+
# if it's not strict, find anything that matched
|
233
|
+
if not strict
|
234
|
+
modifiers = modifiers.split
|
235
|
+
context.each do |key, definition|
|
236
|
+
definition = [key, definition]
|
237
|
+
modifier = definition[0]
|
238
|
+
if modifier != DEFAULT
|
239
|
+
match = true
|
240
|
+
modifier = modifier.split
|
241
|
+
if modifier[0] == REGEX
|
242
|
+
# if it's a regex pattern, test if it matches
|
243
|
+
match = modifiers.join(' ') =~ /#{modifier[1].gsub(/\A"|"\Z/, '')}/i
|
244
|
+
else
|
245
|
+
# otherwise, if the modifier isn't in our list of modifiers, it's not valid and just move on
|
246
|
+
modifier.each { |i| match = false if not modifiers.include?(i) }
|
247
|
+
end
|
248
|
+
# if it matched, process it
|
249
|
+
out = out.rmerge(resolve_dependents(id, definition[1], theme[:name], nil, out.keys)) if match
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
# recompose the special keys and extract any nested/inherited styles
|
254
|
+
# this lets us define special states and elements
|
255
|
+
SPECIAL.each do |special_key|
|
256
|
+
if out.is_a? Hash
|
257
|
+
special = out[special_key]
|
258
|
+
tmp = Archetype::Hash.new
|
259
|
+
(special || Archetype::Hash.new).each { |key, value| tmp[key] = extract_styles(key, key, true, theme[:name], special) }
|
260
|
+
out[special_key] = tmp if not tmp.empty?
|
261
|
+
end
|
262
|
+
end
|
263
|
+
# check for nested styleguides
|
264
|
+
styleguide = out[STYLEGUIDE]
|
265
|
+
if styleguide and not styleguide.empty?
|
266
|
+
styles = get_styles(styleguide, theme[:name])
|
267
|
+
out.delete(STYLEGUIDE)
|
268
|
+
out = styles.rmerge(out)
|
269
|
+
end
|
270
|
+
return out
|
271
|
+
end
|
272
|
+
|
273
|
+
#
|
274
|
+
# resolve any dependent references from the component
|
275
|
+
#
|
276
|
+
# *Parameters*:
|
277
|
+
# - <tt>id</tt> {String} the component identifier
|
278
|
+
# - <tt>value</tt> {Hash} the current value
|
279
|
+
# - <tt>theme</tt> {String} the theme to use
|
280
|
+
# - <tt>context</tt> {Hash} the context to work in
|
281
|
+
# - <tt>keys</tt> {Array} list of the external keys
|
282
|
+
# *Returns*:
|
283
|
+
# - {Hash} a hash of the resolved styles
|
284
|
+
#
|
285
|
+
def resolve_dependents(id, value, theme = nil, context = nil, keys = nil)
|
286
|
+
# we have to create a clone here as the passed in value is volatile and we're performing destructive changes
|
287
|
+
value = value.clone
|
288
|
+
# check that we're dealing with a hash
|
289
|
+
if value.is_a?(Hash)
|
290
|
+
# check for dropped styles
|
291
|
+
drop = value[DROP]
|
292
|
+
if not drop.nil?
|
293
|
+
tmp = Archetype::Hash.new
|
294
|
+
if %w(all true).include?(helpers.to_str(drop)) and not keys.nil? and not keys.empty?
|
295
|
+
keys.each do |key|
|
296
|
+
tmp[key] = 'nil'
|
297
|
+
end
|
298
|
+
else
|
299
|
+
drop = drop.to_a
|
300
|
+
drop.each do |key|
|
301
|
+
tmp[helpers.to_str(key)] = 'nil'
|
302
|
+
end
|
303
|
+
end
|
304
|
+
value.delete(DROP)
|
305
|
+
value = tmp.rmerge(value)
|
306
|
+
end
|
307
|
+
# check for inheritance
|
308
|
+
inherit = value[INHERIT]
|
309
|
+
if inherit and not inherit.empty?
|
310
|
+
# create a temporary object and extract the nested styles
|
311
|
+
tmp = Archetype::Hash.new
|
312
|
+
inherit.each { |related| tmp = tmp.rmerge(extract_styles(id, related, true, theme, context)) }
|
313
|
+
# remove the inheritance key and update the styles
|
314
|
+
value.delete(INHERIT)
|
315
|
+
value = tmp.rmerge(value)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
# return whatever we got
|
319
|
+
return value
|
320
|
+
end
|
321
|
+
|
322
|
+
#
|
323
|
+
# keep a registry of styleguide themes
|
324
|
+
#
|
325
|
+
# *Parameters*:
|
326
|
+
# - <tt>theme</tt> {String} the theme to use
|
327
|
+
# *Returns*:
|
328
|
+
# - {Hash} the theme
|
329
|
+
#
|
330
|
+
def get_theme(theme)
|
331
|
+
theme_name = helpers.to_str(theme || 'archetype')
|
332
|
+
@@styleguide_themes ||= {}
|
333
|
+
theme = @@styleguide_themes[theme_name] ||= {}
|
334
|
+
theme[:name] ||= theme_name
|
335
|
+
theme[:components] ||= {}
|
336
|
+
theme[:extensions] ||= []
|
337
|
+
return theme
|
338
|
+
end
|
339
|
+
|
340
|
+
#
|
341
|
+
# driver method for converting a sentence into a list of styles
|
342
|
+
#
|
343
|
+
# *Parameters*:
|
344
|
+
# - <tt>description</tt> {String|List} the description of the component
|
345
|
+
# - <tt>theme</tt> {String} the theme to use
|
346
|
+
# - <tt>state</tt> {String} the name of a state to return
|
347
|
+
# *Returns*:
|
348
|
+
# - {Hash} the styles
|
349
|
+
#
|
350
|
+
def get_styles(description, theme = nil, state = 'false')
|
351
|
+
state = helpers.to_str(state)
|
352
|
+
description = description.to_a
|
353
|
+
styles = Archetype::Hash.new
|
354
|
+
description.each do |sentence|
|
355
|
+
# get the grammar from the sentence
|
356
|
+
id, modifiers, token = grammar(sentence, theme, state)
|
357
|
+
if id
|
358
|
+
# check memoizer
|
359
|
+
memoized = memoizer.fetch(theme, token)
|
360
|
+
if memoized
|
361
|
+
styles = styles.rmerge(memoized)
|
362
|
+
else
|
363
|
+
# fetch additional styles
|
364
|
+
extracted = extract_styles(id, modifiers, false, theme)
|
365
|
+
# we can delete anything that had a value of `nil` as we won't be outputting those
|
366
|
+
extracted.delete_if { |k,v| helpers.is_value(v, :nil) }
|
367
|
+
styles = styles.rmerge(extracted)
|
368
|
+
memoizer.add(theme, token, extracted)
|
369
|
+
end
|
370
|
+
elsif not helpers.is_value(sentence, :nil)
|
371
|
+
helpers.logger.record(:warning, "[archetype:styleguide:missing_identifier] `#{helpers.to_str(sentence)}` does not contain an identifier. please specify one of: #{modifiers.sort.join(', ')}")
|
372
|
+
end
|
373
|
+
end
|
374
|
+
# now that we've collected all of our styles, if we requested a single state, merge that state upstream
|
375
|
+
if state != 'false' and styles['states']
|
376
|
+
state = styles['states'][state]
|
377
|
+
# remove any nested/special keys
|
378
|
+
SPECIAL.each do |special|
|
379
|
+
styles.delete(special)
|
380
|
+
end
|
381
|
+
styles = styles.merge(state) if not (state.nil? or state.empty?)
|
382
|
+
end
|
383
|
+
return styles
|
384
|
+
end
|
385
|
+
|
386
|
+
#
|
387
|
+
# check whether or not a component (or a component extension) has already been defined
|
388
|
+
#
|
389
|
+
# *Parameters*:
|
390
|
+
# - <tt>$id</tt> {String} the component identifier
|
391
|
+
# - <tt>$data</tt> {List} the component data object
|
392
|
+
# - <tt>$theme</tt> {String} the theme to insert the component into
|
393
|
+
# - <tt>$extension</tt> {String} the name of the extension
|
394
|
+
# - <tt>$force</tt> {Boolean} if true, forcibly extend the component
|
395
|
+
# *Returns*:
|
396
|
+
# - {Boolean} whether or not the component/extension exists
|
397
|
+
#
|
398
|
+
def component_exists(id, theme = nil, extension = nil, force = false)
|
399
|
+
status = false
|
400
|
+
theme = get_theme(theme) if not theme.is_a? Hash
|
401
|
+
id = helpers.to_str(id)
|
402
|
+
# determine the status of the component
|
403
|
+
status = (extension.nil?) ? (not theme[:components][id].nil?) : theme[:extensions].include?(extension)
|
404
|
+
return (status and not force and Compass.configuration.memoize)
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'archetype/functions/helpers'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
#
|
5
|
+
# This module provides some UI helper methods.
|
6
|
+
#
|
7
|
+
module Archetype::SassExtensions::UI
|
8
|
+
# :stopdoc:
|
9
|
+
@@archetype_ui_mutex = Mutex.new
|
10
|
+
# :startdoc:
|
11
|
+
|
12
|
+
#
|
13
|
+
# generate a unique token
|
14
|
+
#
|
15
|
+
# *Parameters*:
|
16
|
+
# - <tt>$prefix</tt> {String} a string to prefix the UID with, `class` and `id` will generate a unique selector
|
17
|
+
# *Returns*:
|
18
|
+
# - {String} the unique string
|
19
|
+
#
|
20
|
+
def unique(prefix = '')
|
21
|
+
prefix = helpers.to_str(prefix, ' ', :quotes)
|
22
|
+
prefix = '.' if prefix == 'class'
|
23
|
+
prefix = '#' if prefix == 'id'
|
24
|
+
return Sass::Script::String.new("#{prefix}archetype-uid-#{uid}")
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# parse a CSS content string and format it for injection into innerHTML
|
29
|
+
#
|
30
|
+
# *Parameters*:
|
31
|
+
# - <tt>$content</tt> {String} the CSS content string
|
32
|
+
# *Returns*:
|
33
|
+
# - {String} the processed string
|
34
|
+
#
|
35
|
+
def _ie_pseudo_content(content)
|
36
|
+
content = helpers.to_str(content)
|
37
|
+
# escape &
|
38
|
+
content = content.gsub(/\&/, '&')
|
39
|
+
# convert char codes (and remove single trailing whitespace if present) (e.g. \2079 -> ⁹)
|
40
|
+
content = content.gsub(/\\([\da-zA-Z]{4})\s?/, '&#x\1;')
|
41
|
+
# escape tags and cleanup quotes
|
42
|
+
content = content.gsub(/\</, '<').gsub(/\>/, '>')
|
43
|
+
# cleanup quotes
|
44
|
+
content = content.gsub(/\A"|"\Z/, '').gsub(/\"/, '\\"')
|
45
|
+
return Sass::Script::String.new(content)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def helpers
|
50
|
+
@helpers ||= Archetype::Functions::Helpers
|
51
|
+
end
|
52
|
+
|
53
|
+
def uid
|
54
|
+
@@archetype_ui_mutex.synchronize do
|
55
|
+
@@uid ||= 0
|
56
|
+
@@uid += 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|