sass 3.4.25 → 3.7.4

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 (237) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +1 -1
  3. data/CONTRIBUTING.md +3 -3
  4. data/README.md +17 -9
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/extra/sass-spec-ref.sh +9 -1
  9. data/lib/sass.rb +0 -7
  10. data/lib/sass/cache_stores/filesystem.rb +1 -1
  11. data/lib/sass/css.rb +1 -2
  12. data/lib/sass/engine.rb +39 -29
  13. data/lib/sass/environment.rb +26 -5
  14. data/lib/sass/error.rb +2 -2
  15. data/lib/sass/exec/base.rb +2 -13
  16. data/lib/sass/exec/sass_scss.rb +1 -5
  17. data/lib/sass/features.rb +1 -0
  18. data/lib/sass/importers/filesystem.rb +6 -4
  19. data/lib/sass/logger/base.rb +11 -0
  20. data/lib/sass/plugin/compiler.rb +20 -50
  21. data/lib/sass/plugin/configuration.rb +2 -2
  22. data/lib/sass/railtie.rb +1 -1
  23. data/lib/sass/script/css_parser.rb +4 -1
  24. data/lib/sass/script/functions.rb +308 -81
  25. data/lib/sass/script/lexer.rb +63 -9
  26. data/lib/sass/script/parser.rb +287 -118
  27. data/lib/sass/script/tree/funcall.rb +35 -34
  28. data/lib/sass/script/tree/interpolation.rb +0 -3
  29. data/lib/sass/script/tree/list_literal.rb +23 -8
  30. data/lib/sass/script/tree/map_literal.rb +2 -2
  31. data/lib/sass/script/tree/node.rb +0 -8
  32. data/lib/sass/script/tree/operation.rb +1 -8
  33. data/lib/sass/script/value.rb +2 -0
  34. data/lib/sass/script/value/arg_list.rb +1 -1
  35. data/lib/sass/script/value/base.rb +17 -0
  36. data/lib/sass/script/value/callable.rb +25 -0
  37. data/lib/sass/script/value/color.rb +8 -2
  38. data/lib/sass/script/value/function.rb +19 -0
  39. data/lib/sass/script/value/helpers.rb +37 -11
  40. data/lib/sass/script/value/list.rb +35 -14
  41. data/lib/sass/script/value/map.rb +2 -2
  42. data/lib/sass/script/value/number.rb +3 -2
  43. data/lib/sass/scss/css_parser.rb +6 -1
  44. data/lib/sass/scss/parser.rb +145 -56
  45. data/lib/sass/scss/rx.rb +5 -11
  46. data/lib/sass/scss/static_parser.rb +20 -42
  47. data/lib/sass/selector.rb +4 -0
  48. data/lib/sass/selector/abstract_sequence.rb +7 -6
  49. data/lib/sass/selector/comma_sequence.rb +9 -5
  50. data/lib/sass/selector/pseudo.rb +20 -3
  51. data/lib/sass/selector/sequence.rb +35 -10
  52. data/lib/sass/selector/simple.rb +9 -2
  53. data/lib/sass/selector/simple_sequence.rb +8 -4
  54. data/lib/sass/source/map.rb +2 -6
  55. data/lib/sass/stack.rb +21 -1
  56. data/lib/sass/tree/charset_node.rb +1 -1
  57. data/lib/sass/tree/prop_node.rb +45 -53
  58. data/lib/sass/tree/rule_node.rb +6 -8
  59. data/lib/sass/tree/visitors/check_nesting.rb +1 -1
  60. data/lib/sass/tree/visitors/convert.rb +2 -3
  61. data/lib/sass/tree/visitors/cssize.rb +4 -15
  62. data/lib/sass/tree/visitors/deep_copy.rb +1 -1
  63. data/lib/sass/tree/visitors/extend.rb +2 -8
  64. data/lib/sass/tree/visitors/perform.rb +23 -15
  65. data/lib/sass/tree/visitors/set_options.rb +1 -1
  66. data/lib/sass/tree/visitors/to_css.rb +49 -22
  67. data/lib/sass/util.rb +72 -310
  68. data/lib/sass/util/multibyte_string_scanner.rb +127 -131
  69. data/lib/sass/util/normalized_map.rb +1 -8
  70. data/lib/sass/version.rb +0 -4
  71. metadata +55 -202
  72. data/Rakefile +0 -453
  73. data/lib/sass/script/css_variable_warning.rb +0 -52
  74. data/lib/sass/util/cross_platform_random.rb +0 -19
  75. data/lib/sass/util/ordered_hash.rb +0 -192
  76. data/test/sass-spec.yml +0 -3
  77. data/test/sass/cache_test.rb +0 -131
  78. data/test/sass/callbacks_test.rb +0 -61
  79. data/test/sass/compiler_test.rb +0 -236
  80. data/test/sass/conversion_test.rb +0 -2188
  81. data/test/sass/css2sass_test.rb +0 -526
  82. data/test/sass/css_variable_test.rb +0 -132
  83. data/test/sass/data/hsl-rgb.txt +0 -319
  84. data/test/sass/encoding_test.rb +0 -219
  85. data/test/sass/engine_test.rb +0 -3447
  86. data/test/sass/exec_test.rb +0 -96
  87. data/test/sass/extend_test.rb +0 -1733
  88. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  89. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  90. data/test/sass/functions_test.rb +0 -1977
  91. data/test/sass/importer_test.rb +0 -421
  92. data/test/sass/logger_test.rb +0 -58
  93. data/test/sass/mock_importer.rb +0 -49
  94. data/test/sass/more_results/more1.css +0 -9
  95. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  96. data/test/sass/more_results/more_import.css +0 -29
  97. data/test/sass/more_templates/_more_partial.sass +0 -2
  98. data/test/sass/more_templates/more1.sass +0 -23
  99. data/test/sass/more_templates/more_import.sass +0 -11
  100. data/test/sass/plugin_test.rb +0 -556
  101. data/test/sass/results/alt.css +0 -4
  102. data/test/sass/results/basic.css +0 -9
  103. data/test/sass/results/cached_import_option.css +0 -3
  104. data/test/sass/results/compact.css +0 -5
  105. data/test/sass/results/complex.css +0 -86
  106. data/test/sass/results/compressed.css +0 -1
  107. data/test/sass/results/expanded.css +0 -19
  108. data/test/sass/results/filename_fn.css +0 -3
  109. data/test/sass/results/if.css +0 -3
  110. data/test/sass/results/import.css +0 -31
  111. data/test/sass/results/import_charset.css +0 -5
  112. data/test/sass/results/import_charset_1_8.css +0 -5
  113. data/test/sass/results/import_charset_ibm866.css +0 -5
  114. data/test/sass/results/import_content.css +0 -1
  115. data/test/sass/results/line_numbers.css +0 -49
  116. data/test/sass/results/mixins.css +0 -95
  117. data/test/sass/results/multiline.css +0 -24
  118. data/test/sass/results/nested.css +0 -22
  119. data/test/sass/results/options.css +0 -1
  120. data/test/sass/results/parent_ref.css +0 -13
  121. data/test/sass/results/script.css +0 -16
  122. data/test/sass/results/scss_import.css +0 -31
  123. data/test/sass/results/scss_importee.css +0 -2
  124. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  125. data/test/sass/results/subdir/subdir.css +0 -3
  126. data/test/sass/results/units.css +0 -11
  127. data/test/sass/results/warn.css +0 -0
  128. data/test/sass/results/warn_imported.css +0 -0
  129. data/test/sass/script_conversion_test.rb +0 -357
  130. data/test/sass/script_test.rb +0 -1431
  131. data/test/sass/scss/css_test.rb +0 -1281
  132. data/test/sass/scss/rx_test.rb +0 -160
  133. data/test/sass/scss/scss_test.rb +0 -4205
  134. data/test/sass/scss/test_helper.rb +0 -37
  135. data/test/sass/source_map_test.rb +0 -1055
  136. data/test/sass/superselector_test.rb +0 -210
  137. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  138. data/test/sass/templates/_double_import_loop2.sass +0 -1
  139. data/test/sass/templates/_filename_fn_import.scss +0 -11
  140. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  141. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  142. data/test/sass/templates/_imported_content.sass +0 -3
  143. data/test/sass/templates/_partial.sass +0 -2
  144. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/alt.sass +0 -16
  146. data/test/sass/templates/basic.sass +0 -23
  147. data/test/sass/templates/bork1.sass +0 -2
  148. data/test/sass/templates/bork2.sass +0 -2
  149. data/test/sass/templates/bork3.sass +0 -2
  150. data/test/sass/templates/bork4.sass +0 -2
  151. data/test/sass/templates/bork5.sass +0 -3
  152. data/test/sass/templates/cached_import_option.scss +0 -3
  153. data/test/sass/templates/compact.sass +0 -17
  154. data/test/sass/templates/complex.sass +0 -305
  155. data/test/sass/templates/compressed.sass +0 -15
  156. data/test/sass/templates/double_import_loop1.sass +0 -1
  157. data/test/sass/templates/expanded.sass +0 -17
  158. data/test/sass/templates/filename_fn.scss +0 -18
  159. data/test/sass/templates/if.sass +0 -11
  160. data/test/sass/templates/import.sass +0 -12
  161. data/test/sass/templates/import_charset.sass +0 -9
  162. data/test/sass/templates/import_charset_1_8.sass +0 -6
  163. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  164. data/test/sass/templates/import_content.sass +0 -4
  165. data/test/sass/templates/importee.less +0 -2
  166. data/test/sass/templates/importee.sass +0 -19
  167. data/test/sass/templates/line_numbers.sass +0 -13
  168. data/test/sass/templates/mixin_bork.sass +0 -5
  169. data/test/sass/templates/mixins.sass +0 -76
  170. data/test/sass/templates/multiline.sass +0 -20
  171. data/test/sass/templates/nested.sass +0 -25
  172. data/test/sass/templates/nested_bork1.sass +0 -2
  173. data/test/sass/templates/nested_bork2.sass +0 -2
  174. data/test/sass/templates/nested_bork3.sass +0 -2
  175. data/test/sass/templates/nested_bork4.sass +0 -2
  176. data/test/sass/templates/nested_import.sass +0 -2
  177. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  178. data/test/sass/templates/options.sass +0 -2
  179. data/test/sass/templates/parent_ref.sass +0 -25
  180. data/test/sass/templates/same_name_different_ext.sass +0 -2
  181. data/test/sass/templates/same_name_different_ext.scss +0 -1
  182. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  183. data/test/sass/templates/script.sass +0 -101
  184. data/test/sass/templates/scss_import.scss +0 -12
  185. data/test/sass/templates/scss_importee.scss +0 -1
  186. data/test/sass/templates/single_import_loop.sass +0 -1
  187. data/test/sass/templates/subdir/import_up1.scss +0 -1
  188. data/test/sass/templates/subdir/import_up2.scss +0 -1
  189. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  190. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  191. data/test/sass/templates/subdir/subdir.sass +0 -6
  192. data/test/sass/templates/units.sass +0 -11
  193. data/test/sass/templates/warn.sass +0 -3
  194. data/test/sass/templates/warn_imported.sass +0 -4
  195. data/test/sass/test_helper.rb +0 -8
  196. data/test/sass/util/multibyte_string_scanner_test.rb +0 -155
  197. data/test/sass/util/normalized_map_test.rb +0 -51
  198. data/test/sass/util/subset_map_test.rb +0 -91
  199. data/test/sass/util_test.rb +0 -438
  200. data/test/sass/value_helpers_test.rb +0 -179
  201. data/test/test_helper.rb +0 -110
  202. data/vendor/listen/CHANGELOG.md +0 -1
  203. data/vendor/listen/CONTRIBUTING.md +0 -38
  204. data/vendor/listen/Gemfile +0 -20
  205. data/vendor/listen/Guardfile +0 -8
  206. data/vendor/listen/LICENSE +0 -20
  207. data/vendor/listen/README.md +0 -349
  208. data/vendor/listen/Rakefile +0 -5
  209. data/vendor/listen/Vagrantfile +0 -96
  210. data/vendor/listen/lib/listen.rb +0 -54
  211. data/vendor/listen/lib/listen/adapter.rb +0 -327
  212. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -75
  213. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -48
  214. data/vendor/listen/lib/listen/adapters/linux.rb +0 -81
  215. data/vendor/listen/lib/listen/adapters/polling.rb +0 -58
  216. data/vendor/listen/lib/listen/adapters/windows.rb +0 -91
  217. data/vendor/listen/lib/listen/directory_record.rb +0 -406
  218. data/vendor/listen/lib/listen/listener.rb +0 -323
  219. data/vendor/listen/lib/listen/turnstile.rb +0 -32
  220. data/vendor/listen/lib/listen/version.rb +0 -3
  221. data/vendor/listen/listen.gemspec +0 -28
  222. data/vendor/listen/spec/listen/adapter_spec.rb +0 -149
  223. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  224. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  225. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  226. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  227. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  228. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1250
  229. data/vendor/listen/spec/listen/listener_spec.rb +0 -258
  230. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  231. data/vendor/listen/spec/listen_spec.rb +0 -67
  232. data/vendor/listen/spec/spec_helper.rb +0 -25
  233. data/vendor/listen/spec/support/adapter_helper.rb +0 -666
  234. data/vendor/listen/spec/support/directory_record_helper.rb +0 -57
  235. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  236. data/vendor/listen/spec/support/listeners_helper.rb +0 -179
  237. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -1,96 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.dirname(__FILE__) + '/../test_helper'
3
- require 'fileutils'
4
- require 'sass/util/test'
5
- require 'tmpdir'
6
-
7
- class ExecTest < MiniTest::Test
8
- include Sass::Util::Test
9
-
10
- def setup
11
- @dir = Dir.mktmpdir
12
- end
13
-
14
- def teardown
15
- FileUtils.rm_rf(@dir)
16
- clean_up_sassc
17
- end
18
-
19
- def test_scss_t_expanded
20
- src = get_path("src.scss")
21
- dest = get_path("dest.css")
22
- write(src, ".ruleset { margin: 0 }")
23
- assert(exec(*%w[scss --sourcemap=none -t expanded --unix-newlines].push(src, dest)))
24
- assert_equal(".ruleset {\n margin: 0;\n}\n", read(dest))
25
- end
26
-
27
- def test_sass_convert_T_sass
28
- src = get_path("src.scss")
29
- dest = get_path("dest.css")
30
- write(src, ".ruleset { margin: 0 }")
31
- assert(exec(*%w[sass-convert -T sass --unix-newlines].push(src, dest)))
32
- assert_equal(".ruleset\n margin: 0\n", read(dest))
33
- end
34
-
35
- def test_sass_convert_T_sass_in_place
36
- src = get_path("src.scss")
37
- write(src, ".ruleset { margin: 0 }")
38
- assert(exec(*%w[sass-convert -T sass --in-place --unix-newlines].push(src)))
39
- assert_equal(".ruleset\n margin: 0\n", read(src))
40
- end
41
-
42
- def test_scss_t_expanded_no_unix_newlines
43
- return skip "Can be run on Windows only" unless Sass::Util.windows?
44
- src = get_path("src.scss")
45
- dest = get_path("dest.css")
46
- write(src, ".ruleset { margin: 0 }")
47
- assert(exec(*%w[scss -t expanded].push(src, dest)))
48
- assert_equal(".ruleset {\r\n margin: 0;\r\n}\r\n", read(dest))
49
- end
50
-
51
- def test_sass_convert_T_sass_no_unix_newlines
52
- return skip "Can be run on Windows only" unless Sass::Util.windows?
53
- src = get_path("src.scss")
54
- dest = get_path("dest.sass")
55
- write(src, ".ruleset { margin: 0 }")
56
- assert(exec(*%w[sass-convert -T sass].push(src, dest)))
57
- assert_equal(".ruleset\r\n margin: 0\r\n", read(dest))
58
- end
59
-
60
- def test_sass_convert_T_sass_in_place_no_unix_newlines
61
- return skip "Can be run on Windows only" unless Sass::Util.windows?
62
- src = get_path("src.scss")
63
- write(src, ".ruleset { margin: 0 }")
64
- assert(exec(*%w[sass-convert -T sass --in-place].push(src)))
65
- assert_equal(".ruleset\r\n margin: 0\r\n", read(src))
66
- end
67
-
68
- def test_sass_convert_R
69
- Dir.chdir(@dir) do
70
- src = get_path("styles/src.css")
71
- write(src, ".ruleset { margin: 0 }")
72
- assert(exec(*%w[sass-convert -Rq --from css --to scss --trace styles]))
73
- end
74
- end
75
-
76
- private
77
-
78
- def get_path(name)
79
- File.join(@dir, name)
80
- end
81
-
82
- def read(file)
83
- open(file, 'rb') {|f| f.read}
84
- end
85
-
86
- def write(file, content)
87
- FileUtils.mkdir_p(File.dirname(file))
88
- open(file, 'wb') {|f| f.write(content)}
89
- end
90
-
91
- def exec(script, *args)
92
- script = File.dirname(__FILE__) + '/../../bin/' + script
93
- ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT'])
94
- system(ruby, script, *args)
95
- end
96
- end
@@ -1,1733 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.dirname(__FILE__) + '/../test_helper'
3
-
4
- class ExtendTest < MiniTest::Test
5
- def test_basic
6
- assert_equal <<CSS, render(<<SCSS)
7
- .foo, .bar {
8
- a: b; }
9
- CSS
10
- .foo {a: b}
11
- .bar {@extend .foo}
12
- SCSS
13
-
14
- assert_equal <<CSS, render(<<SCSS)
15
- .foo, .bar {
16
- a: b; }
17
- CSS
18
- .bar {@extend .foo}
19
- .foo {a: b}
20
- SCSS
21
-
22
- assert_equal <<CSS, render(<<SCSS)
23
- .foo, .bar {
24
- a: b; }
25
-
26
- .bar {
27
- c: d; }
28
- CSS
29
- .foo {a: b}
30
- .bar {c: d; @extend .foo}
31
- SCSS
32
-
33
- assert_equal <<CSS, render(<<SCSS)
34
- .foo, .bar {
35
- a: b; }
36
-
37
- .bar {
38
- c: d; }
39
- CSS
40
- .foo {a: b}
41
- .bar {@extend .foo; c: d}
42
- SCSS
43
- end
44
-
45
- def test_indented_syntax
46
- assert_equal <<CSS, render(<<SASS, :syntax => :sass)
47
- .foo, .bar {
48
- a: b; }
49
- CSS
50
- .foo
51
- a: b
52
- .bar
53
- @extend .foo
54
- SASS
55
-
56
- assert_equal <<CSS, render(<<SASS, :syntax => :sass)
57
- .foo, .bar {
58
- a: b; }
59
- CSS
60
- .foo
61
- a: b
62
- .bar
63
- @extend \#{".foo"}
64
- SASS
65
- end
66
-
67
- def test_multiple_targets
68
- assert_equal <<CSS, render(<<SCSS)
69
- .foo, .bar {
70
- a: b; }
71
-
72
- .blip .foo, .blip .bar {
73
- c: d; }
74
- CSS
75
- .foo {a: b}
76
- .bar {@extend .foo}
77
- .blip .foo {c: d}
78
- SCSS
79
- end
80
-
81
- def test_multiple_extendees
82
- assert_equal <<CSS, render(<<SCSS)
83
- .foo, .baz {
84
- a: b; }
85
-
86
- .bar, .baz {
87
- c: d; }
88
- CSS
89
- .foo {a: b}
90
- .bar {c: d}
91
- .baz {@extend .foo; @extend .bar}
92
- SCSS
93
- end
94
-
95
- def test_multiple_extends_with_single_extender_and_single_target
96
- assert_extends('.foo .bar', '.baz {@extend .foo; @extend .bar}',
97
- '.foo .bar, .baz .bar, .foo .baz, .baz .baz')
98
- assert_extends '.foo.bar', '.baz {@extend .foo; @extend .bar}', '.foo.bar, .baz'
99
- end
100
-
101
- def test_multiple_extends_with_multiple_extenders_and_single_target
102
- assert_equal <<CSS, render(<<SCSS)
103
- .foo .bar, .baz .bar, .foo .bang, .baz .bang {
104
- a: b; }
105
- CSS
106
- .foo .bar {a: b}
107
- .baz {@extend .foo}
108
- .bang {@extend .bar}
109
- SCSS
110
-
111
- assert_equal <<CSS, render(<<SCSS)
112
- .foo.bar, .bar.baz, .baz.bang, .foo.bang {
113
- a: b; }
114
- CSS
115
- .foo.bar {a: b}
116
- .baz {@extend .foo}
117
- .bang {@extend .bar}
118
- SCSS
119
- end
120
-
121
- def test_chained_extends
122
- assert_equal <<CSS, render(<<SCSS)
123
- .foo, .bar, .baz, .bip {
124
- a: b; }
125
- CSS
126
- .foo {a: b}
127
- .bar {@extend .foo}
128
- .baz {@extend .bar}
129
- .bip {@extend .bar}
130
- SCSS
131
- end
132
-
133
- def test_dynamic_extendee
134
- assert_extends '.foo', '.bar {@extend #{".foo"}}', '.foo, .bar'
135
- assert_extends('[baz^="blip12px"]', '.bar {@extend [baz^="blip#{12px}"]}',
136
- '[baz^="blip12px"], .bar')
137
- end
138
-
139
- def test_nested_target
140
- assert_extends '.foo .bar', '.baz {@extend .bar}', '.foo .bar, .foo .baz'
141
- end
142
-
143
- def test_target_with_child
144
- assert_extends '.foo .bar', '.baz {@extend .foo}', '.foo .bar, .baz .bar'
145
- end
146
-
147
- def test_class_unification
148
- assert_unification '.foo.bar', '.baz {@extend .foo}', '.foo.bar, .bar.baz'
149
- assert_unification '.foo.baz', '.baz {@extend .foo}', '.baz'
150
- end
151
-
152
- def test_id_unification
153
- assert_unification '.foo.bar', '#baz {@extend .foo}', '.foo.bar, .bar#baz'
154
- assert_unification '.foo#baz', '#baz {@extend .foo}', '#baz'
155
-
156
- assert_extend_doesnt_match('#bar', '.foo', :failed_to_unify, 2) do
157
- render_unification '.foo#baz', '#bar {@extend .foo}'
158
- end
159
- end
160
-
161
- def test_universal_unification_with_simple_target
162
- assert_unification '.foo', '* {@extend .foo}', '.foo, *'
163
- assert_unification '.foo', '*|* {@extend .foo}', '.foo, *|*'
164
- assert_unification '.foo.bar', '* {@extend .foo}', '.bar'
165
- assert_unification '.foo.bar', '*|* {@extend .foo}', '.bar'
166
- assert_unification '.foo.bar', 'ns|* {@extend .foo}', '.foo.bar, ns|*.bar'
167
- end
168
-
169
- def test_universal_unification_with_namespaceless_universal_target
170
- assert_extend_doesnt_match('ns|*', '.foo', :failed_to_unify, 2) do
171
- render_unification '*.foo', 'ns|* {@extend .foo}'
172
- end
173
-
174
- assert_unification '*.foo', '* {@extend .foo}', '*'
175
- assert_unification '*.foo', '*|* {@extend .foo}', '*'
176
- assert_unification '*|*.foo', '* {@extend .foo}', '*|*.foo, *'
177
- assert_unification '*|*.foo', '*|* {@extend .foo}', '*|*'
178
- assert_unification '*|*.foo', 'ns|* {@extend .foo}', '*|*.foo, ns|*'
179
- end
180
-
181
- def test_universal_unification_with_namespaced_universal_target
182
- assert_extend_doesnt_match('*', '.foo', :failed_to_unify, 2) do
183
- render_unification 'ns|*.foo', '* {@extend .foo}'
184
- end
185
-
186
- assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
187
- render_unification 'ns1|*.foo', 'ns2|* {@extend .foo}'
188
- end
189
-
190
- assert_unification 'ns|*.foo', '*|* {@extend .foo}', 'ns|*'
191
- assert_unification 'ns|*.foo', 'ns|* {@extend .foo}', 'ns|*'
192
- end
193
-
194
- def test_universal_unification_with_namespaceless_element_target
195
- assert_extend_doesnt_match('ns|*', '.foo', :failed_to_unify, 2) do
196
- render_unification 'a.foo', 'ns|* {@extend .foo}'
197
- end
198
-
199
- assert_unification 'a.foo', '* {@extend .foo}', 'a'
200
- assert_unification 'a.foo', '*|* {@extend .foo}', 'a'
201
- assert_unification '*|a.foo', '* {@extend .foo}', '*|a.foo, a'
202
- assert_unification '*|a.foo', '*|* {@extend .foo}', '*|a'
203
- assert_unification '*|a.foo', 'ns|* {@extend .foo}', '*|a.foo, ns|a'
204
- end
205
-
206
- def test_universal_unification_with_namespaced_element_target
207
- assert_extend_doesnt_match('*', '.foo', :failed_to_unify, 2) do
208
- render_unification 'ns|a.foo', '* {@extend .foo}'
209
- end
210
-
211
- assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
212
- render_unification 'ns1|a.foo', 'ns2|* {@extend .foo}'
213
- end
214
-
215
- assert_unification 'ns|a.foo', '*|* {@extend .foo}', 'ns|a'
216
- assert_unification 'ns|a.foo', 'ns|* {@extend .foo}', 'ns|a'
217
- end
218
-
219
- def test_element_unification_with_simple_target
220
- assert_unification '.foo', 'a {@extend .foo}', '.foo, a'
221
- assert_unification '.foo.bar', 'a {@extend .foo}', '.foo.bar, a.bar'
222
- assert_unification '.foo.bar', '*|a {@extend .foo}', '.foo.bar, *|a.bar'
223
- assert_unification '.foo.bar', 'ns|a {@extend .foo}', '.foo.bar, ns|a.bar'
224
- end
225
-
226
- def test_element_unification_with_namespaceless_universal_target
227
- assert_extend_doesnt_match('ns|a', '.foo', :failed_to_unify, 2) do
228
- render_unification '*.foo', 'ns|a {@extend .foo}'
229
- end
230
-
231
- assert_unification '*.foo', 'a {@extend .foo}', '*.foo, a'
232
- assert_unification '*.foo', '*|a {@extend .foo}', '*.foo, a'
233
- assert_unification '*|*.foo', 'a {@extend .foo}', '*|*.foo, a'
234
- assert_unification '*|*.foo', '*|a {@extend .foo}', '*|*.foo, *|a'
235
- assert_unification '*|*.foo', 'ns|a {@extend .foo}', '*|*.foo, ns|a'
236
- end
237
-
238
- def test_element_unification_with_namespaced_universal_target
239
- assert_extend_doesnt_match('a', '.foo', :failed_to_unify, 2) do
240
- render_unification 'ns|*.foo', 'a {@extend .foo}'
241
- end
242
-
243
- assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
244
- render_unification 'ns1|*.foo', 'ns2|a {@extend .foo}'
245
- end
246
-
247
- assert_unification 'ns|*.foo', '*|a {@extend .foo}', 'ns|*.foo, ns|a'
248
- assert_unification 'ns|*.foo', 'ns|a {@extend .foo}', 'ns|*.foo, ns|a'
249
- end
250
-
251
- def test_element_unification_with_namespaceless_element_target
252
- assert_extend_doesnt_match('ns|a', '.foo', :failed_to_unify, 2) do
253
- render_unification 'a.foo', 'ns|a {@extend .foo}'
254
- end
255
-
256
- assert_extend_doesnt_match('h1', '.foo', :failed_to_unify, 2) do
257
- render_unification 'a.foo', 'h1 {@extend .foo}'
258
- end
259
-
260
- assert_unification 'a.foo', 'a {@extend .foo}', 'a'
261
- assert_unification 'a.foo', '*|a {@extend .foo}', 'a'
262
- assert_unification '*|a.foo', 'a {@extend .foo}', '*|a.foo, a'
263
- assert_unification '*|a.foo', '*|a {@extend .foo}', '*|a'
264
- assert_unification '*|a.foo', 'ns|a {@extend .foo}', '*|a.foo, ns|a'
265
- end
266
-
267
- def test_element_unification_with_namespaced_element_target
268
- assert_extend_doesnt_match('a', '.foo', :failed_to_unify, 2) do
269
- render_unification 'ns|a.foo', 'a {@extend .foo}'
270
- end
271
-
272
- assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
273
- render_unification 'ns1|a.foo', 'ns2|a {@extend .foo}'
274
- end
275
-
276
- assert_unification 'ns|a.foo', '*|a {@extend .foo}', 'ns|a'
277
- assert_unification 'ns|a.foo', 'ns|a {@extend .foo}', 'ns|a'
278
- end
279
-
280
- def test_attribute_unification
281
- assert_unification '[foo=bar].baz', '[foo=baz] {@extend .baz}', '[foo=bar].baz, [foo=bar][foo=baz]'
282
- assert_unification '[foo=bar].baz', '[foo^=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][foo^=bar]'
283
- assert_unification '[foo=bar].baz', '[foot=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][foot=bar]'
284
- assert_unification '[foo=bar].baz', '[ns|foo=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][ns|foo=bar]'
285
- assert_unification '%-a [foo=bar].bar', '[foo=bar] {@extend .bar}', '-a [foo=bar]'
286
- end
287
-
288
- def test_pseudo_unification
289
- assert_unification ':foo.baz', ':foo(2n+1) {@extend .baz}', ':foo.baz, :foo:foo(2n+1)'
290
- assert_unification ':foo.baz', '::foo {@extend .baz}', ':foo.baz, :foo::foo'
291
-
292
- assert_extend_doesnt_match('::bar', '.baz', :failed_to_unify, 2) do
293
- render_unification '::foo.baz', '::bar {@extend .baz}'
294
- end
295
-
296
- assert_extend_doesnt_match('::foo(2n+1)', '.baz', :failed_to_unify, 2) do
297
- render_unification '::foo.baz', '::foo(2n+1) {@extend .baz}'
298
- end
299
-
300
- assert_unification '::foo.baz', '::foo {@extend .baz}', '::foo'
301
- assert_unification '::foo(2n+1).baz', '::foo(2n+1) {@extend .baz}', '::foo(2n+1)'
302
- assert_unification ':foo.baz', ':bar {@extend .baz}', ':foo.baz, :foo:bar'
303
- assert_unification '.baz:foo', ':after {@extend .baz}', '.baz:foo, :foo:after'
304
- assert_unification '.baz:after', ':foo {@extend .baz}', '.baz:after, :foo:after'
305
- assert_unification ':foo.baz', ':foo {@extend .baz}', ':foo'
306
- end
307
-
308
- def test_pseudoelement_remains_at_end_of_selector
309
- assert_extends '.foo::bar', '.baz {@extend .foo}', '.foo::bar, .baz::bar'
310
- assert_extends 'a.foo::bar', '.baz {@extend .foo}', 'a.foo::bar, a.baz::bar'
311
- end
312
-
313
- def test_pseudoclass_remains_at_end_of_selector
314
- assert_extends '.foo:bar', '.baz {@extend .foo}', '.foo:bar, .baz:bar'
315
- assert_extends 'a.foo:bar', '.baz {@extend .foo}', 'a.foo:bar, a.baz:bar'
316
- end
317
-
318
- def test_not_remains_at_end_of_selector
319
- assert_extends '.foo:not(.bar)', '.baz {@extend .foo}', '.foo:not(.bar), .baz:not(.bar)'
320
- end
321
-
322
- def test_pseudoelement_goes_lefter_than_pseudoclass
323
- assert_extends '.foo::bar', '.baz:bang {@extend .foo}', '.foo::bar, .baz:bang::bar'
324
- assert_extends '.foo:bar', '.baz::bang {@extend .foo}', '.foo:bar, .baz:bar::bang'
325
- end
326
-
327
- def test_pseudoelement_goes_lefter_than_not
328
- assert_extends '.foo::bar', '.baz:not(.bang) {@extend .foo}', '.foo::bar, .baz:not(.bang)::bar'
329
- assert_extends '.foo:not(.bang)', '.baz::bar {@extend .foo}', '.foo:not(.bang), .baz:not(.bang)::bar'
330
- end
331
-
332
- def test_negation_unification
333
- assert_extends ':not(.foo).baz', ':not(.bar) {@extend .baz}', ':not(.foo).baz, :not(.foo):not(.bar)'
334
- # Unifying to :not(.foo) here would reduce the specificity of the original selector.
335
- assert_extends ':not(.foo).baz', ':not(.foo) {@extend .baz}', ':not(.foo).baz, :not(.foo)'
336
- end
337
-
338
- def test_prefixed_pseudoclass_unification
339
- assert_unification(
340
- ':nth-child(2n+1 of .foo).baz',
341
- ':nth-child(2n of .foo) {@extend .baz}',
342
- ':nth-child(2n+1 of .foo).baz, :nth-child(2n+1 of .foo):nth-child(2n of .foo)')
343
-
344
- assert_unification(
345
- ':nth-child(2n+1 of .foo).baz',
346
- ':nth-child(2n+1 of .bar) {@extend .baz}',
347
- ':nth-child(2n+1 of .foo).baz, :nth-child(2n+1 of .foo):nth-child(2n+1 of .bar)')
348
-
349
- assert_unification(
350
- ':nth-child(2n+1 of .foo).baz',
351
- ':nth-child(2n+1 of .foo) {@extend .baz}',
352
- ':nth-child(2n+1 of .foo)')
353
- end
354
-
355
- def test_extend_into_not
356
- assert_extends(':not(.foo)', '.x {@extend .foo}', ':not(.foo):not(.x)')
357
- assert_extends(':not(.foo.bar)', '.x {@extend .bar}', ':not(.foo.bar):not(.foo.x)')
358
- assert_extends(
359
- ':not(.foo.bar, .baz.bar)',
360
- '.x {@extend .bar}',
361
- ':not(.foo.bar, .foo.x, .baz.bar, .baz.x)')
362
- end
363
-
364
- def test_extend_into_mergeable_pseudoclasses
365
- assert_extends(':matches(.foo)', '.x {@extend .foo}', ':matches(.foo, .x)')
366
- assert_extends(':matches(.foo.bar)', '.x {@extend .bar}', ':matches(.foo.bar, .foo.x)')
367
- assert_extends(
368
- ':matches(.foo.bar, .baz.bar)',
369
- '.x {@extend .bar}',
370
- ':matches(.foo.bar, .foo.x, .baz.bar, .baz.x)')
371
-
372
- assert_extends(':-moz-any(.foo)', '.x {@extend .foo}', ':-moz-any(.foo, .x)')
373
- assert_extends(':current(.foo)', '.x {@extend .foo}', ':current(.foo, .x)')
374
- assert_extends(':has(.foo)', '.x {@extend .foo}', ':has(.foo, .x)')
375
- assert_extends(':host(.foo)', '.x {@extend .foo}', ':host(.foo, .x)')
376
- assert_extends(':host-context(.foo)', '.x {@extend .foo}', ':host-context(.foo, .x)')
377
- assert_extends(':nth-child(n of .foo)', '.x {@extend .foo}', ':nth-child(n of .foo, .x)')
378
- assert_extends(
379
- ':nth-last-child(n of .foo)',
380
- '.x {@extend .foo}',
381
- ':nth-last-child(n of .foo, .x)')
382
- end
383
-
384
- def test_complex_extend_into_pseudoclass
385
- # Unlike other selectors, we don't allow complex selectors to be
386
- # added to `:not` if they weren't there before. At time of
387
- # writing, most browsers don't support that and will throw away
388
- # the entire selector if it exists.
389
- #assert_extends(':not(.bar)', '.x .y {@extend .bar}', ':not(.bar)')
390
-
391
- # If the `:not()` already has a complex selector, we won't break
392
- # anything by adding a new one.
393
- assert_extends(':not(.baz .bar)', '.x .y {@extend .bar}',
394
- ':not(.baz .bar):not(.baz .x .y):not(.x .baz .y)')
395
-
396
- # If the `:not()` would only contain complex selectors, there's no
397
- # harm in letting it continue to exist.
398
- assert_extends(':not(%bar)', '.x .y {@extend %bar}', ':not(.x .y)')
399
-
400
- assert_extends(':matches(.bar)', '.x .y {@extend .bar}', ':matches(.bar, .x .y)')
401
- assert_extends(':current(.bar)', '.x .y {@extend .bar}', ':current(.bar, .x .y)')
402
- assert_extends(':has(.bar)', '.x .y {@extend .bar}', ':has(.bar, .x .y)')
403
- assert_extends(':host(.bar)', '.x .y {@extend .bar}', ':host(.bar, .x .y)')
404
- assert_extends(':host-context(.bar)', '.x .y {@extend .bar}', ':host-context(.bar, .x .y)')
405
- assert_extends(
406
- ':-moz-any(.bar)',
407
- '.x .y {@extend .bar}',
408
- ':-moz-any(.bar, .x .y)')
409
- assert_extends(
410
- ':nth-child(n of .bar)',
411
- '.x .y {@extend .bar}',
412
- ':nth-child(n of .bar, .x .y)')
413
- assert_extends(
414
- ':nth-last-child(n of .bar)',
415
- '.x .y {@extend .bar}',
416
- ':nth-last-child(n of .bar, .x .y)')
417
- end
418
-
419
- def test_extend_over_selector_pseudoclass
420
- assert_extends(':not(.foo)', '.x {@extend :not(.foo)}', ':not(.foo), .x')
421
- assert_extends(
422
- ':matches(.foo, .bar)',
423
- '.x {@extend :matches(.foo, .bar)}',
424
- ':matches(.foo, .bar), .x')
425
- end
426
-
427
- def test_matches_within_not
428
- assert_extends(
429
- ':not(.foo, .bar)',
430
- ':matches(.x, .y) {@extend .foo}',
431
- ':not(.foo, .x, .y, .bar)')
432
- end
433
-
434
- def test_pseudoclasses_merge
435
- assert_extends(':matches(.foo)', ':matches(.bar) {@extend .foo}', ':matches(.foo, .bar)')
436
- assert_extends(':-moz-any(.foo)', ':-moz-any(.bar) {@extend .foo}', ':-moz-any(.foo, .bar)')
437
- assert_extends(':current(.foo)', ':current(.bar) {@extend .foo}', ':current(.foo, .bar)')
438
- assert_extends(
439
- ':nth-child(n of .foo)',
440
- ':nth-child(n of .bar) {@extend .foo}',
441
- ':nth-child(n of .foo, .bar)')
442
- assert_extends(
443
- ':nth-last-child(n of .foo)',
444
- ':nth-last-child(n of .bar) {@extend .foo}',
445
- ':nth-last-child(n of .foo, .bar)')
446
- end
447
-
448
- def test_nesting_pseudoclasses_merge
449
- assert_extends(':has(.foo)', ':has(.bar) {@extend .foo}', ':has(.foo, :has(.bar))')
450
- assert_extends(':host(.foo)', ':host(.bar) {@extend .foo}', ':host(.foo, :host(.bar))')
451
- assert_extends(
452
- ':host-context(.foo)',
453
- ':host-context(.bar) {@extend .foo}',
454
- ':host-context(.foo, :host-context(.bar))')
455
- end
456
-
457
- def test_not_unifies_with_unique_values
458
- assert_unification('foo', ':not(bar) {@extend foo}', ':not(bar)')
459
- assert_unification('#foo', ':not(#bar) {@extend #foo}', ':not(#bar)')
460
- end
461
-
462
- def test_not_adds_no_specificity
463
- assert_specificity_equals(':not(.foo)', '.foo')
464
- end
465
-
466
- def test_matches_has_a_specificity_range
467
- # `:matches(.foo, #bar)` has minimum specificity equal to that of `.foo`,
468
- # which means `:matches(.foo, #bar) .a` can have less specificity than
469
- # `#b.a`. Thus the selector generated by `#b.a` should be preserved.
470
- assert_equal <<CSS, render(<<SCSS)
471
- :matches(.foo, #bar) .a, :matches(.foo, #bar) #b.a {
472
- a: b; }
473
- CSS
474
- :matches(.foo, #bar) %x {a: b}
475
- .a {@extend %x}
476
- #b.a {@extend %x}
477
- SCSS
478
-
479
- # `:matches(.foo, #bar)` has maximum specificity equal to that of `#bar`,
480
- # which means `:matches(.foo, #bar).b` can have greater specificity than `.a
481
- # .b`. Thus the selector generated by `:matches(.foo, #bar).b` should be
482
- # preserved.
483
- assert_equal <<CSS, render(<<SCSS)
484
- .a .b, .a .b:matches(.foo, #bar) {
485
- a: b; }
486
- CSS
487
- .a %x {a: b}
488
- .b {@extend %x}
489
- .b:matches(.foo, #bar) {@extend %x}
490
- SCSS
491
- end
492
-
493
- def test_extend_into_not_and_normal_extend
494
- assert_equal <<CSS, render(<<SCSS)
495
- .x:not(.y):not(.bar), .foo:not(.y):not(.bar) {
496
- a: b; }
497
- CSS
498
- .x:not(.y) {a: b}
499
- .foo {@extend .x}
500
- .bar {@extend .y}
501
- SCSS
502
- end
503
-
504
- def test_extend_into_matches_and_normal_extend
505
- assert_equal <<CSS, render(<<SCSS)
506
- .x:matches(.y, .bar), .foo:matches(.y, .bar) {
507
- a: b; }
508
- CSS
509
- .x:matches(.y) {a: b}
510
- .foo {@extend .x}
511
- .bar {@extend .y}
512
- SCSS
513
- end
514
-
515
- def test_multilayer_pseudoclass_extend
516
- assert_equal <<CSS, render(<<SCSS)
517
- :matches(.x, .foo, .bar) {
518
- a: b; }
519
- CSS
520
- :matches(.x) {a: b}
521
- .foo {@extend .x}
522
- .bar {@extend .foo}
523
- SCSS
524
- end
525
-
526
- def test_root_only_allowed_at_root
527
- assert_extends(':root .foo', '.bar .baz {@extend .foo}',
528
- ':root .foo, :root .bar .baz')
529
- assert_extends('.foo:root .bar', '.baz:root .bang {@extend .bar}',
530
- '.foo:root .bar, .baz.foo:root .bang')
531
- assert_extends('html:root .bar', 'xml:root .bang {@extend .bar}', 'html:root .bar')
532
- assert_extends('.foo:root > .bar .x', '.baz:root .bang .y {@extend .x}',
533
- '.foo:root > .bar .x, .baz.foo:root > .bar .bang .y')
534
- end
535
-
536
- def test_comma_extendee
537
- assert_equal <<CSS, render(<<SCSS)
538
- .foo, .baz {
539
- a: b; }
540
-
541
- .bar, .baz {
542
- c: d; }
543
- CSS
544
- .foo {a: b}
545
- .bar {c: d}
546
- .baz {@extend .foo, .bar}
547
- SCSS
548
- end
549
-
550
- def test_redundant_selector_elimination
551
- assert_equal <<CSS, render(<<SCSS)
552
- .foo.bar, .x, .y {
553
- a: b; }
554
- CSS
555
- .foo.bar {a: b}
556
- .x {@extend .foo, .bar}
557
- .y {@extend .foo, .bar}
558
- SCSS
559
- end
560
-
561
- def test_nested_pseudo_selectors
562
- assert_equal <<CSS, render(<<SCSS)
563
- .foo .bar:not(.baz), .bang .bar:not(.baz) {
564
- a: b; }
565
- CSS
566
- .foo {
567
- .bar:not(.baz) {a: b}
568
- }
569
- .bang {@extend .foo}
570
- SCSS
571
- end
572
-
573
- ## Long Extendees
574
-
575
- def test_long_extendee
576
- assert_warning(<<WARNING) {assert_extends '.foo.bar', '.baz {@extend .foo.bar}', '.foo.bar, .baz'}
577
- DEPRECATION WARNING on line 2 of test_long_extendee_inline.scss:
578
- Extending a compound selector, .foo.bar, is deprecated and will not be supported in a future release.
579
- See https://github.com/sass/sass/issues/1599 for details.
580
- WARNING
581
- end
582
-
583
- def test_long_extendee_requires_all_selectors
584
- silence_warnings do
585
- assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
586
- render_extends '.foo', '.baz {@extend .foo.bar}'
587
- end
588
- end
589
- end
590
-
591
- def test_long_extendee_matches_supersets
592
- silence_warnings {assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'}
593
- end
594
-
595
- def test_long_extendee_runs_unification
596
- silence_warnings {assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'}
597
- end
598
-
599
- ## Long Extenders
600
-
601
- def test_long_extender
602
- assert_extends '.foo.bar', '.baz.bang {@extend .foo}', '.foo.bar, .bar.baz.bang'
603
- end
604
-
605
- def test_long_extender_runs_unification
606
- assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
607
- end
608
-
609
- def test_long_extender_aborts_unification
610
- assert_extend_doesnt_match('h1.baz', '.foo', :failed_to_unify, 2) do
611
- render_extends 'a.foo#bar', 'h1.baz {@extend .foo}'
612
- end
613
-
614
- assert_extend_doesnt_match('.bang#baz', '.foo', :failed_to_unify, 2) do
615
- render_extends 'a.foo#bar', '.bang#baz {@extend .foo}'
616
- end
617
- end
618
-
619
- ## Nested Extenders
620
-
621
- def test_nested_extender
622
- assert_extends '.foo', 'foo bar {@extend .foo}', '.foo, foo bar'
623
- end
624
-
625
- def test_nested_extender_runs_unification
626
- assert_extends '.foo.bar', 'foo bar {@extend .foo}', '.foo.bar, foo bar.bar'
627
- end
628
-
629
- def test_nested_extender_aborts_unification
630
- assert_extend_doesnt_match('foo bar', '.foo', :failed_to_unify, 2) do
631
- render_extends 'baz.foo', 'foo bar {@extend .foo}'
632
- end
633
- end
634
-
635
- def test_nested_extender_alternates_parents
636
- assert_extends('.baz .bip .foo', 'foo .grank bar {@extend .foo}',
637
- '.baz .bip .foo, .baz .bip foo .grank bar, foo .grank .baz .bip bar')
638
- end
639
-
640
- def test_nested_extender_unifies_identical_parents
641
- assert_extends('.baz .bip .foo', '.baz .bip bar {@extend .foo}',
642
- '.baz .bip .foo, .baz .bip bar')
643
- end
644
-
645
- def test_nested_extender_unifies_common_substring
646
- assert_extends('.baz .bip .bap .bink .foo', '.brat .bip .bap bar {@extend .foo}',
647
- '.baz .bip .bap .bink .foo, .baz .brat .bip .bap .bink bar, .brat .baz .bip .bap .bink bar')
648
- end
649
-
650
- def test_nested_extender_unifies_common_subseq
651
- assert_extends('.a .x .b .y .foo', '.a .n .b .m bar {@extend .foo}',
652
- '.a .x .b .y .foo, .a .x .n .b .y .m bar, .a .n .x .b .y .m bar, .a .x .n .b .m .y bar, .a .n .x .b .m .y bar')
653
- end
654
-
655
- def test_nested_extender_chooses_first_subseq
656
- assert_extends('.a .b .c .d .foo', '.c .d .a .b .bar {@extend .foo}',
657
- '.a .b .c .d .foo, .a .b .c .d .a .b .bar')
658
- end
659
-
660
- def test_nested_extender_counts_extended_subselectors
661
- assert_extends('.a .bip.bop .foo', '.b .bip .bar {@extend .foo}',
662
- '.a .bip.bop .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
663
- end
664
-
665
- def test_nested_extender_counts_extended_superselectors
666
- assert_extends('.a .bip .foo', '.b .bip.bop .bar {@extend .foo}',
667
- '.a .bip .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
668
- end
669
-
670
- def test_nested_extender_with_child_selector
671
- assert_extends '.baz .foo', 'foo > bar {@extend .foo}', '.baz .foo, .baz foo > bar'
672
- end
673
-
674
- def test_nested_extender_finds_common_selectors_around_child_selector
675
- assert_extends 'a > b c .c1', 'a c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
676
- assert_extends 'a > b c .c1', 'b c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
677
- end
678
-
679
- def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector
680
- assert_extends 'a + b c .c1', 'a c .c2 {@extend .c1}', 'a + b c .c1, a + b a c .c2, a a + b c .c2'
681
- assert_extends 'a + b c .c1', 'a b .c2 {@extend .c1}', 'a + b c .c1, a a + b c .c2'
682
- assert_extends 'a + b c .c1', 'b c .c2 {@extend .c1}', 'a + b c .c1, a + b c .c2'
683
- end
684
-
685
- def test_nested_extender_doesnt_find_common_selectors_around_sibling_selector
686
- assert_extends 'a ~ b c .c1', 'a c .c2 {@extend .c1}', 'a ~ b c .c1, a ~ b a c .c2, a a ~ b c .c2'
687
- assert_extends 'a ~ b c .c1', 'a b .c2 {@extend .c1}', 'a ~ b c .c1, a a ~ b c .c2'
688
- assert_extends 'a ~ b c .c1', 'b c .c2 {@extend .c1}', 'a ~ b c .c1, a ~ b c .c2'
689
- end
690
-
691
- def test_nested_extender_doesnt_find_common_selectors_around_reference_selector
692
- silence_warnings {assert_extends 'a /for/ b c .c1', 'a c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b a c .c2, a a /for/ b c .c2'}
693
- silence_warnings {assert_extends 'a /for/ b c .c1', 'a b .c2 {@extend .c1}', 'a /for/ b c .c1, a a /for/ b c .c2'}
694
- silence_warnings {assert_extends 'a /for/ b c .c1', 'b c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'}
695
- end
696
-
697
- def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
698
- assert_extends('.bip > .bap .foo', '.grip > .bap .bar {@extend .foo}',
699
- '.bip > .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar')
700
- assert_extends('.bap > .bip .foo', '.bap > .grip .bar {@extend .foo}',
701
- '.bap > .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar')
702
- end
703
-
704
- def test_nested_extender_with_child_selector_unifies
705
- assert_extends '.baz.foo', 'foo > bar {@extend .foo}', '.baz.foo, foo > bar.baz'
706
-
707
- assert_equal <<CSS, render(<<SCSS)
708
- .baz > .foo, .baz > .bar {
709
- a: b; }
710
- CSS
711
- .baz > {
712
- .foo {a: b}
713
- .bar {@extend .foo}
714
- }
715
- SCSS
716
-
717
- assert_equal <<CSS, render(<<SCSS)
718
- .foo .bar, .foo > .baz {
719
- a: b; }
720
- CSS
721
- .foo {
722
- .bar {a: b}
723
- > .baz {@extend .bar}
724
- }
725
- SCSS
726
- end
727
-
728
- def test_nested_extender_with_early_child_selector
729
- assert_equal <<CSS, render(<<SCSS)
730
- .foo .bar, .foo .bip > .baz {
731
- a: b; }
732
- CSS
733
- .foo {
734
- .bar {a: b}
735
- .bip > .baz {@extend .bar}
736
- }
737
- SCSS
738
-
739
- assert_equal <<CSS, render(<<SCSS)
740
- .foo .bip .bar, .foo .bip .foo > .baz {
741
- a: b; }
742
- CSS
743
- .foo {
744
- .bip .bar {a: b}
745
- > .baz {@extend .bar}
746
- }
747
- SCSS
748
-
749
- assert_extends '.foo > .bar', '.bip + .baz {@extend .bar}', '.foo > .bar, .foo > .bip + .baz'
750
- assert_extends '.foo + .bar', '.bip > .baz {@extend .bar}', '.foo + .bar, .bip > .foo + .baz'
751
- assert_extends '.foo > .bar', '.bip > .baz {@extend .bar}', '.foo > .bar, .bip.foo > .baz'
752
- end
753
-
754
- def test_nested_extender_with_trailing_child_selector
755
- assert_raises(Sass::SyntaxError, "bar > can't extend: invalid selector") do
756
- render("bar > {@extend .baz}")
757
- end
758
- end
759
-
760
- def test_nested_extender_with_sibling_selector
761
- assert_extends '.baz .foo', 'foo + bar {@extend .foo}', '.baz .foo, .baz foo + bar'
762
- end
763
-
764
- def test_nested_extender_with_hacky_selector
765
- assert_extends('.baz .foo', 'foo + > > + bar {@extend .foo}',
766
- '.baz .foo, .baz foo + > > + bar, foo .baz + > > + bar')
767
- assert_extends '.baz .foo', '> > bar {@extend .foo}', '.baz .foo, > > .baz bar'
768
- end
769
-
770
- def test_nested_extender_merges_with_same_selector
771
- assert_equal <<CSS, render(<<SCSS)
772
- .foo .bar, .foo .baz {
773
- a: b; }
774
- CSS
775
- .foo {
776
- .bar {a: b}
777
- .baz {@extend .bar} }
778
- SCSS
779
- end
780
-
781
- def test_nested_extender_with_child_selector_merges_with_same_selector
782
- assert_extends('.foo > .bar .baz', '.foo > .bar .bang {@extend .baz}',
783
- '.foo > .bar .baz, .foo > .bar .bang')
784
- end
785
-
786
- # Combinator Unification
787
-
788
- def test_combinator_unification_for_hacky_combinators
789
- assert_extends '.a > + x', '.b y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
790
- assert_extends '.a x', '.b > + y {@extend x}', '.a x, .a .b > + y, .b .a > + y'
791
- assert_extends '.a > + x', '.b > + y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
792
- assert_extends '.a ~ > + x', '.b > + y {@extend x}', '.a ~ > + x, .a .b ~ > + y, .b .a ~ > + y'
793
- assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
794
- assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
795
- assert_extends '.a ~ > + .b > x', '.c > + .d > y {@extend x}', '.a ~ > + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y'
796
- end
797
-
798
- def test_combinator_unification_double_tilde
799
- assert_extends '.a.b ~ x', '.a ~ y {@extend x}', '.a.b ~ x, .a.b ~ y'
800
- assert_extends '.a ~ x', '.a.b ~ y {@extend x}', '.a ~ x, .a.b ~ y'
801
- assert_extends '.a ~ x', '.b ~ y {@extend x}', '.a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y'
802
- assert_extends 'a.a ~ x', 'b.b ~ y {@extend x}', 'a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y'
803
- end
804
-
805
- def test_combinator_unification_tilde_plus
806
- assert_extends '.a.b + x', '.a ~ y {@extend x}', '.a.b + x, .a.b + y'
807
- assert_extends '.a + x', '.a.b ~ y {@extend x}', '.a + x, .a.b ~ .a + y, .a.b + y'
808
- assert_extends '.a + x', '.b ~ y {@extend x}', '.a + x, .b ~ .a + y, .b.a + y'
809
- assert_extends 'a.a + x', 'b.b ~ y {@extend x}', 'a.a + x, b.b ~ a.a + y'
810
- assert_extends '.a.b ~ x', '.a + y {@extend x}', '.a.b ~ x, .a.b ~ .a + y, .a.b + y'
811
- assert_extends '.a ~ x', '.a.b + y {@extend x}', '.a ~ x, .a.b + y'
812
- assert_extends '.a ~ x', '.b + y {@extend x}', '.a ~ x, .a ~ .b + y, .a.b + y'
813
- assert_extends 'a.a ~ x', 'b.b + y {@extend x}', 'a.a ~ x, a.a ~ b.b + y'
814
- end
815
-
816
- def test_combinator_unification_angle_sibling
817
- assert_extends '.a > x', '.b ~ y {@extend x}', '.a > x, .a > .b ~ y'
818
- assert_extends '.a > x', '.b + y {@extend x}', '.a > x, .a > .b + y'
819
- assert_extends '.a ~ x', '.b > y {@extend x}', '.a ~ x, .b > .a ~ y'
820
- assert_extends '.a + x', '.b > y {@extend x}', '.a + x, .b > .a + y'
821
- end
822
-
823
- def test_combinator_unification_double_angle
824
- assert_extends '.a.b > x', '.b > y {@extend x}', '.a.b > x, .b.a > y'
825
- assert_extends '.a > x', '.a.b > y {@extend x}', '.a > x, .a.b > y'
826
- assert_extends '.a > x', '.b > y {@extend x}', '.a > x, .b.a > y'
827
- assert_extends 'a.a > x', 'b.b > y {@extend x}', 'a.a > x'
828
- end
829
-
830
- def test_combinator_unification_double_plus
831
- assert_extends '.a.b + x', '.b + y {@extend x}', '.a.b + x, .b.a + y'
832
- assert_extends '.a + x', '.a.b + y {@extend x}', '.a + x, .a.b + y'
833
- assert_extends '.a + x', '.b + y {@extend x}', '.a + x, .b.a + y'
834
- assert_extends 'a.a + x', 'b.b + y {@extend x}', 'a.a + x'
835
- end
836
-
837
- def test_combinator_unification_angle_space
838
- assert_extends '.a.b > x', '.a y {@extend x}', '.a.b > x, .a.b > y'
839
- assert_extends '.a > x', '.a.b y {@extend x}', '.a > x, .a.b .a > y'
840
- assert_extends '.a > x', '.b y {@extend x}', '.a > x, .b .a > y'
841
- assert_extends '.a.b x', '.a > y {@extend x}', '.a.b x, .a.b .a > y'
842
- assert_extends '.a x', '.a.b > y {@extend x}', '.a x, .a.b > y'
843
- assert_extends '.a x', '.b > y {@extend x}', '.a x, .a .b > y'
844
- end
845
-
846
- def test_combinator_unification_plus_space
847
- assert_extends '.a.b + x', '.a y {@extend x}', '.a.b + x, .a .a.b + y'
848
- assert_extends '.a + x', '.a.b y {@extend x}', '.a + x, .a.b .a + y'
849
- assert_extends '.a + x', '.b y {@extend x}', '.a + x, .b .a + y'
850
- assert_extends '.a.b x', '.a + y {@extend x}', '.a.b x, .a.b .a + y'
851
- assert_extends '.a x', '.a.b + y {@extend x}', '.a x, .a .a.b + y'
852
- assert_extends '.a x', '.b + y {@extend x}', '.a x, .a .b + y'
853
- end
854
-
855
- def test_combinator_unification_nested
856
- assert_extends '.a > .b + x', '.c > .d + y {@extend x}', '.a > .b + x, .c.a > .d.b + y'
857
- assert_extends '.a > .b + x', '.c > y {@extend x}', '.a > .b + x, .c.a > .b + y'
858
- end
859
-
860
- def test_combinator_unification_with_newlines
861
- assert_equal <<CSS, render(<<SCSS)
862
- .a >
863
- .b
864
- + x, .c.a > .d.b + y {
865
- a: b; }
866
- CSS
867
- .a >
868
- .b
869
- + x {a: b}
870
- .c
871
- > .d +
872
- y {@extend x}
873
- SCSS
874
- end
875
-
876
- # Loops
877
-
878
- def test_extend_self_loop
879
- assert_equal <<CSS, render(<<SCSS)
880
- .foo {
881
- a: b; }
882
- CSS
883
- .foo {a: b; @extend .foo}
884
- SCSS
885
- end
886
-
887
- def test_basic_extend_loop
888
- assert_equal <<CSS, render(<<SCSS)
889
- .foo, .bar {
890
- a: b; }
891
-
892
- .bar, .foo {
893
- c: d; }
894
- CSS
895
- .foo {a: b; @extend .bar}
896
- .bar {c: d; @extend .foo}
897
- SCSS
898
- end
899
-
900
- def test_three_level_extend_loop
901
- assert_equal <<CSS, render(<<SCSS)
902
- .foo, .baz, .bar {
903
- a: b; }
904
-
905
- .bar, .foo, .baz {
906
- c: d; }
907
-
908
- .baz, .bar, .foo {
909
- e: f; }
910
- CSS
911
- .foo {a: b; @extend .bar}
912
- .bar {c: d; @extend .baz}
913
- .baz {e: f; @extend .foo}
914
- SCSS
915
- end
916
-
917
- def test_nested_extend_loop
918
- assert_equal <<CSS, render(<<SCSS)
919
- .bar, .bar .foo {
920
- a: b; }
921
- .bar .foo {
922
- c: d; }
923
- CSS
924
- .bar {
925
- a: b;
926
- .foo {c: d; @extend .bar}
927
- }
928
- SCSS
929
- end
930
-
931
- def test_cross_loop
932
- # The first law of extend means the selector should stick around.
933
- assert_equal <<CSS, render(<<SCSS)
934
- .foo.bar, .foo, .bar {
935
- a: b; }
936
- CSS
937
- .foo.bar {a: b}
938
- .foo {@extend .bar}
939
- .bar {@extend .foo}
940
- SCSS
941
- end
942
-
943
- def test_multiple_extender_merges_with_superset_selector
944
- assert_equal <<CSS, render(<<SCSS)
945
- a.bar.baz, a.foo {
946
- a: b; }
947
- CSS
948
- .foo {@extend .bar; @extend .baz}
949
- a.bar.baz {a: b}
950
- SCSS
951
- end
952
-
953
- def test_control_flow_if
954
- assert_equal <<CSS, render(<<SCSS)
955
- .true, .also-true {
956
- color: green; }
957
-
958
- .false, .also-false {
959
- color: red; }
960
- CSS
961
- .true { color: green; }
962
- .false { color: red; }
963
- .also-true {
964
- @if true { @extend .true; }
965
- @else { @extend .false; }
966
- }
967
- .also-false {
968
- @if false { @extend .true; }
969
- @else { @extend .false; }
970
- }
971
- SCSS
972
- end
973
-
974
- def test_control_flow_for
975
- assert_equal <<CSS, render(<<SCSS)
976
- .base-0, .added {
977
- color: green; }
978
-
979
- .base-1, .added {
980
- display: block; }
981
-
982
- .base-2, .added {
983
- border: 1px solid blue; }
984
- CSS
985
- .base-0 { color: green; }
986
- .base-1 { display: block; }
987
- .base-2 { border: 1px solid blue; }
988
- .added {
989
- @for $i from 0 to 3 {
990
- @extend .base-\#{$i};
991
- }
992
- }
993
- SCSS
994
- end
995
-
996
- def test_control_flow_while
997
- assert_equal <<CSS, render(<<SCSS)
998
- .base-0, .added {
999
- color: green; }
1000
-
1001
- .base-1, .added {
1002
- display: block; }
1003
-
1004
- .base-2, .added {
1005
- border: 1px solid blue; }
1006
- CSS
1007
- .base-0 { color: green; }
1008
- .base-1 { display: block; }
1009
- .base-2 { border: 1px solid blue; }
1010
- .added {
1011
- $i : 0;
1012
- @while $i < 3 {
1013
- @extend .base-\#{$i};
1014
- $i : $i + 1;
1015
- }
1016
- }
1017
- SCSS
1018
- end
1019
-
1020
- def test_basic_placeholder_selector
1021
- assert_extends '%foo', '.bar {@extend %foo}', '.bar'
1022
- end
1023
-
1024
- def test_unused_placeholder_selector
1025
- assert_equal <<CSS, render(<<SCSS)
1026
- .baz {
1027
- color: blue; }
1028
- CSS
1029
- %foo {color: blue}
1030
- %bar {color: red}
1031
- .baz {@extend %foo}
1032
- SCSS
1033
- end
1034
-
1035
- def test_placeholder_descendant_selector
1036
- assert_extends '#context %foo a', '.bar {@extend %foo}', '#context .bar a'
1037
- end
1038
-
1039
- def test_semi_placeholder_selector
1040
- assert_equal <<CSS, render(<<SCSS)
1041
- .bar .baz {
1042
- color: blue; }
1043
- CSS
1044
- #context %foo, .bar .baz {color: blue}
1045
- SCSS
1046
- end
1047
-
1048
- def test_placeholder_selector_with_multiple_extenders
1049
- assert_equal <<CSS, render(<<SCSS)
1050
- .bar, .baz {
1051
- color: blue; }
1052
- CSS
1053
- %foo {color: blue}
1054
- .bar {@extend %foo}
1055
- .baz {@extend %foo}
1056
- SCSS
1057
- end
1058
-
1059
- def test_placeholder_selector_as_modifier
1060
- assert_extend_doesnt_match('div', '%foo', :failed_to_unify, 3) do
1061
- render(<<SCSS)
1062
- a%foo.baz {color: blue}
1063
- .bar {@extend %foo}
1064
- div {@extend %foo}
1065
- SCSS
1066
- end
1067
- end
1068
-
1069
- def test_placeholder_interpolation
1070
- assert_equal <<CSS, render(<<SCSS)
1071
- .bar {
1072
- color: blue; }
1073
- CSS
1074
- $foo: foo;
1075
-
1076
- %\#{$foo} {color: blue}
1077
- .bar {@extend %foo}
1078
- SCSS
1079
- end
1080
-
1081
- def test_placeholder_in_selector_pseudoclass
1082
- assert_equal <<CSS, render(<<SCSS)
1083
- :matches(.bar, .baz) {
1084
- color: blue; }
1085
- CSS
1086
- :matches(%foo) {color: blue}
1087
- .bar {@extend %foo}
1088
- .baz {@extend %foo}
1089
- SCSS
1090
- end
1091
-
1092
- def test_media_in_placeholder_selector
1093
- assert_equal <<CSS, render(<<SCSS)
1094
- .baz {
1095
- c: d; }
1096
- CSS
1097
- %foo {bar {@media screen {a: b}}}
1098
- .baz {c: d}
1099
- SCSS
1100
- end
1101
-
1102
- def test_extend_out_of_media
1103
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1104
- You may not @extend an outer selector from within @media.
1105
- You may only @extend selectors within the same directive.
1106
- From "@extend .foo" on line 3 of test_extend_out_of_media_inline.scss.
1107
- ERR
1108
- .foo {a: b}
1109
- @media screen {
1110
- .bar {@extend .foo}
1111
- }
1112
- SCSS
1113
- end
1114
-
1115
- def test_extend_out_of_unknown_directive
1116
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1117
- You may not @extend an outer selector from within @flooblehoof.
1118
- You may only @extend selectors within the same directive.
1119
- From "@extend .foo" on line 3 of test_extend_out_of_unknown_directive_inline.scss.
1120
- ERR
1121
- .foo {a: b}
1122
- @flooblehoof {
1123
- .bar {@extend .foo}
1124
- }
1125
- SCSS
1126
- end
1127
-
1128
- def test_extend_out_of_nested_directives
1129
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1130
- You may not @extend an outer selector from within @flooblehoof.
1131
- You may only @extend selectors within the same directive.
1132
- From "@extend .foo" on line 4 of test_extend_out_of_nested_directives_inline.scss.
1133
- ERR
1134
- @media screen {
1135
- .foo {a: b}
1136
- @flooblehoof {
1137
- .bar {@extend .foo}
1138
- }
1139
- }
1140
- SCSS
1141
- end
1142
-
1143
- def test_extend_within_media
1144
- assert_equal(<<CSS, render(<<SCSS))
1145
- @media screen {
1146
- .foo, .bar {
1147
- a: b; } }
1148
- CSS
1149
- @media screen {
1150
- .foo {a: b}
1151
- .bar {@extend .foo}
1152
- }
1153
- SCSS
1154
- end
1155
-
1156
- def test_extend_within_unknown_directive
1157
- assert_equal(<<CSS, render(<<SCSS))
1158
- @flooblehoof {
1159
- .foo, .bar {
1160
- a: b; } }
1161
- CSS
1162
- @flooblehoof {
1163
- .foo {a: b}
1164
- .bar {@extend .foo}
1165
- }
1166
- SCSS
1167
- end
1168
-
1169
- def test_extend_within_nested_directives
1170
- assert_equal(<<CSS, render(<<SCSS))
1171
- @media screen {
1172
- @flooblehoof {
1173
- .foo, .bar {
1174
- a: b; } } }
1175
- CSS
1176
- @media screen {
1177
- @flooblehoof {
1178
- .foo {a: b}
1179
- .bar {@extend .foo}
1180
- }
1181
- }
1182
- SCSS
1183
- end
1184
-
1185
- def test_extend_within_disparate_media
1186
- assert_equal(<<CSS, render(<<SCSS))
1187
- @media screen {
1188
- .foo, .bar {
1189
- a: b; } }
1190
- CSS
1191
- @media screen {.foo {a: b}}
1192
- @media screen {.bar {@extend .foo}}
1193
- SCSS
1194
- end
1195
-
1196
- def test_extend_within_disparate_unknown_directive
1197
- assert_equal(<<CSS, render(<<SCSS))
1198
- @flooblehoof {
1199
- .foo, .bar {
1200
- a: b; } }
1201
- @flooblehoof {}
1202
- CSS
1203
- @flooblehoof {.foo {a: b}}
1204
- @flooblehoof {.bar {@extend .foo}}
1205
- SCSS
1206
- end
1207
-
1208
- def test_extend_within_disparate_nested_directives
1209
- assert_equal(<<CSS, render(<<SCSS))
1210
- @media screen {
1211
- @flooblehoof {
1212
- .foo, .bar {
1213
- a: b; } } }
1214
- @media screen {
1215
- @flooblehoof {} }
1216
- CSS
1217
- @media screen {@flooblehoof {.foo {a: b}}}
1218
- @media screen {@flooblehoof {.bar {@extend .foo}}}
1219
- SCSS
1220
- end
1221
-
1222
- def test_extend_within_and_without_media
1223
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1224
- You may not @extend an outer selector from within @media.
1225
- You may only @extend selectors within the same directive.
1226
- From "@extend .foo" on line 4 of test_extend_within_and_without_media_inline.scss.
1227
- ERR
1228
- .foo {a: b}
1229
- @media screen {
1230
- .foo {c: d}
1231
- .bar {@extend .foo}
1232
- }
1233
- SCSS
1234
- end
1235
-
1236
- def test_extend_within_and_without_unknown_directive
1237
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1238
- You may not @extend an outer selector from within @flooblehoof.
1239
- You may only @extend selectors within the same directive.
1240
- From "@extend .foo" on line 4 of test_extend_within_and_without_unknown_directive_inline.scss.
1241
- ERR
1242
- .foo {a: b}
1243
- @flooblehoof {
1244
- .foo {c: d}
1245
- .bar {@extend .foo}
1246
- }
1247
- SCSS
1248
- end
1249
-
1250
- def test_extend_within_and_without_nested_directives
1251
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1252
- You may not @extend an outer selector from within @flooblehoof.
1253
- You may only @extend selectors within the same directive.
1254
- From "@extend .foo" on line 5 of test_extend_within_and_without_nested_directives_inline.scss.
1255
- ERR
1256
- @media screen {
1257
- .foo {a: b}
1258
- @flooblehoof {
1259
- .foo {c: d}
1260
- .bar {@extend .foo}
1261
- }
1262
- }
1263
- SCSS
1264
- end
1265
-
1266
- def test_extend_with_subject_transfers_subject_to_extender
1267
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1268
- foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
1269
- a: b; }
1270
- CSS
1271
- foo bar! baz {a: b}
1272
- .bip .bap {@extend bar}
1273
- SCSS
1274
-
1275
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1276
- foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
1277
- a: b; }
1278
- CSS
1279
- foo.x bar.y! baz.z {a: b}
1280
- .bip .bap {@extend .y}
1281
- SCSS
1282
- end
1283
-
1284
- def test_extend_with_subject_retains_subject_on_target
1285
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1286
- .foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
1287
- a: b; }
1288
- CSS
1289
- .foo! .bar {a: b}
1290
- .bip .bap {@extend .bar}
1291
- SCSS
1292
- end
1293
-
1294
- def test_extend_with_subject_transfers_subject_to_target
1295
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1296
- a.foo .bar, .bip a.bap! .bar {
1297
- a: b; }
1298
- CSS
1299
- a.foo .bar {a: b}
1300
- .bip .bap! {@extend .foo}
1301
- SCSS
1302
- end
1303
-
1304
- def test_extend_with_subject_retains_subject_on_extender
1305
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1306
- .foo .bar, .foo .bip! .bap, .bip! .foo .bap {
1307
- a: b; }
1308
- CSS
1309
- .foo .bar {a: b}
1310
- .bip! .bap {@extend .bar}
1311
- SCSS
1312
- end
1313
-
1314
- def test_extend_with_subject_fails_with_conflicting_subject
1315
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1316
- x! .bar {
1317
- a: b; }
1318
- CSS
1319
- x! .bar {a: b}
1320
- y! .bap {@extend .bar}
1321
- SCSS
1322
- end
1323
-
1324
- def test_extend_warns_when_extendee_doesnt_exist
1325
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1326
- ".foo" failed to @extend ".bar".
1327
- The selector ".bar" was not found.
1328
- Use "@extend .bar !optional" if the extend should be able to fail.
1329
- ERR
1330
- .foo {@extend .bar}
1331
- SCSS
1332
- end
1333
-
1334
- def test_extend_warns_when_extension_fails
1335
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1336
- "b.foo" failed to @extend ".bar".
1337
- No selectors matching ".bar" could be unified with "b.foo".
1338
- Use "@extend .bar !optional" if the extend should be able to fail.
1339
- ERR
1340
- a.bar {a: b}
1341
- b.foo {@extend .bar}
1342
- SCSS
1343
- end
1344
-
1345
- def test_extend_succeeds_when_one_extension_fails_but_others_dont
1346
- assert_equal(<<CSS, render(<<SCSS))
1347
- a.bar {
1348
- a: b; }
1349
-
1350
- .bar, b.foo {
1351
- c: d; }
1352
- CSS
1353
- a.bar {a: b}
1354
- .bar {c: d}
1355
- b.foo {@extend .bar}
1356
- SCSS
1357
- end
1358
-
1359
- def test_optional_extend_succeeds_when_extendee_doesnt_exist
1360
- assert_equal("", render(<<SCSS))
1361
- .foo {@extend .bar !optional}
1362
- SCSS
1363
- end
1364
-
1365
- def test_optional_extend_succeeds_when_extension_fails
1366
- assert_equal(<<CSS, render(<<SCSS))
1367
- a.bar {
1368
- a: b; }
1369
- CSS
1370
- a.bar {a: b}
1371
- b.foo {@extend .bar !optional}
1372
- SCSS
1373
- end
1374
-
1375
- # Regression Tests
1376
-
1377
- def test_extend_with_middle_pseudo
1378
- assert_equal(<<CSS, render(<<SCSS))
1379
- .btn:active.focus, :active.focus:before {
1380
- a: b; }
1381
- CSS
1382
- .btn:active.focus {a: b}
1383
- :before {@extend .btn}
1384
- SCSS
1385
- end
1386
-
1387
- def test_extend_parent_selector_suffix
1388
- assert_equal <<CSS, render(<<SCSS)
1389
- .a-b, .c {
1390
- x: y; }
1391
- CSS
1392
- .a {&-b {x: y}}
1393
- .c {@extend .a-b}
1394
- SCSS
1395
- end
1396
-
1397
- def test_pseudo_element_superselector
1398
- # Pseudo-elements shouldn't be removed in superselector calculations.
1399
- assert_equal <<CSS, render(<<SCSS)
1400
- a#bar, a#bar::fblthp {
1401
- a: b; }
1402
- CSS
1403
- %x#bar {a: b} // Add an id to make the results have high specificity
1404
- %y, %y::fblthp {@extend %x}
1405
- a {@extend %y}
1406
- SCSS
1407
-
1408
- # Pseudo-classes can be removed when the second law allows.
1409
- assert_equal <<CSS, render(<<SCSS)
1410
- a#bar {
1411
- a: b; }
1412
- CSS
1413
- %x#bar {a: b}
1414
- %y, %y:fblthp {@extend %x}
1415
- a {@extend %y}
1416
- SCSS
1417
-
1418
- # A few pseudo-elements can be written as pseudo-elements for historical
1419
- # reasons. See http://www.w3.org/TR/selectors4/#pseudo-elements.
1420
- %w[first-line first-letter before after].each do |pseudo|
1421
- assert_equal <<CSS, render(<<SCSS)
1422
- a#bar, a#bar:#{pseudo} {
1423
- a: b; }
1424
- CSS
1425
- %x#bar {a: b}
1426
- %y, %y:#{pseudo} {@extend %x}
1427
- a {@extend %y}
1428
- SCSS
1429
- end
1430
- end
1431
-
1432
- def test_multiple_source_redundancy_elimination
1433
- assert_equal <<CSS, render(<<SCSS)
1434
- .test-case, .test-case:active {
1435
- color: red; }
1436
-
1437
- .test-case:hover {
1438
- color: green; }
1439
- CSS
1440
- %default-color {color: red}
1441
- %alt-color {color: green}
1442
-
1443
- %default-style {
1444
- @extend %default-color;
1445
- &:hover {@extend %alt-color}
1446
- &:active {@extend %default-color}
1447
- }
1448
-
1449
- .test-case {@extend %default-style}
1450
- SCSS
1451
- end
1452
-
1453
- def test_nested_sibling_extend
1454
- assert_equal <<CSS, render(<<SCSS)
1455
- .parent .bar, .parent .foo {
1456
- width: 2000px; }
1457
- CSS
1458
- .foo {@extend .bar}
1459
-
1460
- .parent {
1461
- .bar {
1462
- width: 2000px;
1463
- }
1464
- .foo {
1465
- @extend .bar
1466
- }
1467
- }
1468
- SCSS
1469
- end
1470
-
1471
- def test_parent_and_sibling_extend
1472
- assert_equal <<CSS, render(<<SCSS)
1473
- .parent1 .parent2 .child1.child2, .parent2 .parent1 .child1.child2 {
1474
- c: d; }
1475
- CSS
1476
- %foo %bar%baz {c: d}
1477
-
1478
- .parent1 {
1479
- @extend %foo;
1480
- .child1 {@extend %bar}
1481
- }
1482
-
1483
- .parent2 {
1484
- @extend %foo;
1485
- .child2 {@extend %baz}
1486
- }
1487
- SCSS
1488
- end
1489
-
1490
- def test_nested_extend_specificity
1491
- assert_equal <<CSS, render(<<SCSS)
1492
- a :b, a :b:c {
1493
- a: b; }
1494
- CSS
1495
- %foo {a: b}
1496
-
1497
- a {
1498
- :b {@extend %foo}
1499
- :b:c {@extend %foo}
1500
- }
1501
- SCSS
1502
- end
1503
-
1504
- def test_nested_double_extend_optimization
1505
- assert_equal <<CSS, render(<<SCSS)
1506
- .parent1 .child {
1507
- a: b; }
1508
- CSS
1509
- %foo %bar {
1510
- a: b;
1511
- }
1512
-
1513
- .parent1 {
1514
- @extend %foo;
1515
-
1516
- .child {
1517
- @extend %bar;
1518
- }
1519
- }
1520
-
1521
- .parent2 {
1522
- @extend %foo;
1523
- }
1524
- SCSS
1525
- end
1526
-
1527
- def test_extend_in_double_nested_media_query
1528
- assert_equal <<CSS, render(<<SCSS)
1529
- @media all and (orientation: landscape) {
1530
- .bar {
1531
- color: blue; } }
1532
- CSS
1533
- @media all {
1534
- @media (orientation: landscape) {
1535
- %foo {color: blue}
1536
- .bar {@extend %foo}
1537
- }
1538
- }
1539
- SCSS
1540
- end
1541
-
1542
- def test_partially_failed_extend
1543
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1544
- .rc, test {
1545
- color: white; }
1546
-
1547
- .prices span.pill span.rc {
1548
- color: red; }
1549
- CSS
1550
- test { @extend .rc; }
1551
- .rc {color: white;}
1552
- .prices span.pill span.rc {color: red;}
1553
- SCSS
1554
- end
1555
-
1556
- def test_newline_near_combinator
1557
- assert_equal <<CSS, render(<<SCSS)
1558
- .a +
1559
- .b x, .a +
1560
- .b .c y, .c .a +
1561
- .b y {
1562
- a: b; }
1563
- CSS
1564
- .a +
1565
- .b x {a: b}
1566
- .c y {@extend x}
1567
- SCSS
1568
- end
1569
-
1570
- def test_duplicated_selector_with_newlines
1571
- assert_equal(<<CSS, render(<<SCSS))
1572
- .example-1-1,
1573
- .example-1-2,
1574
- .my-page-1 .my-module-1-1,
1575
- .example-1-3 {
1576
- a: b; }
1577
- CSS
1578
- .example-1-1,
1579
- .example-1-2,
1580
- .example-1-3 {
1581
- a: b;
1582
- }
1583
-
1584
- .my-page-1 .my-module-1-1 {@extend .example-1-2}
1585
- SCSS
1586
- end
1587
-
1588
- def test_nested_selector_with_child_selector_hack_extendee
1589
- assert_extends '> .foo', 'foo bar {@extend .foo}', '> .foo, > foo bar'
1590
- end
1591
-
1592
- def test_nested_selector_with_child_selector_hack_extender
1593
- assert_extends '.foo .bar', '> foo bar {@extend .bar}', '.foo .bar, > .foo foo bar, > foo .foo bar'
1594
- end
1595
-
1596
- def test_nested_selector_with_child_selector_hack_extender_and_extendee
1597
- assert_extends '> .foo', '> foo bar {@extend .foo}', '> .foo, > foo bar'
1598
- end
1599
-
1600
- def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee
1601
- assert_extends '~ .foo', '> foo bar {@extend .foo}', '~ .foo'
1602
- end
1603
-
1604
- def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline
1605
- assert_equal <<CSS, render(<<SCSS)
1606
- > .foo, > flip,
1607
- > foo bar {
1608
- a: b; }
1609
- CSS
1610
- > .foo {a: b}
1611
- flip,
1612
- > foo bar {@extend .foo}
1613
- SCSS
1614
- end
1615
-
1616
- def test_extended_parent_and_child_redundancy_elimination
1617
- assert_equal <<CSS, render(<<SCSS)
1618
- a b, d b, a c, d c {
1619
- a: b; }
1620
- CSS
1621
- a {
1622
- b {a: b}
1623
- c {@extend b}
1624
- }
1625
- d {@extend a}
1626
- SCSS
1627
- end
1628
-
1629
- def test_extend_redundancy_elimination_when_it_would_reduce_specificity
1630
- assert_extends 'a', 'a.foo {@extend a}', 'a, a.foo'
1631
- end
1632
-
1633
- def test_extend_redundancy_elimination_when_it_would_preserve_specificity
1634
- assert_extends '.bar a', 'a.foo {@extend a}', '.bar a'
1635
- end
1636
-
1637
- def test_extend_redundancy_elimination_never_eliminates_base_selector
1638
- assert_extends 'a.foo', '.foo {@extend a}', 'a.foo, .foo'
1639
- end
1640
-
1641
- def test_extend_cross_branch_redundancy_elimination
1642
- assert_equal <<CSS, render(<<SCSS)
1643
- .a .c .d, .b .c .a .d {
1644
- a: b; }
1645
- CSS
1646
- %x .c %y {a: b}
1647
- .a, .b {@extend %x}
1648
- .a .d {@extend %y}
1649
- SCSS
1650
-
1651
- assert_equal <<CSS, render(<<SCSS)
1652
- .e .a .c .d, .a .c .e .d, .e .b .c .a .d, .b .c .a .e .d {
1653
- a: b; }
1654
- CSS
1655
- .e %z {a: b}
1656
- %x .c %y {@extend %z}
1657
- .a, .b {@extend %x}
1658
- .a .d {@extend %y}
1659
- SCSS
1660
- end
1661
-
1662
- private
1663
-
1664
- def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
1665
- message = "\"#{extender}\" failed to @extend \"#{target}\"."
1666
- reason =
1667
- if reason == :not_found
1668
- "The selector \"#{target}\" was not found."
1669
- else
1670
- "No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
1671
- end
1672
-
1673
- assert_raise_message(Sass::SyntaxError, <<ERR) {yield}
1674
- #{message}
1675
- #{reason}
1676
- Use "@extend #{target} !optional" if the extend should be able to fail.
1677
- ERR
1678
- end
1679
-
1680
- def assert_unification(selector, extension, unified, nested = true)
1681
- # Do some trickery so the first law of extend doesn't get in our way.
1682
- assert_extends(
1683
- "%-a #{selector}",
1684
- extension + " -a {@extend %-a}",
1685
- unified.split(', ').map {|s| "-a #{s}"}.join(', '))
1686
- end
1687
-
1688
- def assert_specificity_equals(sel1, sel2)
1689
- assert_specificity_gte(sel1, sel2)
1690
- assert_specificity_gte(sel2, sel1)
1691
- end
1692
-
1693
- def assert_specificity_gte(sel1, sel2)
1694
- assert_equal <<CSS, render(<<SCSS)
1695
- #{sel1} .a {
1696
- a: b; }
1697
- CSS
1698
- #{sel1} %-a {a: b}
1699
- .a {@extend %-a}
1700
- #{sel2}.a {@extend %-a}
1701
- SCSS
1702
- end
1703
-
1704
- def render_unification(selector, extension)
1705
- render_extends(
1706
- "%-a #{selector}",
1707
- extension + " -a {@extend %-a}")
1708
- end
1709
-
1710
- def assert_extends(selector, extension, result)
1711
- assert_equal <<CSS, render_extends(selector, extension)
1712
- #{result} {
1713
- a: b; }
1714
- CSS
1715
- end
1716
-
1717
- def assert_extends_to_nothing(selector, extension)
1718
- assert_equal '', render_extends(selector, extension)
1719
- end
1720
-
1721
- def render_extends(selector, extension)
1722
- render(<<SCSS)
1723
- #{selector} {a: b}
1724
- #{extension}
1725
- SCSS
1726
- end
1727
-
1728
- def render(sass, options = {})
1729
- options = {:syntax => :scss}.merge(options)
1730
- munge_filename options
1731
- Sass::Engine.new(sass, options).render
1732
- end
1733
- end