archetype 0.0.1.pre.1 → 0.0.1.pre.3.00dfd9a
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.
- 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
|