compass 0.13.alpha.4 → 0.13.alpha.5

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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/README.markdown +2 -3
  3. data/Rakefile +91 -5
  4. data/VERSION.yml +1 -1
  5. data/examples/compass/images/emblem-a043c4f148.png +0 -0
  6. data/examples/compass/images/flag-03c3b29b35.png +0 -0
  7. data/examples/compass/images/flag-21cfbfbfc8.png +0 -0
  8. data/examples/css3/extensions/fancy-fonts/templates/project/Prociono.otf +0 -0
  9. data/features/command_line.feature +2 -6
  10. data/features/step_definitions/command_line_steps.rb +1 -0
  11. data/frameworks/compass/stylesheets/compass/_css3.scss +0 -1
  12. data/frameworks/compass/stylesheets/compass/_support.scss +353 -35
  13. data/frameworks/compass/stylesheets/compass/css3/_animation.scss +49 -48
  14. data/frameworks/compass/stylesheets/compass/css3/_appearance.scss +4 -8
  15. data/frameworks/compass/stylesheets/compass/css3/_background-clip.scss +15 -19
  16. data/frameworks/compass/stylesheets/compass/css3/_background-origin.scss +17 -19
  17. data/frameworks/compass/stylesheets/compass/css3/_background-size.scss +4 -8
  18. data/frameworks/compass/stylesheets/compass/css3/_border-radius.scss +37 -39
  19. data/frameworks/compass/stylesheets/compass/css3/_box-shadow.scss +45 -20
  20. data/frameworks/compass/stylesheets/compass/css3/_box-sizing.scss +6 -8
  21. data/frameworks/compass/stylesheets/compass/css3/_box.scss +12 -13
  22. data/frameworks/compass/stylesheets/compass/css3/_columns.scss +46 -26
  23. data/frameworks/compass/stylesheets/compass/css3/_deprecated-support.scss +272 -0
  24. data/frameworks/compass/stylesheets/compass/css3/_filter.scss +17 -10
  25. data/frameworks/compass/stylesheets/compass/css3/_flexbox.scss +134 -281
  26. data/frameworks/compass/stylesheets/compass/css3/_font-face.scss +5 -5
  27. data/frameworks/compass/stylesheets/compass/css3/_hyphenation.scss +14 -11
  28. data/frameworks/compass/stylesheets/compass/css3/_images.scss +77 -67
  29. data/frameworks/compass/stylesheets/compass/css3/_inline-block.scss +15 -6
  30. data/frameworks/compass/stylesheets/compass/css3/_opacity.scss +6 -2
  31. data/frameworks/compass/stylesheets/compass/css3/_pie.scss +1 -73
  32. data/frameworks/compass/stylesheets/compass/css3/_regions.scss +7 -6
  33. data/frameworks/compass/stylesheets/compass/css3/_selection.scss +45 -17
  34. data/frameworks/compass/stylesheets/compass/css3/_shared.scss +4 -261
  35. data/frameworks/compass/stylesheets/compass/css3/_text-shadow.scss +1 -1
  36. data/frameworks/compass/stylesheets/compass/css3/_transform.scss +24 -32
  37. data/frameworks/compass/stylesheets/compass/css3/_transition.scss +102 -152
  38. data/frameworks/compass/stylesheets/compass/css3/_user-interface.scss +42 -27
  39. data/frameworks/compass/stylesheets/compass/typography/_vertical_rhythm.scss +2 -1
  40. data/frameworks/compass/stylesheets/compass/typography/links/_hover-link.scss +1 -1
  41. data/frameworks/compass/stylesheets/compass/typography/lists/_horizontal-list.scss +2 -2
  42. data/frameworks/compass/stylesheets/compass/typography/lists/_inline-list.scss +1 -1
  43. data/frameworks/compass/stylesheets/compass/typography/text/_ellipsis.scss +1 -1
  44. data/frameworks/compass/stylesheets/compass/utilities/_sass.scss +2 -0
  45. data/frameworks/compass/stylesheets/compass/utilities/color/_brightness.scss +12 -0
  46. data/frameworks/compass/stylesheets/compass/utilities/color/_contrast.scss +36 -12
  47. data/frameworks/compass/stylesheets/compass/utilities/general/_float.scss +6 -2
  48. data/frameworks/compass/stylesheets/compass/utilities/general/_hacks.scss +23 -4
  49. data/frameworks/compass/stylesheets/compass/utilities/general/_min.scss +1 -1
  50. data/frameworks/compass/stylesheets/compass/utilities/sass/_lists.scss +16 -0
  51. data/frameworks/compass/stylesheets/compass/utilities/sass/_maps.scss +19 -0
  52. data/frameworks/compass/stylesheets/compass/utilities/sprites/_base.scss +25 -18
  53. data/frameworks/compass/stylesheets/compass/utilities/sprites/_sprite-img.scss +3 -1
  54. data/frameworks/compass/stylesheets/compass/utilities/tables/_borders.scss +3 -3
  55. data/lib/compass.rb +1 -1
  56. data/lib/compass/browser_support.rb +1 -1
  57. data/lib/compass/caniuse.rb +247 -0
  58. data/lib/compass/configuration/adapters.rb +7 -1
  59. data/lib/compass/sass_extensions/functions.rb +5 -0
  60. data/lib/compass/sass_extensions/functions/constants.rb +2 -2
  61. data/lib/compass/sass_extensions/functions/cross_browser_support.rb +176 -1
  62. data/lib/compass/sass_extensions/functions/display.rb +24 -19
  63. data/lib/compass/sass_extensions/functions/env.rb +37 -8
  64. data/lib/compass/sass_extensions/functions/gradient_support.rb +10 -13
  65. data/lib/compass/sass_extensions/functions/math.rb +31 -13
  66. data/lib/compass/sass_extensions/functions/sprites.rb +48 -25
  67. data/lib/compass/sass_extensions/monkey_patches/browser_support.rb +42 -13
  68. data/lib/compass/sass_extensions/sprites/image.rb +14 -4
  69. data/lib/compass/sass_extensions/sprites/image_methods.rb +19 -3
  70. data/lib/compass/sprite_importer/content.erb +8 -7
  71. data/lib/compass/watcher/project_watcher.rb +75 -42
  72. data/lib/compass/watcher/watch.rb +35 -17
  73. data/test/fixtures/sprites/public/images/focus/ten-by-ten.png +0 -0
  74. data/test/fixtures/sprites/public/images/focus/ten-by-ten_active.png +0 -0
  75. data/test/fixtures/sprites/public/images/focus/ten-by-ten_focus.png +0 -0
  76. data/test/fixtures/sprites/public/images/focus/ten-by-ten_hover.png +0 -0
  77. data/test/fixtures/sprites/public/images/focus/ten-by-ten_target.png +0 -0
  78. data/test/fixtures/stylesheets/compass/config.rb +1 -0
  79. data/test/fixtures/stylesheets/compass/css/animation-with-legacy-ie.css +1 -9
  80. data/test/fixtures/stylesheets/compass/css/animation.css +1 -9
  81. data/test/fixtures/stylesheets/compass/css/appearance.css +3 -0
  82. data/test/fixtures/stylesheets/compass/css/background-clip.css +4 -8
  83. data/test/fixtures/stylesheets/compass/css/background-origin.css +4 -8
  84. data/test/fixtures/stylesheets/compass/css/background-size.css +3 -10
  85. data/test/fixtures/stylesheets/compass/css/border_radius.css +3 -3
  86. data/test/fixtures/stylesheets/compass/css/{box-sizeing.css → box-sizing.css} +2 -2
  87. data/test/fixtures/stylesheets/compass/css/box_shadow.css +15 -5
  88. data/test/fixtures/stylesheets/compass/css/brightness.css +14 -0
  89. data/test/fixtures/stylesheets/compass/css/browser-support.css +306 -0
  90. data/test/fixtures/stylesheets/compass/css/color.css +18 -0
  91. data/test/fixtures/stylesheets/compass/css/columns.css +27 -18
  92. data/test/fixtures/stylesheets/compass/css/filters.css +6 -6
  93. data/test/fixtures/stylesheets/compass/css/flexbox.css +84 -111
  94. data/test/fixtures/stylesheets/compass/css/fonts.css +1 -1
  95. data/test/fixtures/stylesheets/compass/css/gradients.css +53 -53
  96. data/test/fixtures/stylesheets/compass/css/grid_background.css +11 -11
  97. data/test/fixtures/stylesheets/compass/css/hyphenation.css +2 -4
  98. data/test/fixtures/stylesheets/compass/css/lists.css +6 -12
  99. data/test/fixtures/stylesheets/compass/css/regions.css +2 -2
  100. data/test/fixtures/stylesheets/compass/css/selection.css +41 -4
  101. data/test/fixtures/stylesheets/compass/css/sprites_with_explicit_separator.css +16 -0
  102. data/test/fixtures/stylesheets/compass/css/support.css +62 -0
  103. data/test/fixtures/stylesheets/compass/css/transform.css +64 -136
  104. data/test/fixtures/stylesheets/compass/css/transition.css +27 -45
  105. data/test/fixtures/stylesheets/compass/css/typography/links/hover-link.css +4 -0
  106. data/test/fixtures/stylesheets/compass/css/user-interface.css +34 -7
  107. data/test/fixtures/stylesheets/compass/css/utilities.css +7 -7
  108. data/test/fixtures/stylesheets/compass/css/vertical_rhythm.css +6 -9
  109. data/test/fixtures/stylesheets/compass/images/flag_states-sc42d7bf926.png +0 -0
  110. data/test/fixtures/stylesheets/compass/images/flag_states/foo.png +0 -0
  111. data/test/fixtures/stylesheets/compass/images/flag_states/foo_active.png +0 -0
  112. data/test/fixtures/stylesheets/compass/images/flag_states/foo_focus.png +0 -0
  113. data/test/fixtures/stylesheets/compass/images/flag_states/foo_hover.png +0 -0
  114. data/test/fixtures/stylesheets/compass/images/flag_states/foo_target.png +0 -0
  115. data/test/fixtures/stylesheets/compass/sass/animation-with-legacy-ie.scss +1 -3
  116. data/test/fixtures/stylesheets/compass/sass/appearance.scss +5 -0
  117. data/test/fixtures/stylesheets/compass/sass/background-clip.scss +0 -5
  118. data/test/fixtures/stylesheets/compass/sass/background-origin.scss +0 -5
  119. data/test/fixtures/stylesheets/compass/sass/background-size.scss +0 -5
  120. data/test/fixtures/stylesheets/compass/sass/{box-sizeing.scss → box-sizing.scss} +1 -1
  121. data/test/fixtures/stylesheets/compass/sass/box_shadow.scss +2 -0
  122. data/test/fixtures/stylesheets/compass/sass/brightness.scss +12 -0
  123. data/test/fixtures/stylesheets/compass/sass/browser-support.scss +30 -0
  124. data/test/fixtures/stylesheets/compass/sass/color.scss +22 -0
  125. data/test/fixtures/stylesheets/compass/sass/filters.scss +1 -0
  126. data/test/fixtures/stylesheets/compass/sass/flexbox.scss +84 -40
  127. data/test/fixtures/stylesheets/compass/sass/gradients.sass +3 -2
  128. data/test/fixtures/stylesheets/compass/sass/selection.scss +29 -4
  129. data/test/fixtures/stylesheets/compass/sass/sprites_with_explicit_separator.scss +7 -0
  130. data/test/fixtures/stylesheets/compass/sass/support.scss +137 -0
  131. data/test/fixtures/stylesheets/compass/sass/transition.scss +0 -3
  132. data/test/fixtures/stylesheets/compass/sass/typography/links/hover-link.scss +3 -0
  133. data/test/fixtures/stylesheets/compass/sass/user-interface.scss +16 -5
  134. data/test/fixtures/stylesheets/compass/sass/utilities.scss +4 -4
  135. data/test/fixtures/stylesheets/envtest/css/env.css +4 -4
  136. data/test/fixtures/stylesheets/envtest/tmp/env.css +4 -4
  137. data/test/integrations/sprites_test.rb +30 -1
  138. data/test/test_helper.rb +2 -2
  139. data/test/units/caniuse_test.rb +115 -0
  140. data/test/units/command_line_test.rb +1 -0
  141. data/test/units/sass_extensions_test.rb +5 -0
  142. data/test/units/sprites/image_test.rb +12 -0
  143. data/test/units/sprites/sprite_map_test.rb +11 -0
  144. data/test/units/watcher/project_watcher_test.rb +26 -18
  145. metadata +96 -42
  146. data/examples/compass/src/pie.scss +0 -110
  147. data/frameworks/compass/stylesheets/compass/css3/_transform-legacy.scss +0 -87
  148. data/frameworks/compass/templates/pie/LICENSE +0 -12
  149. data/frameworks/compass/templates/pie/LICENSE-APACHE2.txt +0 -13
  150. data/frameworks/compass/templates/pie/LICENSE-GPL2.txt +0 -278
  151. data/frameworks/compass/templates/pie/PIE.htc +0 -96
  152. data/frameworks/compass/templates/pie/manifest.rb +0 -39
  153. data/frameworks/compass/templates/pie/pie.scss +0 -74
  154. data/lib/compass/sass_extensions/functions/utility.rb +0 -10
  155. data/test/fixtures/stylesheets/compass/css/pie.css +0 -23
  156. data/test/fixtures/stylesheets/compass/sass/pie.scss +0 -47
@@ -1,3 +1,5 @@
1
+ @import "compass/typography/text/replacement";
2
+
1
3
  // @doc off
2
4
  // Example 1:
3
5
  //
@@ -76,4 +78,4 @@ $sprite-image-default-height: $sprite-default-size !default;
76
78
  // The name of the image in the sprite folder should be `$img-name`
77
79
  @mixin sprite-replace-text-with-dimensions ($map, $sprite, $offset-x: 0, $offset-y: 0){
78
80
  @include sprite-replace-text ($map, $sprite, true, $offset-x, $offset-y);
79
- }
81
+ }
@@ -9,7 +9,7 @@
9
9
  th, td {
10
10
  border-top: $width solid $color; } }
11
11
  th {
12
- &:first-child #{if($legacy-support-for-ie6, ', &.first', '')} {
12
+ &:first-child #{if(support-legacy-browser(ie, "6"), ', &.first', null)} {
13
13
  border-right: $width solid $color; } } }
14
14
 
15
15
  @mixin inner-table-borders($width: 2px, $color: black) {
@@ -24,7 +24,7 @@
24
24
 
25
25
  // IE8 ignores rules that are included on the same line as :last-child
26
26
  // see http://www.richardscarrott.co.uk/posts/view/ie8-last-child-bug for details
27
- @if $legacy-support-for-ie6 or $legacy-support-for-ie7 or $legacy-support-for-ie8 {
27
+ @if support-legacy-browser(ie, "8") {
28
28
  &.last {
29
29
  border-right-width: 0px; } } }
30
30
 
@@ -32,7 +32,7 @@
32
32
  tr:last-child {
33
33
  th, td {
34
34
  border-bottom-width: 0px; } }
35
- @if $legacy-support-for-ie6 or $legacy-support-for-ie7 or $legacy-support-for-ie8 {
35
+ @if support-legacy-browser(ie, "8") {
36
36
  tr.last {
37
37
  th, td {
38
38
  border-bottom-width: 0px; } } } } }
@@ -29,7 +29,7 @@ module Compass
29
29
  extend QuickCache
30
30
  end
31
31
 
32
- %w(watcher configuration frameworks app_integration compiler).each do |lib|
32
+ %w(watcher configuration frameworks app_integration compiler caniuse).each do |lib|
33
33
  require "compass/#{lib}"
34
34
  end
35
35
 
@@ -2,7 +2,7 @@ module Compass
2
2
  module BrowserSupport
3
3
  extend self
4
4
 
5
- ASPECTS = %w(webkit moz o ms svg pie css2)
5
+ ASPECTS = %w(webkit moz o ms svg css2)
6
6
 
7
7
  SIMPLE_FUNCTIONS = {
8
8
  "image" => %w(), # No browsers implement this yet.
@@ -0,0 +1,247 @@
1
+ require 'json'
2
+ require 'singleton'
3
+ class Compass::CanIUse
4
+ include Singleton
5
+
6
+ DATA_FILE_NAME = File.join(Compass.base_directory, "data", "caniuse.json")
7
+ DATA_FEATURE_FILES = Dir.glob(File.join(Compass.base_directory, "data", "caniuse_extras", "**", "*.json"))
8
+
9
+ def initialize
10
+ @data = JSON.parse(File.read(DATA_FILE_NAME))
11
+ # support ad-hoc features
12
+ DATA_FEATURE_FILES.each do |feature_file|
13
+ feature_name = File.basename(feature_file, ".json")
14
+ # if the feature doesn't exist in the master `caniuse.json`
15
+ if @data["data"][feature_name].nil?
16
+ @data["data"][feature_name] = JSON.parse(File.read(feature_file))
17
+ end
18
+ end
19
+ end
20
+
21
+ # The browser names from caniuse are ugly.
22
+ PUBLIC_BROWSER_NAMES = Hash.new {|h, k| k}
23
+ PUBLIC_BROWSER_NAMES.update(
24
+ "and_chr" => "android-chrome",
25
+ "and_ff" => "android-firefox",
26
+ "android" => "android",
27
+ "bb" => "blackberry",
28
+ "chrome" => "chrome",
29
+ "firefox" => "firefox",
30
+ "ie" => "ie",
31
+ "ie_mob" => "ie-mobile",
32
+ "ios_saf" => "ios-safari",
33
+ "op_mini" => "opera-mini",
34
+ "op_mob" => "opera-mobile",
35
+ "opera" => "opera",
36
+ "safari" => "safari"
37
+ )
38
+ CAN_I_USE_NAMES = Hash.new {|h, k| k}
39
+ CAN_I_USE_NAMES.update(PUBLIC_BROWSER_NAMES.invert)
40
+
41
+ # Returns all the known browsers according to caniuse
42
+ def browsers
43
+ @browsers ||= @data["agents"].keys.map{|b| PUBLIC_BROWSER_NAMES[b] }.sort
44
+ end
45
+
46
+ # Returns the prefix corresponding to a particular browser
47
+ def prefix(browser, version = nil)
48
+ assert_valid_browser browser
49
+ assert_valid_version browser, version if version
50
+ data = browser_data(browser)
51
+ p = if data["prefix_exceptions"] && data["prefix_exceptions"][version]
52
+ data["prefix_exceptions"][version]
53
+ else
54
+ data["prefix"]
55
+ end
56
+ "-#{p}"
57
+ end
58
+
59
+ # returns all possible prefixes a browser might use.
60
+ def all_prefixes(browser)
61
+ assert_valid_browser browser
62
+ data = browser_data(browser)
63
+ prefixes = ["-#{data["prefix"]}"]
64
+ if data["prefix_exceptions"]
65
+ prefixes += data["prefix_exceptions"].values.uniq.map{|p| "-#{p}"}
66
+ end
67
+ prefixes
68
+ end
69
+
70
+ # returns the prefixes needed by the list of browsers given
71
+ def prefixes(browsers = browsers)
72
+ result = browsers.map{|b| all_prefixes(b) }
73
+ result.flatten!
74
+ result.uniq!
75
+ result.sort!
76
+ result
77
+ end
78
+
79
+ def browser_minimums(capability, prefix = nil)
80
+ assert_valid_capability capability
81
+ browsers = prefix.nil? ? browsers() : browsers_with_prefix(prefix)
82
+ browsers.inject({}) do |m, browser|
83
+ version = versions(browser).find do |version|
84
+ support = browser_support(browser, version, capability)
85
+ if prefix.nil?
86
+ support !~ /\bn\b/ && support !~ /\bx\b/
87
+ else
88
+ actual_prefix = prefix(browser, version)
89
+ support !~ /\bn\b/ && support =~ /\bx\b/ && prefix == actual_prefix
90
+ end
91
+ end
92
+ m.update(browser => version) if version
93
+ m
94
+ end
95
+ end
96
+
97
+ # How many users would be omitted if support for the given browser starts
98
+ # with the given version.
99
+ def omitted_usage(browser, min_version)
100
+ assert_valid_browser browser
101
+ usage = 0
102
+ versions(browser).each do |version|
103
+ return usage if version == min_version
104
+ usage += usage(browser, version)
105
+ end
106
+ raise ArgumentError, "#{min_version} is not a version for #{browser}"
107
+ end
108
+
109
+ # returns the list of browsers that use the given prefix
110
+ def browsers_with_prefix(prefix)
111
+ assert_valid_prefix prefix
112
+ prefix = "-" + prefix unless prefix.start_with?("-")
113
+ browsers.select {|b| all_prefixes(b).include?(prefix) }
114
+ end
115
+
116
+ SPEC_VERSION_MATCHERS = Hash.new do |h, k|
117
+ h[k] = /##{k}\b/
118
+ end
119
+
120
+ CAPABILITY_MATCHERS = {
121
+ :full_support => lambda {|support, capability| !support ^ (capability =~ /\by\b/) },
122
+ :partial_support => lambda {|support, capability| !support ^ (capability =~ /\ba\b/) },
123
+ :prefixed => lambda {|support, capability| !support ^ (capability =~ /\bx\b/) },
124
+ :spec_versions => lambda {|versions, capability| versions.any? {|v| capability =~ SPEC_VERSION_MATCHERS[v] } }
125
+ }
126
+
127
+ # Return whether the capability matcher the options specified.
128
+ # For each capability option in the options the capability will need to match it.
129
+ def capability_matches(support, capability_options_list)
130
+ capability_options_list.any? do |capability_options|
131
+ capability_options.all? {|c, v| CAPABILITY_MATCHERS[c].call(v, support)}
132
+ end
133
+ end
134
+
135
+ # returns the percentage of users (0-100) that would be affected if the prefix
136
+ # was not used with the given capability.
137
+ def prefixed_usage(prefix, capability, capability_options_list)
138
+ assert_valid_prefix prefix
139
+ assert_valid_capability capability
140
+ usage = 0
141
+ browsers_with_prefix(prefix).each do |browser|
142
+ versions(browser).each do |version|
143
+ next unless prefix == prefix(browser, version)
144
+ support = browser_support(browser, version, capability)
145
+ if capability_matches(support, capability_options_list) and support =~ /\bx\b/
146
+ usage += usage(browser, version)
147
+ end
148
+ end
149
+ end
150
+ usage
151
+ end
152
+
153
+ # Returns whether the given minimum version of a browser
154
+ # requires the use of a prefix for the stated capability.
155
+ def requires_prefix(browser, min_version, capability, capability_options_list)
156
+ assert_valid_browser browser
157
+ assert_valid_capability capability
158
+ found_version = false
159
+ versions(browser).each do |version|
160
+ found_version ||= version == min_version
161
+ next unless found_version
162
+ support = browser_support(browser, version, capability)
163
+ if capability_matches(support, capability_options_list) and support =~ /\bx\b/
164
+ return prefix(browser, version)
165
+ end
166
+ end
167
+ raise ArgumentError, "#{min_version} is not a version for #{browser}" unless found_version
168
+ nil
169
+ end
170
+
171
+ # Returns the versions of a browser. If the min_usage parameter is provided,
172
+ # only those versions having met the threshold of user percentage.
173
+ #
174
+ # @param min_usage a decimal number betwee 0 and 100
175
+ def versions(browser, min_usage = 0)
176
+ assert_valid_browser browser
177
+ versions = browser_data(browser)["versions"].compact
178
+ return versions if min_usage == 0
179
+ versions.select {|v| browser_data(browser)["usage_global"][v] > min_usage }
180
+ end
181
+
182
+ # The list of capabilities tracked by caniuse.
183
+ def capabilities
184
+ @capabilities ||= @data["data"].keys.select do |cap|
185
+ cats = @data["data"][cap]["categories"]
186
+ cats.any?{|cat| cat =~ /CSS/ }
187
+ end.sort
188
+ end
189
+
190
+ # the usage % for a given browser version.
191
+ def usage(browser, version)
192
+ browser_data(browser)["usage_global"][version]
193
+ end
194
+
195
+
196
+ def inspect
197
+ "Compass::CanIUse(#{browsers.join(", ")})"
198
+ end
199
+
200
+ # the browser data assocated with a given capability
201
+ def capability_data(capability)
202
+ @data["data"][capability]
203
+ end
204
+
205
+ def browser_support(browser, version, capability)
206
+ capability_data(capability)["stats"][CAN_I_USE_NAMES[browser]][version]
207
+ end
208
+
209
+ # the metadata assocated with a given browser
210
+ def browser_data(browser)
211
+ @data["agents"][CAN_I_USE_NAMES[browser]]
212
+ end
213
+
214
+ # efficiently checks if a prefix is valid
215
+ def assert_valid_prefix(prefix)
216
+ @known_prefixes ||= Set.new(prefixes(browsers))
217
+ unless @known_prefixes.include?(prefix)
218
+ raise ArgumentError, "#{prefix} is not known browser prefix."
219
+ end
220
+ end
221
+
222
+ # efficiently checks if a browser is valid
223
+ def assert_valid_browser(browser)
224
+ @known_browsers ||= Set.new(browsers)
225
+ @known_browsers.include?(browser)
226
+ unless @known_browsers.include?(browser)
227
+ raise ArgumentError, "#{browser} is not known browser."
228
+ end
229
+ end
230
+
231
+ # efficiently checks if a capability is valid
232
+ def assert_valid_capability(capability)
233
+ @known_capabilities ||= Set.new(capabilities)
234
+ unless @known_capabilities.include?(capability)
235
+ raise ArgumentError, "#{capability} is not known browser capability."
236
+ end
237
+ nil
238
+ end
239
+
240
+ def assert_valid_version(browser, *versions)
241
+ versions.each do |v|
242
+ unless versions(browser).include?(v)
243
+ raise ArgumentError, "#{v} is not known version for #{browser}."
244
+ end
245
+ end
246
+ end
247
+ end
@@ -4,7 +4,13 @@ module Compass
4
4
  # adapt to various consumers of configuration data
5
5
  module Adapters
6
6
  def to_compiler_arguments(additional_options = {})
7
- [project_path, sass_path, css_path, to_sass_engine_options.merge(additional_options)]
7
+ engine_opts = to_sass_engine_options.merge(additional_options)
8
+ # we have to pass the quiet option in the nested :sass hash to disambiguate it from the compass compiler's own quiet option.
9
+ if engine_opts.has_key?(:quiet)
10
+ engine_opts[:sass] ||= {}
11
+ engine_opts[:sass][:quiet] = engine_opts.delete(:quiet)
12
+ end
13
+ [project_path, sass_path, css_path, engine_opts]
8
14
  end
9
15
 
10
16
  def to_sass_plugin_options
@@ -1,4 +1,9 @@
1
1
  module Compass::SassExtensions::Functions
2
+ module SassDeclarationHelper
3
+ def register_sass_function(*args)
4
+ Sass::Script::Functions.declare(*args)
5
+ end
6
+ end
2
7
  end
3
8
 
4
9
  %w(
@@ -1,6 +1,6 @@
1
1
  module Compass::SassExtensions::Functions::Constants
2
- if defined?(Sass::Script::List)
3
- POSITIONS = /top|bottom|left|right|center/
2
+ POSITIONS = /top|bottom|left|right|center/
3
+ if defined?(Sass::Script::Value::List)
4
4
  def is_position(position)
5
5
  Sass::Script::Bool.new(position.is_a?(Sass::Script::String) && !!(position.value =~ POSITIONS))
6
6
  end
@@ -28,12 +28,13 @@ module Compass::SassExtensions::Functions::CrossBrowserSupport
28
28
 
29
29
  # Check if any of the arguments passed require a vendor prefix.
30
30
  def prefixed(prefix, *args)
31
+ assert_type prefix, :String
31
32
  aspect = prefix.value.sub(/^-/,"")
32
33
  needed = args.any?{|a| a.respond_to?(:supports?) && a.supports?(aspect)}
33
34
  Sass::Script::Bool.new(needed)
34
35
  end
35
36
 
36
- %w(webkit moz o ms svg pie css2).each do |prefix|
37
+ %w(webkit moz o ms svg css2).each do |prefix|
37
38
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
38
39
  # Syntactic sugar to apply the given prefix
39
40
  # -moz($arg) is the same as calling prefix(-moz, $arg)
@@ -44,6 +45,7 @@ module Compass::SassExtensions::Functions::CrossBrowserSupport
44
45
  end
45
46
 
46
47
  def prefix(prefix, *objects)
48
+ assert_type prefix, :String if prefix.is_a?(Sass::Script::Value::Base)
47
49
  prefix = prefix.value if prefix.is_a?(Sass::Script::String)
48
50
  prefix = prefix[1..-1] if prefix[0] == ?-
49
51
  if objects.size > 1
@@ -67,4 +69,177 @@ module Compass::SassExtensions::Functions::CrossBrowserSupport
67
69
  CSS2FallbackValue.new(value, css2_value)
68
70
  end
69
71
 
72
+ # The known browsers.
73
+ #
74
+ # If prefix is given, limits the returned browsers to those using the specified prefix.
75
+ def browsers(prefix = nil)
76
+ browsers = if prefix
77
+ assert_type prefix, :String
78
+ Compass::CanIUse.instance.browsers_with_prefix(prefix.value)
79
+ else
80
+ Compass::CanIUse.instance.browsers
81
+ end
82
+ list(browsers.map{|b| identifier(b)}, :comma)
83
+ end
84
+ Sass::Script::Functions.declare(:browsers, [])
85
+ Sass::Script::Functions.declare(:browsers, [:prefix])
86
+
87
+ # The known capabilities of browsers.
88
+ def browser_capabilities
89
+ list(Compass::CanIUse.instance.capabilities.map{|c| identifier(c)}, :comma)
90
+ end
91
+ Sass::Script::Functions.declare(:browser_capabilities, [])
92
+
93
+ # The versions for the given browser.
94
+ def browser_versions(browser)
95
+ assert_type browser, :String
96
+ list(Compass::CanIUse.instance.versions(browser.value).map{|v| quoted_string(v)}, :comma)
97
+ rescue ArgumentError => e
98
+ raise Sass::SyntaxError.new(e.message)
99
+ end
100
+ Sass::Script::Functions.declare(:browser_versions, [:browser])
101
+
102
+ # whether the browser uses a prefix for the given capability at the version
103
+ # specified or a later version. Returns the prefix it requires, or null.
104
+ def browser_requires_prefix(browser, version, capability, capability_options)
105
+ assert_type browser, :String
106
+ assert_type version, :String
107
+ assert_type capability, :String
108
+ p = Compass::CanIUse.instance.requires_prefix(browser.value,
109
+ version.value,
110
+ capability.value,
111
+ unbox_capability_options_list(capability_options))
112
+ p ? identifier(p) : null()
113
+ rescue ArgumentError => e
114
+ raise Sass::SyntaxError.new(e.message)
115
+ end
116
+ Sass::Script::Functions.declare(:browser_requires_prefix, [:browser, :version, :capability])
117
+
118
+ # the prefix for the given browser.
119
+ def browser_prefix(browser, version = nil)
120
+ assert_type browser, :String
121
+ identifier(Compass::CanIUse.instance.prefix(browser.value))
122
+ rescue ArgumentError => e
123
+ raise Sass::SyntaxError.new(e.message)
124
+ end
125
+ Sass::Script::Functions.declare(:browser_prefix, [:browser])
126
+ Sass::Script::Functions.declare(:browser_prefix, [:browser, :version])
127
+
128
+ # The prefixes used by the given browsers.
129
+ def browser_prefixes(browsers)
130
+ browsers = list(browsers, :comma) if browsers.is_a?(Sass::Script::Value::String)
131
+ assert_type browsers, :List
132
+ browser_strings = browsers.value.map {|b| assert_type(b, :String); b.value }
133
+ prefix_strings = Compass::CanIUse.instance.prefixes(browser_strings)
134
+ list(prefix_strings.map {|p| identifier(p)}, :comma)
135
+ rescue ArgumentError => e
136
+ raise Sass::SyntaxError.new(e.message)
137
+ end
138
+ Sass::Script::Functions.declare(:browser_prefixes, [:browsers])
139
+
140
+ # The percent of users that are omitted by setting the min_version of browser
141
+ # as specified.
142
+ def omitted_usage(browser, min_version)
143
+ assert_type browser, :String
144
+ assert_type min_version, :String
145
+ number(Compass::CanIUse.instance.omitted_usage(browser.value, min_version.value))
146
+ end
147
+ Sass::Script::Functions.declare(:omitted_usage, [:browser, :min_version])
148
+
149
+ # The percent of users relying on a particular prefix
150
+ def prefix_usage(prefix, capability, capability_options)
151
+ assert_type prefix, :String
152
+ assert_type capability, :String
153
+ number(Compass::CanIUse.instance.prefixed_usage(prefix.value,
154
+ capability.value,
155
+ unbox_capability_options_list(capability_options)))
156
+ rescue ArgumentError => e
157
+ raise Sass::SyntaxError.new(e.message)
158
+ end
159
+ Sass::Script::Functions.declare(:prefix_usage, [:prefix, :capability])
160
+
161
+ # Compares two browser versions. Returning:
162
+ #
163
+ # * 0 if they are the same
164
+ # * <0 if the first version is less than the second
165
+ # * >0 if the first version is more than the second
166
+ def compare_browser_versions(browser, version1, version2)
167
+ assert_type browser, :String
168
+ assert_type version1, :String
169
+ assert_type version2, :String
170
+ index1 = index2 = nil
171
+ Compass::CanIUse.instance.versions(browser.value).each_with_index do |v, i|
172
+ index1 = i if v == version1.value
173
+ index2 = i if v == version2.value
174
+ break if index1 && index2
175
+ end
176
+ unless index1
177
+ raise Sass::SyntaxError.new("#{version1} is not a version for #{browser}")
178
+ end
179
+ unless index2
180
+ raise Sass::SyntaxError.new("#{version2} is not a version for #{browser}")
181
+ end
182
+ number(index1 <=> index2)
183
+ end
184
+ Sass::Script::Functions.declare(:compare_browser_versions, [:browser, :version1, :version2])
185
+
186
+ # Returns a map of browsers to the first version the capability became available
187
+ # without a prefix.
188
+ #
189
+ # If a prefix is provided, only those browsers using that prefix will be returned
190
+ # and the minimum version will be when it first became available as a prefix or
191
+ # without a prefix.
192
+ #
193
+ # If a browser does not have the capability, it will not included in the map.
194
+ def browser_minimums(capability, prefix = null())
195
+ assert_type capability, :String
196
+ assert_type(prefix, :String) unless prefix == null()
197
+ mins = Compass::CanIUse.instance.browser_minimums(capability.value, prefix.value)
198
+ Sass::Script::Value::Map.new(mins.inject({}) do |m, (h, k)|
199
+ m[identifier(h)] = quoted_string(k)
200
+ m
201
+ end)
202
+ end
203
+ Sass::Script::Functions.declare(:browser_minimums, [:capability])
204
+ Sass::Script::Functions.declare(:browser_minimums, [:capability, :prefix])
205
+
206
+ private
207
+
208
+ def unbox_capability_options_list(capability_options_list)
209
+ if capability_options_list.is_a?(Sass::Script::Value::Map)
210
+ [unbox_capability_options(capability_options_list)]
211
+ elsif capability_options_list.is_a?(Sass::Script::Value::List)
212
+ capability_options_list.to_a.map{|opts| unbox_capability_options(opts) }
213
+ else
214
+ assert_type capability_options_list, :List
215
+ end
216
+ end
217
+
218
+ CAPABILITY_OPTION_KEYS = {
219
+ "full-support" => :full_support,
220
+ "partial-support" => :partial_support,
221
+ "prefixed" => :prefixed,
222
+ "spec-versions" => :spec_versions,
223
+ }
224
+
225
+ CAPABILITY_OPTION_UNBOXER = {
226
+ :full_support => lambda {|v| v.to_bool },
227
+ :partial_support => lambda {|v| v.to_bool },
228
+ :prefixed => lambda {|v| v.to_bool },
229
+ :spec_versions => lambda {|versions| versions.to_a.map {|v| v.value } }
230
+ }
231
+
232
+ def unbox_capability_options(capability_options)
233
+ assert_type capability_options, :Map
234
+ result = {}
235
+ capability_options.value.each do |k, v|
236
+ assert_type k, :String
237
+ key = CAPABILITY_OPTION_KEYS[k.value]
238
+ unless key
239
+ raise Sass::SyntaxError, "#{k} is not valid capability option"
240
+ end
241
+ result[key] = CAPABILITY_OPTION_UNBOXER[key].call(v)
242
+ end
243
+ result
244
+ end
70
245
  end