sass 3.4.25 → 3.7.4

Sign up to get free protection for your applications and to get access to all the features.
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]