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
@@ -32,7 +32,7 @@ module Sass
32
32
  # @return [String] The escaped character
33
33
  # @private
34
34
  def self.escape_char(c)
35
- return "\\%06x" % (Sass::Util.ord(c)) unless c =~ %r{[ -/:-~]}
35
+ return "\\%06x" % c.ord unless c =~ %r{[ -/:-~]}
36
36
  "\\#{c}"
37
37
  end
38
38
 
@@ -50,15 +50,9 @@ module Sass
50
50
  H = /[0-9a-fA-F]/
51
51
  NL = /\n|\r\n|\r|\f/
52
52
  UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
53
- s = if Sass::Util.ruby1_8?
54
- '\200-\377'
55
- elsif Sass::Util.macruby?
56
- '\u0080-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF'
57
- else
58
- '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
59
- end
53
+ s = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
60
54
  NONASCII = /[#{s}]/
61
- ESCAPE = /#{UNICODE}|\\[ -~#{s}]/
55
+ ESCAPE = /#{UNICODE}|\\[^0-9a-fA-F\r\n\f]/
62
56
  NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
63
57
  NMCHAR = /[a-zA-Z0-9_-]|#{NONASCII}|#{ESCAPE}/
64
58
  STRING1 = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/
@@ -127,13 +121,13 @@ module Sass
127
121
  OPTIONAL = /!#{W}optional/i
128
122
  IDENT_START = /-|#{NMSTART}/
129
123
 
130
- IDENT_HYPHEN_INTERP = /-(#\{)/
124
+ IDENT_HYPHEN_INTERP = /-+(?=#\{)/
131
125
  STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|#{ESCAPE})*)\"/
132
126
  STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|#{ESCAPE})*)\'/
133
127
  STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
134
128
 
135
129
  STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
136
- STATIC_VALUE = %r(#{STATIC_COMPONENT}(\s*[\s,/]\s*#{STATIC_COMPONENT})*([;}]))i
130
+ STATIC_VALUE = %r(#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*(?=[;}]))i
137
131
  STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){1,50}([{])/i
138
132
  end
139
133
  end
@@ -51,10 +51,7 @@ module Sass
51
51
  # @see Parser#initialize
52
52
  # @param allow_parent_ref [Boolean] Whether to allow the
53
53
  # parent-reference selector, `&`, when parsing the document.
54
- # @comment
55
- # rubocop:disable ParameterLists
56
54
  def initialize(str, filename, importer, line = 1, offset = 1, allow_parent_ref = true)
57
- # rubocop:enable ParameterLists
58
55
  super(str, filename, importer, line, offset)
59
56
  @allow_parent_ref = allow_parent_ref
60
57
  end
@@ -74,7 +71,7 @@ module Sass
74
71
  def var_expr; nil; end
75
72
  def interp_string; (s = tok(STRING)) && [s]; end
76
73
  def interp_uri; (s = tok(URI)) && [s]; end
77
- def interp_ident(ident = IDENT); (s = tok(ident)) && [s]; end
74
+ def interp_ident; (s = ident) && [s]; end
78
75
  def use_css_import?; true; end
79
76
 
80
77
  def special_directive(name, start_pos)
@@ -188,25 +185,25 @@ MESSAGE
188
185
 
189
186
  def parent_selector
190
187
  return unless @allow_parent_ref && tok(/&/)
191
- Selector::Parent.new(tok(NAME))
188
+ Selector::Parent.new(name)
192
189
  end
193
190
 
194
191
  def class_selector
195
192
  return unless tok(/\./)
196
193
  @expected = "class name"
197
- Selector::Class.new(tok!(IDENT))
194
+ Selector::Class.new(ident!)
198
195
  end
199
196
 
200
197
  def id_selector
201
198
  return unless tok(/#(?!\{)/)
202
199
  @expected = "id name"
203
- Selector::Id.new(tok!(NAME))
200
+ Selector::Id.new(name!)
204
201
  end
205
202
 
206
203
  def placeholder_selector
207
204
  return unless tok(/%/)
208
205
  @expected = "placeholder name"
209
- Selector::Placeholder.new(tok!(IDENT))
206
+ Selector::Placeholder.new(ident!)
210
207
  end
211
208
 
212
209
  def element_name
@@ -221,13 +218,13 @@ MESSAGE
221
218
  end
222
219
 
223
220
  def qualified_name(allow_star_name = false)
224
- name = tok(IDENT) || tok(/\*/) || (tok?(/\|/) && "")
221
+ name = ident || tok(/\*/) || (tok?(/\|/) && "")
225
222
  return unless name
226
223
  return nil, name unless tok(/\|/)
227
224
 
228
- return name, tok!(IDENT) unless allow_star_name
225
+ return name, ident! unless allow_star_name
229
226
  @expected = "identifier or *"
230
- return name, tok(IDENT) || tok!(/\*/)
227
+ return name, ident || tok!(/\*/)
231
228
  end
232
229
 
233
230
  def attrib
@@ -245,21 +242,21 @@ MESSAGE
245
242
  if op
246
243
  @expected = "identifier or string"
247
244
  ss
248
- val = tok(IDENT) || tok!(STRING)
245
+ val = ident || tok!(STRING)
249
246
  ss
250
247
  end
251
- flags = tok(IDENT) || tok(STRING)
248
+ flags = ident || tok(STRING)
252
249
  tok!(/\]/)
253
250
 
254
251
  Selector::Attribute.new(name, ns, op, val, flags)
255
252
  end
256
253
 
257
254
  def attrib_name!
258
- if (name_or_ns = tok(IDENT))
255
+ if (name_or_ns = ident)
259
256
  # E, E|E
260
257
  if tok(/\|(?!=)/)
261
258
  ns = name_or_ns
262
- name = tok(IDENT)
259
+ name = ident
263
260
  else
264
261
  name = name_or_ns
265
262
  end
@@ -267,7 +264,7 @@ MESSAGE
267
264
  # *|E or |E
268
265
  ns = tok(/\*/) || ""
269
266
  tok!(/\|/)
270
- name = tok!(IDENT)
267
+ name = ident!
271
268
  end
272
269
  return ns, name
273
270
  end
@@ -276,11 +273,13 @@ MESSAGE
276
273
 
277
274
  PREFIXED_SELECTOR_PSEUDO_CLASSES = %w(nth-child nth-last-child).to_set
278
275
 
276
+ SELECTOR_PSEUDO_ELEMENTS = %w(slotted).to_set
277
+
279
278
  def pseudo
280
279
  s = tok(/::?/)
281
280
  return unless s
282
281
  @expected = "pseudoclass or pseudoelement"
283
- name = tok!(IDENT)
282
+ name = ident!
284
283
  if tok(/\(/)
285
284
  ss
286
285
  deprefixed = deprefix(name)
@@ -288,8 +287,10 @@ MESSAGE
288
287
  sel = selector_comma_sequence
289
288
  elsif s == ':' && PREFIXED_SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
290
289
  arg, sel = prefixed_selector_pseudo
290
+ elsif s == '::' && SELECTOR_PSEUDO_ELEMENTS.include?(deprefixed)
291
+ sel = selector_comma_sequence
291
292
  else
292
- arg = expr!(:pseudo_args)
293
+ arg = expr!(:declaration_value).join
293
294
  end
294
295
 
295
296
  tok!(/\)/)
@@ -297,29 +298,6 @@ MESSAGE
297
298
  Selector::Pseudo.new(s == ':' ? :class : :element, name, arg, sel)
298
299
  end
299
300
 
300
- def pseudo_args
301
- arg = expr!(:pseudo_expr)
302
- while tok(/,/)
303
- arg << ',' << str {ss}
304
- arg.concat expr!(:pseudo_expr)
305
- end
306
- arg
307
- end
308
-
309
- def pseudo_expr
310
- res = pseudo_expr_token
311
- return unless res
312
- res << str {ss}
313
- while (e = pseudo_expr_token)
314
- res << e << str {ss}
315
- end
316
- res
317
- end
318
-
319
- def pseudo_expr_token
320
- tok(PLUS) || tok(/[-*]/) || tok(NUMBER) || tok(STRING) || tok(IDENT)
321
- end
322
-
323
301
  def prefixed_selector_pseudo
324
302
  prefix = str do
325
303
  expr = str {expr!(:a_n_plus_b)}
@@ -364,7 +342,7 @@ MESSAGE
364
342
  end
365
343
 
366
344
  def keyframes_selector_component
367
- tok(IDENT) || tok(PERCENTAGE)
345
+ ident || tok(PERCENTAGE)
368
346
  end
369
347
 
370
348
  @sass_script_parser = Class.new(Sass::Script::CssParser)
@@ -87,6 +87,10 @@ module Sass
87
87
  @name = name
88
88
  end
89
89
 
90
+ def unique?
91
+ true
92
+ end
93
+
90
94
  # @see Selector#to_s
91
95
  def to_s(opts = {})
92
96
  "#" + @name
@@ -59,12 +59,11 @@ module Sass
59
59
  end
60
60
  alias_method :==, :eql?
61
61
 
62
- # Whether or not this selector sequence contains a placeholder selector.
63
- # Checks recursively.
64
- def has_placeholder?
65
- @has_placeholder ||= members.any? do |m|
66
- next m.has_placeholder? if m.is_a?(AbstractSequence)
67
- next m.selector && m.selector.has_placeholder? if m.is_a?(Pseudo)
62
+ # Whether or not this selector should be hidden due to containing a
63
+ # placeholder.
64
+ def invisible?
65
+ @invisible ||= members.any? do |m|
66
+ next m.invisible? if m.is_a?(AbstractSequence) || m.is_a?(Pseudo)
68
67
  m.is_a?(Placeholder)
69
68
  end
70
69
  end
@@ -73,6 +72,8 @@ module Sass
73
72
  #
74
73
  # @param opts [Hash] rendering options.
75
74
  # @option opts [Symbol] :style The css rendering style.
75
+ # @option placeholders [Boolean] :placeholders
76
+ # Whether to include placeholder selectors. Defaults to `true`.
76
77
  # @return [String]
77
78
  def to_s(opts = {})
78
79
  Sass::Util.abstract(self)
@@ -119,7 +119,8 @@ module Sass
119
119
  if !allow_compound_target && sel.length > 1
120
120
  @@compound_extend_deprecation.warn(sseq.filename, sseq.line, <<WARNING)
121
121
  Extending a compound selector, #{sseq}, is deprecated and will not be supported in a future release.
122
- See https://github.com/sass/sass/issues/1599 for details.
122
+ Consider "@extend #{sseq.members.join(', ')}" instead.
123
+ See http://bit.ly/ExtendCompound for details.
123
124
  WARNING
124
125
  end
125
126
 
@@ -129,7 +130,7 @@ WARNING
129
130
  end
130
131
 
131
132
  extends[sel] = Sass::Tree::Visitors::Cssize::Extend.new(
132
- member, sel, extend_node, parent_directives, :not_found)
133
+ member, sel, extend_node, parent_directives, false)
133
134
  end
134
135
  end
135
136
  end
@@ -158,8 +159,8 @@ WARNING
158
159
  Sass::Script::Value::List.new(seq.members.map do |component|
159
160
  next if component == "\n"
160
161
  Sass::Script::Value::String.new(component.to_s)
161
- end.compact, :space)
162
- end, :comma)
162
+ end.compact, separator: :space)
163
+ end, separator: :comma)
163
164
  end
164
165
 
165
166
  # Returns a string representation of the sequence.
@@ -172,7 +173,10 @@ WARNING
172
173
 
173
174
  # @see AbstractSequence#to_s
174
175
  def to_s(opts = {})
175
- @members.map {|m| m.to_s(opts)}.
176
+ @members.map do |m|
177
+ next if opts[:placeholder] == false && m.invisible?
178
+ m.to_s(opts)
179
+ end.compact.
176
180
  join(opts[:style] == :compressed ? "," : ", ").
177
181
  gsub(", \n", ",\n")
178
182
  end
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  module Sass
2
3
  module Selector
3
4
  # A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`)
@@ -48,6 +49,18 @@ module Sass
48
49
  @selector = selector
49
50
  end
50
51
 
52
+ def unique?
53
+ type == :class && normalized_name == 'root'
54
+ end
55
+
56
+ # Whether or not this selector should be hidden due to containing a
57
+ # placeholder.
58
+ def invisible?
59
+ # :not() is a special case—if you eliminate all the placeholders from
60
+ # it, it should match anything.
61
+ name != 'not' && @selector && @selector.members.all? {|s| s.invisible?}
62
+ end
63
+
51
64
  # Returns a copy of this with \{#selector} set to \{#new\_selector}.
52
65
  #
53
66
  # @param new_selector [CommaSequence]
@@ -77,7 +90,7 @@ module Sass
77
90
  # more complex cases that likely aren't worth the pain.
78
91
  next [] unless sel.name == name && sel.arg == arg
79
92
  sel.selector.members
80
- when 'has', 'host', 'host-context'
93
+ when 'has', 'host', 'host-context', 'slotted'
81
94
  # We can't expand nested selectors here, because each layer adds an
82
95
  # additional layer of semantics. For example, `:has(:has(img))`
83
96
  # doesn't match `<div><img></div>` but `:has(img)` does.
@@ -114,10 +127,14 @@ module Sass
114
127
 
115
128
  # @see Selector#to_s
116
129
  def to_s(opts = {})
130
+ # :not() is a special case, because :not(<nothing>) should match
131
+ # everything.
132
+ return '' if name == 'not' && @selector && @selector.members.all? {|m| m.invisible?}
133
+
117
134
  res = (syntactic_type == :class ? ":" : "::") + @name
118
135
  if @arg || @selector
119
136
  res << "("
120
- res << @arg.strip if @arg
137
+ res << Sass::Util.strip_except_escapes(@arg) if @arg
121
138
  res << " " if @arg && @selector
122
139
  res << @selector.to_s(opts) if @selector
123
140
  res << ")"
@@ -161,7 +178,7 @@ module Sass
161
178
  their_seq = Sequence.new(parents + [their_sseq])
162
179
  our_seq.superselector?(their_seq)
163
180
  end
164
- when 'has', 'host', 'host-context'
181
+ when 'has', 'host', 'host-context', 'slotted'
165
182
  # Like :matches, :has (et al) can be a superselector of another
166
183
  # selector if its constituent selectors are a superset of those of
167
184
  # another :has in the other selector. However, the :matches other case
@@ -66,10 +66,14 @@ module Sass
66
66
  next [sseq_or_op] unless sseq_or_op.is_a?(SimpleSequence)
67
67
  sseq_or_op.resolve_parent_refs(super_cseq).members
68
68
  end).map do |path|
69
- Sequence.new(path.map do |seq_or_op|
69
+ path_members = path.map do |seq_or_op|
70
70
  next seq_or_op unless seq_or_op.is_a?(Sequence)
71
71
  seq_or_op.members
72
- end.flatten)
72
+ end
73
+ if path_members.length == 2 && path_members[1][0] == "\n"
74
+ path_members[0].unshift path_members[1].shift
75
+ end
76
+ Sequence.new(path_members.flatten)
73
77
  end)
74
78
  end
75
79
 
@@ -115,7 +119,7 @@ module Sass
115
119
  # specificity greater than or equal to that of the original selector.
116
120
  # In order to ensure that, we record the original selector's
117
121
  # (`extended.first`) original specificity.
118
- extended.first.add_sources!([self]) if original && !has_placeholder?
122
+ extended.first.add_sources!([self]) if original && !invisible?
119
123
 
120
124
  extended.map {|seq| seq.members}
121
125
  end
@@ -283,6 +287,9 @@ module Sass
283
287
  next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
284
288
  next s2 if parent_superselector?(s1, s2)
285
289
  next s1 if parent_superselector?(s2, s1)
290
+ next unless must_unify?(s1, s2)
291
+ next unless (unified = Sequence.new(s1).unify(Sequence.new(s2)))
292
+ unified.members.first.members if unified.members.length == 1
286
293
  end
287
294
 
288
295
  diff = [[init]]
@@ -337,8 +344,6 @@ module Sass
337
344
  # be nil. Otherwise, this will contained the merged selector. Array
338
345
  # elements are [Sass::Util#paths]-style options; conceptually, an "or"
339
346
  # of multiple selectors.
340
- # @comment
341
- # rubocop:disable MethodLength
342
347
  def merge_final_ops(seq1, seq2, res = [])
343
348
  ops1, ops2 = [], []
344
349
  ops1 << seq1.pop while seq1.last.is_a?(String)
@@ -420,8 +425,6 @@ module Sass
420
425
  return merge_final_ops(seq1, seq2, res)
421
426
  end
422
427
  end
423
- # @comment
424
- # rubocop:enable MethodLength
425
428
 
426
429
  # Takes initial subsequences of `seq1` and `seq2` and returns all
427
430
  # orderings of those subsequences. The initial subsequences are determined
@@ -494,7 +497,7 @@ module Sass
494
497
  return if seq1.size > seq2.size
495
498
  return seq1.first.superselector?(seq2.last, seq2[0...-1]) if seq1.size == 1
496
499
 
497
- _, si = Sass::Util.enum_with_index(seq2).find do |e, i|
500
+ _, si = seq2.each_with_index.find do |e, i|
498
501
  return if i == seq2.size - 1
499
502
  next if e.is_a?(String)
500
503
  seq1.first.superselector?(e, seq2[0...i])
@@ -537,6 +540,30 @@ module Sass
537
540
  _superselector?(seq1 + [base], seq2 + [base])
538
541
  end
539
542
 
543
+ # Returns whether two selectors must be unified to produce a valid
544
+ # combined selector. This is true when both selectors contain the same
545
+ # unique simple selector such as an id.
546
+ #
547
+ # @param seq1 [Array<SimpleSequence or String>]
548
+ # @param seq2 [Array<SimpleSequence or String>]
549
+ # @return [Boolean]
550
+ def must_unify?(seq1, seq2)
551
+ unique_selectors = seq1.map do |sseq|
552
+ next [] if sseq.is_a?(String)
553
+ sseq.members.select {|sel| sel.unique?}
554
+ end.flatten.to_set
555
+
556
+ return false if unique_selectors.empty?
557
+
558
+ seq2.any? do |sseq|
559
+ next false if sseq.is_a?(String)
560
+ sseq.members.any? do |sel|
561
+ next unless sel.unique?
562
+ unique_selectors.include?(sel)
563
+ end
564
+ end
565
+ end
566
+
540
567
  # Removes redundant selectors from between multiple lists of
541
568
  # selectors. This takes a list of lists of selector sequences;
542
569
  # each individual list is assumed to have no redundancy within
@@ -597,8 +624,6 @@ module Sass
597
624
  other.members.reject {|m| m == "\n"}.eql?(members.reject {|m| m == "\n"})
598
625
  end
599
626
 
600
- private
601
-
602
627
  def path_has_two_subjects?(path)
603
628
  subject = false
604
629
  path.each do |sseq_or_op|
@@ -14,6 +14,14 @@ module Sass
14
14
  # @return [String, nil]
15
15
  attr_accessor :filename
16
16
 
17
+ # Whether only one instance of this simple selector is allowed in a given
18
+ # complex selector.
19
+ #
20
+ # @return [Boolean]
21
+ def unique?
22
+ false
23
+ end
24
+
17
25
  # @see #to_s
18
26
  #
19
27
  # @return [String]
@@ -74,9 +82,8 @@ module Sass
74
82
  def unify(sels)
75
83
  return sels.first.unify([self]) if sels.length == 1 && sels.first.is_a?(Universal)
76
84
  return sels if sels.any? {|sel2| eql?(sel2)}
77
- sels_with_ix = Sass::Util.enum_with_index(sels)
78
85
  if !is_a?(Pseudo) || (sels.last.is_a?(Pseudo) && sels.last.type == :element)
79
- _, i = sels_with_ix.find {|sel, _| sel.is_a?(Pseudo)}
86
+ _, i = sels.each_with_index.find {|sel, _| sel.is_a?(Pseudo)}
80
87
  end
81
88
  return sels + [self] unless i
82
89
  sels[0...i] + [self] + sels[i..-1]