sass 3.1.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (205) hide show
  1. data/.yardopts +11 -0
  2. data/CONTRIBUTING +3 -0
  3. data/EDGE_GEM_VERSION +1 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +201 -0
  6. data/REVISION +1 -0
  7. data/Rakefile +353 -0
  8. data/VERSION +1 -0
  9. data/VERSION_NAME +1 -0
  10. data/bin/css2sass +13 -0
  11. data/bin/sass +8 -0
  12. data/bin/sass-convert +7 -0
  13. data/extra/update_watch.rb +13 -0
  14. data/init.rb +18 -0
  15. data/lib/sass.rb +71 -0
  16. data/lib/sass/cache_store.rb +208 -0
  17. data/lib/sass/callbacks.rb +66 -0
  18. data/lib/sass/css.rb +294 -0
  19. data/lib/sass/engine.rb +792 -0
  20. data/lib/sass/environment.rb +143 -0
  21. data/lib/sass/error.rb +201 -0
  22. data/lib/sass/exec.rb +619 -0
  23. data/lib/sass/importers.rb +22 -0
  24. data/lib/sass/importers/base.rb +138 -0
  25. data/lib/sass/importers/filesystem.rb +121 -0
  26. data/lib/sass/less.rb +363 -0
  27. data/lib/sass/plugin.rb +126 -0
  28. data/lib/sass/plugin/compiler.rb +346 -0
  29. data/lib/sass/plugin/configuration.rb +123 -0
  30. data/lib/sass/plugin/generic.rb +15 -0
  31. data/lib/sass/plugin/merb.rb +48 -0
  32. data/lib/sass/plugin/rack.rb +47 -0
  33. data/lib/sass/plugin/rails.rb +41 -0
  34. data/lib/sass/plugin/staleness_checker.rb +145 -0
  35. data/lib/sass/railtie.rb +8 -0
  36. data/lib/sass/repl.rb +58 -0
  37. data/lib/sass/root.rb +7 -0
  38. data/lib/sass/script.rb +63 -0
  39. data/lib/sass/script/bool.rb +18 -0
  40. data/lib/sass/script/color.rb +490 -0
  41. data/lib/sass/script/css_lexer.rb +29 -0
  42. data/lib/sass/script/css_parser.rb +31 -0
  43. data/lib/sass/script/funcall.rb +78 -0
  44. data/lib/sass/script/functions.rb +852 -0
  45. data/lib/sass/script/interpolation.rb +70 -0
  46. data/lib/sass/script/lexer.rb +337 -0
  47. data/lib/sass/script/literal.rb +236 -0
  48. data/lib/sass/script/node.rb +101 -0
  49. data/lib/sass/script/number.rb +420 -0
  50. data/lib/sass/script/operation.rb +92 -0
  51. data/lib/sass/script/parser.rb +392 -0
  52. data/lib/sass/script/string.rb +67 -0
  53. data/lib/sass/script/string_interpolation.rb +93 -0
  54. data/lib/sass/script/unary_operation.rb +57 -0
  55. data/lib/sass/script/variable.rb +48 -0
  56. data/lib/sass/scss.rb +17 -0
  57. data/lib/sass/scss/css_parser.rb +51 -0
  58. data/lib/sass/scss/parser.rb +838 -0
  59. data/lib/sass/scss/rx.rb +126 -0
  60. data/lib/sass/scss/sass_parser.rb +11 -0
  61. data/lib/sass/scss/script_lexer.rb +15 -0
  62. data/lib/sass/scss/script_parser.rb +25 -0
  63. data/lib/sass/scss/static_parser.rb +40 -0
  64. data/lib/sass/selector.rb +361 -0
  65. data/lib/sass/selector/abstract_sequence.rb +62 -0
  66. data/lib/sass/selector/comma_sequence.rb +82 -0
  67. data/lib/sass/selector/sequence.rb +236 -0
  68. data/lib/sass/selector/simple.rb +113 -0
  69. data/lib/sass/selector/simple_sequence.rb +135 -0
  70. data/lib/sass/shared.rb +78 -0
  71. data/lib/sass/tree/comment_node.rb +128 -0
  72. data/lib/sass/tree/debug_node.rb +36 -0
  73. data/lib/sass/tree/directive_node.rb +75 -0
  74. data/lib/sass/tree/extend_node.rb +65 -0
  75. data/lib/sass/tree/for_node.rb +67 -0
  76. data/lib/sass/tree/if_node.rb +81 -0
  77. data/lib/sass/tree/import_node.rb +124 -0
  78. data/lib/sass/tree/mixin_def_node.rb +60 -0
  79. data/lib/sass/tree/mixin_node.rb +123 -0
  80. data/lib/sass/tree/node.rb +490 -0
  81. data/lib/sass/tree/prop_node.rb +220 -0
  82. data/lib/sass/tree/root_node.rb +125 -0
  83. data/lib/sass/tree/rule_node.rb +273 -0
  84. data/lib/sass/tree/variable_node.rb +39 -0
  85. data/lib/sass/tree/warn_node.rb +42 -0
  86. data/lib/sass/tree/while_node.rb +48 -0
  87. data/lib/sass/util.rb +687 -0
  88. data/lib/sass/util/subset_map.rb +101 -0
  89. data/lib/sass/version.rb +109 -0
  90. data/rails/init.rb +1 -0
  91. data/test/sass/cache_test.rb +74 -0
  92. data/test/sass/callbacks_test.rb +61 -0
  93. data/test/sass/conversion_test.rb +1210 -0
  94. data/test/sass/css2sass_test.rb +364 -0
  95. data/test/sass/data/hsl-rgb.txt +319 -0
  96. data/test/sass/engine_test.rb +2273 -0
  97. data/test/sass/extend_test.rb +1348 -0
  98. data/test/sass/functions_test.rb +565 -0
  99. data/test/sass/importer_test.rb +104 -0
  100. data/test/sass/less_conversion_test.rb +632 -0
  101. data/test/sass/mock_importer.rb +49 -0
  102. data/test/sass/more_results/more1.css +9 -0
  103. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  104. data/test/sass/more_results/more_import.css +29 -0
  105. data/test/sass/more_templates/_more_partial.sass +2 -0
  106. data/test/sass/more_templates/more1.sass +23 -0
  107. data/test/sass/more_templates/more_import.sass +11 -0
  108. data/test/sass/plugin_test.rb +430 -0
  109. data/test/sass/results/alt.css +4 -0
  110. data/test/sass/results/basic.css +9 -0
  111. data/test/sass/results/compact.css +5 -0
  112. data/test/sass/results/complex.css +86 -0
  113. data/test/sass/results/compressed.css +1 -0
  114. data/test/sass/results/expanded.css +19 -0
  115. data/test/sass/results/import.css +31 -0
  116. data/test/sass/results/line_numbers.css +49 -0
  117. data/test/sass/results/mixins.css +95 -0
  118. data/test/sass/results/multiline.css +24 -0
  119. data/test/sass/results/nested.css +22 -0
  120. data/test/sass/results/options.css +1 -0
  121. data/test/sass/results/parent_ref.css +13 -0
  122. data/test/sass/results/script.css +16 -0
  123. data/test/sass/results/scss_import.css +31 -0
  124. data/test/sass/results/scss_importee.css +2 -0
  125. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  126. data/test/sass/results/subdir/subdir.css +3 -0
  127. data/test/sass/results/units.css +11 -0
  128. data/test/sass/results/warn.css +0 -0
  129. data/test/sass/results/warn_imported.css +0 -0
  130. data/test/sass/script_conversion_test.rb +254 -0
  131. data/test/sass/script_test.rb +459 -0
  132. data/test/sass/scss/css_test.rb +897 -0
  133. data/test/sass/scss/rx_test.rb +156 -0
  134. data/test/sass/scss/scss_test.rb +1088 -0
  135. data/test/sass/scss/test_helper.rb +37 -0
  136. data/test/sass/templates/_partial.sass +2 -0
  137. data/test/sass/templates/alt.sass +16 -0
  138. data/test/sass/templates/basic.sass +23 -0
  139. data/test/sass/templates/bork1.sass +2 -0
  140. data/test/sass/templates/bork2.sass +2 -0
  141. data/test/sass/templates/bork3.sass +2 -0
  142. data/test/sass/templates/bork4.sass +2 -0
  143. data/test/sass/templates/compact.sass +17 -0
  144. data/test/sass/templates/complex.sass +305 -0
  145. data/test/sass/templates/compressed.sass +15 -0
  146. data/test/sass/templates/expanded.sass +17 -0
  147. data/test/sass/templates/import.sass +12 -0
  148. data/test/sass/templates/importee.less +2 -0
  149. data/test/sass/templates/importee.sass +19 -0
  150. data/test/sass/templates/line_numbers.sass +13 -0
  151. data/test/sass/templates/mixin_bork.sass +5 -0
  152. data/test/sass/templates/mixins.sass +76 -0
  153. data/test/sass/templates/multiline.sass +20 -0
  154. data/test/sass/templates/nested.sass +25 -0
  155. data/test/sass/templates/nested_bork1.sass +2 -0
  156. data/test/sass/templates/nested_bork2.sass +2 -0
  157. data/test/sass/templates/nested_bork3.sass +2 -0
  158. data/test/sass/templates/nested_bork4.sass +2 -0
  159. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  160. data/test/sass/templates/options.sass +2 -0
  161. data/test/sass/templates/parent_ref.sass +25 -0
  162. data/test/sass/templates/script.sass +101 -0
  163. data/test/sass/templates/scss_import.scss +11 -0
  164. data/test/sass/templates/scss_importee.scss +1 -0
  165. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  166. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  167. data/test/sass/templates/subdir/subdir.sass +6 -0
  168. data/test/sass/templates/units.sass +11 -0
  169. data/test/sass/templates/warn.sass +3 -0
  170. data/test/sass/templates/warn_imported.sass +4 -0
  171. data/test/sass/test_helper.rb +8 -0
  172. data/test/sass/util/subset_map_test.rb +91 -0
  173. data/test/sass/util_test.rb +275 -0
  174. data/test/test_helper.rb +64 -0
  175. data/vendor/fssm/LICENSE +20 -0
  176. data/vendor/fssm/README.markdown +55 -0
  177. data/vendor/fssm/Rakefile +59 -0
  178. data/vendor/fssm/VERSION.yml +5 -0
  179. data/vendor/fssm/example.rb +9 -0
  180. data/vendor/fssm/fssm.gemspec +77 -0
  181. data/vendor/fssm/lib/fssm.rb +33 -0
  182. data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  183. data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  184. data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  185. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  186. data/vendor/fssm/lib/fssm/monitor.rb +26 -0
  187. data/vendor/fssm/lib/fssm/path.rb +91 -0
  188. data/vendor/fssm/lib/fssm/pathname.rb +502 -0
  189. data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  190. data/vendor/fssm/lib/fssm/state/file.rb +24 -0
  191. data/vendor/fssm/lib/fssm/support.rb +63 -0
  192. data/vendor/fssm/lib/fssm/tree.rb +176 -0
  193. data/vendor/fssm/profile/prof-cache.rb +40 -0
  194. data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  195. data/vendor/fssm/profile/prof-pathname.rb +68 -0
  196. data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  197. data/vendor/fssm/profile/prof.html +2379 -0
  198. data/vendor/fssm/spec/path_spec.rb +75 -0
  199. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  200. data/vendor/fssm/spec/root/file.css +0 -0
  201. data/vendor/fssm/spec/root/file.rb +0 -0
  202. data/vendor/fssm/spec/root/file.yml +0 -0
  203. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  204. data/vendor/fssm/spec/spec_helper.rb +14 -0
  205. metadata +297 -0
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+ require File.dirname(__FILE__) + '/test_helper'
4
+
5
+ class ImporterTest < Test::Unit::TestCase
6
+
7
+ class FruitImporter < Sass::Importers::Base
8
+ attr_reader :cached
9
+
10
+ def find(name, context = nil)
11
+ if name =~ %r{fruits/(\w+)(\.s[ac]ss)?}
12
+ fruit = $1
13
+ color = case $1
14
+ when "apple"
15
+ "red"
16
+ when "orange"
17
+ "orange"
18
+ else
19
+ "blue"
20
+ end
21
+ contents = %Q{
22
+ $#{fruit}-color: #{color} !default;
23
+ @mixin #{fruit} {
24
+ color: $#{fruit}-color;
25
+ }
26
+ }
27
+ Sass::Engine.new(contents, :filename => name, :syntax => :scss, :importer => self)
28
+ end
29
+ end
30
+
31
+ def key(name, context)
32
+ [self.class.name, name]
33
+ end
34
+
35
+ def _around_dump
36
+ @cached = true
37
+ yield
38
+ ensure
39
+ @cached = false
40
+ end
41
+ end
42
+
43
+ # This class proves that you can override the extension scheme for importers
44
+ class ReversedExtImporter < Sass::Importers::Filesystem
45
+ def extensions
46
+ {"sscs" => :scss, "ssas" => :sass}
47
+ end
48
+ end
49
+
50
+ def test_can_resolve_generated_imports
51
+ scss_file = %Q{
52
+ $pear-color: green;
53
+ @import "fruits/apple"; @import "fruits/orange"; @import "fruits/pear";
54
+ .apple { @include apple; }
55
+ .orange { @include orange; }
56
+ .pear { @include pear; }
57
+ }
58
+ css_file = <<CSS
59
+ .apple { color: red; }
60
+
61
+ .orange { color: orange; }
62
+
63
+ .pear { color: green; }
64
+ CSS
65
+ options = {:style => :compact, :load_paths => [FruitImporter.new], :syntax => :scss}
66
+ assert_equal css_file, Sass::Engine.new(scss_file, options).render
67
+ end
68
+
69
+ def test_extension_overrides
70
+ FileUtils.mkdir_p(absolutize("tmp"))
71
+ open(absolutize("tmp/foo.ssas"), "w") {|f| f.write(".foo\n reversed: true\n")}
72
+ open(absolutize("tmp/bar.sscs"), "w") {|f| f.write(".bar {reversed: true}\n")}
73
+ scss_file = %Q{
74
+ @import "foo", "bar";
75
+ @import "foo.ssas", "bar.sscs";
76
+ }
77
+ css_file = <<CSS
78
+ .foo { reversed: true; }
79
+
80
+ .bar { reversed: true; }
81
+
82
+ .foo { reversed: true; }
83
+
84
+ .bar { reversed: true; }
85
+ CSS
86
+ options = {:style => :compact, :load_paths => [ReversedExtImporter.new(absolutize("tmp"))], :syntax => :scss}
87
+ assert_equal css_file, Sass::Engine.new(scss_file, options).render
88
+ ensure
89
+ FileUtils.rm_rf(absolutize("tmp"))
90
+ end
91
+
92
+ def test_caching_importer
93
+ source = "p\n foo: bar"
94
+ importer = FruitImporter.new
95
+ filename = filename_for_test
96
+ engine = Sass::Engine.new(source, :filename => filename, :importer => importer)
97
+ engine.to_tree # Trigger caching
98
+
99
+ sha = Digest::SHA1.hexdigest(source)
100
+ cache = engine.options[:cache_store]
101
+ cached_tree = cache.retrieve(cache.key(*importer.key(filename, engine.options)), sha)
102
+ assert cached_tree.options[:importer].cached, "Importer's _around_dump method should have been called"
103
+ end
104
+ end
@@ -0,0 +1,632 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+
4
+ begin
5
+ require 'sass/less'
6
+
7
+ class LessConversionTest < Test::Unit::TestCase
8
+ def test_variable_declarations
9
+ assert_renders <<SCSS, <<LESS
10
+ $var1: 2px 3px;
11
+ $var2: $var1 + 7px;
12
+
13
+ $var3: fizz;
14
+
15
+ foo {
16
+ prop: $var1 $var2 $var3; }
17
+ SCSS
18
+ @var1: 2px 3px;
19
+ @var2: @var1 + 7px;
20
+
21
+ @var3: fizz;
22
+
23
+ foo {prop: @var1 @var2 @var3}
24
+ LESS
25
+ end
26
+
27
+ def test_nested_variable_declarations
28
+ assert_renders <<SCSS, <<LESS
29
+ .foo {
30
+ $var: 2px;
31
+ prop: $var; }
32
+ SCSS
33
+ .foo {
34
+ @var: 2px;
35
+ prop: @var; }
36
+ LESS
37
+ end
38
+
39
+ def test_import
40
+ path = relative_path_to(File.dirname(__FILE__) + "/templates/importee.less")
41
+ resolved_path = relative_path_to(File.dirname(__FILE__) + "/templates/importee")
42
+ assert_renders <<SCSS, <<LESS
43
+ @import "#{resolved_path}";
44
+ @import "#{resolved_path}";
45
+
46
+ @import "#{resolved_path}";
47
+ @import "#{resolved_path}";
48
+ @import "#{resolved_path}";
49
+ SCSS
50
+ @import url(#{path});
51
+ @import url("#{path}");
52
+
53
+ @import url('#{path}');
54
+ @import '#{path}';
55
+ @import "#{path}";
56
+ LESS
57
+ end
58
+
59
+ def test_mixins_found_through_import
60
+ path = relative_path_to(File.dirname(__FILE__) + "/templates/importee.less")
61
+ resolved_path = relative_path_to(File.dirname(__FILE__) + "/templates/importee")
62
+ assert_renders <<SCSS, <<LESS
63
+ @import "#{resolved_path}";
64
+
65
+ .baz {
66
+ @extend .foo;
67
+ @include bar; }
68
+ SCSS
69
+ @import "#{path}";
70
+
71
+ .baz {.foo; .bar;}
72
+ LESS
73
+ end
74
+
75
+ # Selectors
76
+
77
+ def test_element_selector
78
+ assert_renders <<SCSS, <<LESS
79
+ foo {
80
+ a: b; }
81
+ SCSS
82
+ foo {a: b}
83
+ LESS
84
+ end
85
+
86
+ def test_class_selector
87
+ assert_renders <<SCSS, <<LESS
88
+ .foo {
89
+ a: b; }
90
+ SCSS
91
+ .foo {a: b}
92
+ LESS
93
+ end
94
+
95
+ def test_id_selector
96
+ assert_renders <<SCSS, <<LESS
97
+ #foo {
98
+ a: b; }
99
+ SCSS
100
+ #foo {a: b}
101
+ LESS
102
+ end
103
+
104
+ def test_pseudoclass_selector
105
+ assert_renders <<SCSS, <<LESS
106
+ :foo {
107
+ a: b; }
108
+ SCSS
109
+ :foo {a: b}
110
+ LESS
111
+ end
112
+
113
+ def test_pseudoelement_selector
114
+ assert_renders <<SCSS, <<LESS
115
+ ::foo {
116
+ a: b; }
117
+ SCSS
118
+ ::foo {a: b}
119
+ LESS
120
+ end
121
+
122
+ def test_comma_selector
123
+ assert_renders <<SCSS, <<LESS
124
+ foo, .bar .baz, :bang {
125
+ a: b; }
126
+ SCSS
127
+ foo, .bar .baz, :bang {a: b}
128
+ LESS
129
+ end
130
+
131
+ def test_nested_comma_selector
132
+ assert_renders <<SCSS, <<LESS
133
+ foo bar, .baz {
134
+ .bang, &:bip bap {
135
+ a: b; } }
136
+ SCSS
137
+ foo bar, .baz {
138
+ .bang, :bip bap {a: b} }
139
+ LESS
140
+ end
141
+
142
+ def test_simple_selector_sequence
143
+ assert_renders <<SCSS, <<LESS
144
+ a.foo#bar[attr=val] {
145
+ a: b; }
146
+ SCSS
147
+ a.foo#bar[attr=val] {a: b}
148
+ LESS
149
+ end
150
+
151
+ def test_descendant_selector
152
+ assert_renders <<SCSS, <<LESS
153
+ .foo .bar {
154
+ a: b; }
155
+ SCSS
156
+ .foo .bar {a: b}
157
+ LESS
158
+ end
159
+
160
+ def test_child_selector
161
+ assert_renders <<SCSS, <<LESS
162
+ .foo > .bar {
163
+ a: b; }
164
+ SCSS
165
+ .foo > .bar {a: b}
166
+ LESS
167
+ end
168
+
169
+ def test_adjacent_selector
170
+ assert_renders <<SCSS, <<LESS
171
+ .foo + .bar {
172
+ a: b; }
173
+ SCSS
174
+ .foo + .bar {a: b}
175
+ LESS
176
+ end
177
+
178
+ def test_pseudoclass_in_sequence
179
+ assert_renders <<SCSS, <<LESS
180
+ .foo:bar {
181
+ a: b; }
182
+ SCSS
183
+ .foo:bar {a: b}
184
+ LESS
185
+ end
186
+
187
+ def test_pseudoelement_in_sequence
188
+ assert_renders <<SCSS, <<LESS
189
+ .foo::bar {
190
+ a: b; }
191
+ SCSS
192
+ .foo::bar {a: b}
193
+ LESS
194
+ end
195
+
196
+ # Properties
197
+
198
+ def test_space_separated_props
199
+ assert_renders <<SCSS, <<LESS
200
+ foo {
201
+ a: foo bar baz; }
202
+ SCSS
203
+ foo {a: foo bar baz}
204
+ LESS
205
+ end
206
+
207
+ def test_comma_separated_props
208
+ assert_renders <<SCSS, <<LESS
209
+ foo {
210
+ a: foo, bar, baz; }
211
+ SCSS
212
+ foo {a: foo, bar, baz}
213
+ LESS
214
+ end
215
+
216
+ def test_numbers
217
+ assert_renders <<SCSS, <<LESS
218
+ foo {
219
+ a: 1 2.3 -8 5px 3%; }
220
+ SCSS
221
+ foo {a: 1 2.3 -8 5px 3%}
222
+ LESS
223
+ end
224
+
225
+ def test_colors
226
+ assert_renders <<SCSS, <<LESS
227
+ foo {
228
+ a: red #abcdef blue; }
229
+ SCSS
230
+ foo {a: #f00 #abcdef blue}
231
+ LESS
232
+ end
233
+
234
+ def test_strings
235
+ assert_renders <<SCSS, <<LESS
236
+ foo {
237
+ a: "foo @var bar" "baz bang" "quote'quote" 'quote"quote'; }
238
+ SCSS
239
+ foo {a: "foo @var bar" 'baz bang' "quote'quote" 'quote"quote'}
240
+ LESS
241
+ end
242
+
243
+ def test_slash
244
+ assert_renders <<SCSS, <<LESS
245
+ foo {
246
+ a: small/8px 7em/8px;
247
+ b: 8/4;
248
+ c: (8 / 4); }
249
+ SCSS
250
+ foo {
251
+ a: small/8px 7em/8px;
252
+ b: 8/4;
253
+ c: 8 / 4; }
254
+ LESS
255
+ end
256
+
257
+ def test_url
258
+ assert_renders <<SCSS, <<LESS
259
+ foo {
260
+ a: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
261
+ b: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
262
+ c: url("http://foobar.com/fizzle.html?foo=bar&bar=baz"); }
263
+ SCSS
264
+ foo {
265
+ a: url(http://foobar.com/fizzle.html?foo=bar&bar=baz);
266
+ b: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
267
+ c: url('http://foobar.com/fizzle.html?foo=bar&bar=baz'); }
268
+ LESS
269
+ end
270
+
271
+ def test_functions
272
+ assert_renders <<SCSS, <<LESS
273
+ foo {
274
+ a: baz(12px) rgba(80, 70 120, 0.76);
275
+ b: faz(1px + 3px) bang($var, #aaaaaa * 3); }
276
+ SCSS
277
+ foo {
278
+ a: baz(12px) rgba(80, 70 120, 0.76);
279
+ b: faz(1px + 3px) bang(@var, #aaa * 3); }
280
+ LESS
281
+ end
282
+
283
+ def test_alpha_function
284
+ assert_renders <<SCSS, <<LESS
285
+ foo {
286
+ a: alpha(opacity=2px);
287
+ b: alpha(opacity = $var); }
288
+ SCSS
289
+ foo {
290
+ a: alpha(opacity=2px);
291
+ b: alpha(opacity=@var); }
292
+ LESS
293
+ end
294
+
295
+ def test_variables
296
+ assert_renders <<SCSS, <<LESS
297
+ foo {
298
+ a: $var1 $var-foo; }
299
+ SCSS
300
+ foo {a: @var1 @var-foo}
301
+ LESS
302
+ end
303
+
304
+ def test_operators
305
+ assert_renders <<SCSS, <<LESS
306
+ foo {
307
+ a: 1px + 2px;
308
+ b: #bbaa88 - #aa1122;
309
+ c: 5 * 3;
310
+ d: (8 / 4); }
311
+ SCSS
312
+ foo {
313
+ a: 1px + 2px;
314
+ b: #ba8 - #a12;
315
+ c: 5 * 3;
316
+ d: 8 / 4; }
317
+ LESS
318
+ end
319
+
320
+ def test_operator_precedence
321
+ assert_renders <<SCSS, <<LESS
322
+ foo {
323
+ a: 1 + 2 * 3 + 4;
324
+ b: 1 * 2 + 3 * 4;
325
+ c: 1 - 2 + 2 - 4;
326
+ d: 1 + 2 - 3 + 4;
327
+ e: 1 / 2 - 3 / 4;
328
+ f: 1 - 2 / 3 - 4;
329
+ g: 1 / 2 * 3 / 4; }
330
+ SCSS
331
+ foo {
332
+ a: 1 + 2 * 3 + 4;
333
+ b: 1 * 2 + 3 * 4;
334
+ c: 1 - 2 + 2 - 4;
335
+ d: 1 + 2 - 3 + 4;
336
+ e: 1 / 2 - 3 / 4;
337
+ f: 1 - 2 / 3 - 4;
338
+ g: 1 / 2 * 3 / 4; }
339
+ LESS
340
+ end
341
+
342
+ def test_operators_with_parens
343
+ assert_renders <<SCSS, <<LESS
344
+ foo {
345
+ a: 1px + 2px * 3;
346
+ b: (1px - 2px) / 3; }
347
+ SCSS
348
+ foo {
349
+ a: 1px + (2px * 3);
350
+ b: (1px - (2px)) / 3; }
351
+ LESS
352
+ end
353
+
354
+ def test_unary_minus
355
+ assert_renders <<SCSS, <<LESS
356
+ foo {
357
+ a: 1px + -3px; }
358
+ SCSS
359
+ foo {a: 1px + (- 3px)}
360
+ LESS
361
+ end
362
+
363
+ # Nested Rules
364
+
365
+ def test_single_nested_rule
366
+ assert_renders <<SCSS, <<LESS
367
+ foo bar {
368
+ a: b; }
369
+ SCSS
370
+ foo {bar {a: b}}
371
+ LESS
372
+ end
373
+
374
+ def test_single_nested_rule_with_props
375
+ assert_renders <<SCSS, <<LESS
376
+ foo {
377
+ bar {
378
+ a: b; }
379
+ c: d;
380
+ e: f; }
381
+ SCSS
382
+ foo {
383
+ bar {a: b}
384
+ c: d;
385
+ e: f; }
386
+ LESS
387
+ end
388
+
389
+ def test_two_nested_rules
390
+ assert_renders <<SCSS, <<LESS
391
+ foo {
392
+ bar {
393
+ a: b; }
394
+ baz {
395
+ c: d; } }
396
+ SCSS
397
+ foo {
398
+ bar {a: b}
399
+ baz {c: d} }
400
+ LESS
401
+ end
402
+
403
+ def test_two_nested_rules_with_props
404
+ assert_renders <<SCSS, <<LESS
405
+ foo {
406
+ bar {
407
+ a: b; }
408
+ baz {
409
+ c: d; }
410
+ e: f;
411
+ g: h; }
412
+ SCSS
413
+ foo {
414
+ bar {a: b}
415
+ baz {c: d}
416
+ e: f;
417
+ g: h; }
418
+ LESS
419
+ end
420
+
421
+ def test_nested_rules_with_combinators
422
+ assert_renders <<SCSS, <<LESS
423
+ foo {
424
+ > bar {
425
+ a: b; }
426
+ + baz {
427
+ c: d; } }
428
+ SCSS
429
+ foo {
430
+ > bar {a: b}
431
+ + baz {c: d} }
432
+ LESS
433
+ end
434
+
435
+ def test_nested_pseudo_rules
436
+ assert_renders <<SCSS, <<LESS
437
+ foo {
438
+ &:bar {
439
+ a: b; }
440
+ &::baz {
441
+ c: d; } }
442
+ SCSS
443
+ foo {
444
+ :bar {a: b}
445
+ ::baz {c: d} }
446
+ LESS
447
+ end
448
+
449
+ # Mixins
450
+
451
+ def test_class_inheritance
452
+ assert_renders <<SCSS, <<LESS
453
+ .foo {
454
+ a: b; }
455
+
456
+ .bar {
457
+ @extend .foo; }
458
+ SCSS
459
+ .foo {a: b}
460
+ .bar {.foo;}
461
+ LESS
462
+ end
463
+
464
+ def test_multiple_class_inheritance
465
+ assert_renders <<SCSS, <<LESS
466
+ .foo {
467
+ a: b; }
468
+
469
+ .bar {
470
+ c: d; }
471
+
472
+ .baz {
473
+ @extend .foo;
474
+ @extend .bar; }
475
+ SCSS
476
+ .foo {a: b}
477
+ .bar {c: d}
478
+ .baz {.foo, .bar;}
479
+ LESS
480
+ end
481
+
482
+ def test_pseudoclass_inheritance
483
+ assert_renders <<SCSS, <<LESS
484
+ :foo {
485
+ a: b; }
486
+
487
+ :bar {
488
+ @extend :foo; }
489
+ SCSS
490
+ :foo {a: b}
491
+ :bar {:foo;}
492
+ LESS
493
+ end
494
+
495
+ def test_multiple_pseudoclass_inheritance
496
+ assert_renders <<SCSS, <<LESS
497
+ :foo:bar {
498
+ a: b; }
499
+
500
+ :baz {
501
+ @extend :foo:bar; }
502
+ SCSS
503
+ :foo:bar {a: b}
504
+ :baz {:foo:bar;}
505
+ LESS
506
+ end
507
+
508
+ def test_abstract_mixin
509
+ assert_renders <<SCSS, <<LESS
510
+ @mixin foo {
511
+ a: b; }
512
+
513
+ .bar {
514
+ @include foo; }
515
+ SCSS
516
+ .foo() {a: b}
517
+ .bar {.foo;}
518
+ LESS
519
+ end
520
+
521
+ def test_mixin_with_args
522
+ assert_renders <<SCSS, <<LESS
523
+ @mixin foo($a: 2px, $b: red) {
524
+ a: $a; }
525
+
526
+ .bar {
527
+ @include foo; }
528
+ SCSS
529
+ .foo(@a: 2px, @b: #f00) {a: @a}
530
+ .bar {.foo;}
531
+ LESS
532
+
533
+ assert_renders <<SCSS, <<LESS
534
+ @mixin foo($a: 2px + 3px, $b: red) {
535
+ a: $a; }
536
+
537
+ .bar {
538
+ @include foo(5px); }
539
+ SCSS
540
+ .foo(@a: 2px + 3px, @b: #f00) {a: @a}
541
+ .bar {.foo(5px);}
542
+ LESS
543
+ end
544
+
545
+ ## Disallowed Mixins
546
+
547
+ def test_nested_mixin
548
+ assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
549
+ WARNING: Sass doesn't support mixing in selector sequences.
550
+ Replacing ".foo .bar" with "@extend .bar"
551
+ WARN
552
+ .foo .bar {
553
+ a: b; }
554
+
555
+ .bar {
556
+ // .foo .bar;
557
+ @extend .bar; }
558
+ SCSS
559
+ .foo .bar {a: b}
560
+ .bar {.foo .bar;}
561
+ LESS
562
+ end
563
+
564
+ def test_child_selector_mixin
565
+ assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
566
+ WARNING: Sass doesn't support mixing in selector sequences.
567
+ Replacing "> .bar" with "@extend .bar"
568
+ WARN
569
+ .foo > .bar {
570
+ a: b; }
571
+
572
+ .bar {
573
+ // > .bar;
574
+ @extend .bar; }
575
+ SCSS
576
+ .foo > .bar {a: b}
577
+ .bar {> .bar;}
578
+ LESS
579
+ end
580
+
581
+ # Accessors
582
+
583
+ def test_property_accessor
584
+ assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
585
+ WARNING: Sass doesn't support attribute accessors.
586
+ Ignoring .magic-box['content']
587
+ WARN
588
+ .magic-box {
589
+ content: "gold"; }
590
+
591
+ .foo {
592
+ content: /* .magic-box['content'] */; }
593
+ SCSS
594
+ .magic-box {content: "gold"}
595
+ .foo {content: .magic-box['content']}
596
+ LESS
597
+ end
598
+
599
+ def test_variable_accessor
600
+ assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
601
+ WARNING: Sass doesn't support attribute accessors.
602
+ Ignoring .magic-box[@content]
603
+ WARN
604
+ .magic-box {
605
+ $content: "gold";
606
+ content: $content; }
607
+
608
+ .foo {
609
+ content: /* .magic-box[@content] */; }
610
+ SCSS
611
+ .magic-box {@content: "gold"; content: @content}
612
+ .foo {content: .magic-box[@content]}
613
+ LESS
614
+ end
615
+
616
+ private
617
+
618
+ def assert_renders(scss, less)
619
+ assert_equal(scss, Less::Engine.new(less).to_tree.to_sass_tree.to_scss)
620
+ end
621
+
622
+ # Necessary because Less can't import absolute files
623
+ def relative_path_to(file)
624
+ file = Pathname.new(file)
625
+ pwd = file.absolute? ? Dir.pwd : "."
626
+ file.relative_path_from(Pathname.new(pwd))
627
+ end
628
+ end
629
+
630
+ rescue LoadError => e
631
+ puts "\nCouldn't require less, skipping some tests."
632
+ end