sass 3.3.14 → 3.4.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +5 -5
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +0 -5
  10. data/lib/sass/css.rb +1 -3
  11. data/lib/sass/engine.rb +28 -39
  12. data/lib/sass/environment.rb +13 -17
  13. data/lib/sass/error.rb +6 -9
  14. data/lib/sass/exec.rb +5 -771
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +419 -0
  18. data/lib/sass/features.rb +6 -0
  19. data/lib/sass/importers.rb +0 -1
  20. data/lib/sass/importers/base.rb +5 -1
  21. data/lib/sass/importers/filesystem.rb +4 -21
  22. data/lib/sass/media.rb +1 -4
  23. data/lib/sass/plugin/compiler.rb +32 -136
  24. data/lib/sass/script/css_lexer.rb +1 -1
  25. data/lib/sass/script/functions.rb +363 -39
  26. data/lib/sass/script/lexer.rb +68 -50
  27. data/lib/sass/script/parser.rb +29 -14
  28. data/lib/sass/script/tree.rb +1 -0
  29. data/lib/sass/script/tree/funcall.rb +1 -1
  30. data/lib/sass/script/tree/interpolation.rb +19 -1
  31. data/lib/sass/script/tree/selector.rb +26 -0
  32. data/lib/sass/script/value.rb +0 -1
  33. data/lib/sass/script/value/bool.rb +0 -5
  34. data/lib/sass/script/value/color.rb +32 -12
  35. data/lib/sass/script/value/helpers.rb +107 -0
  36. data/lib/sass/script/value/list.rb +0 -15
  37. data/lib/sass/script/value/null.rb +0 -5
  38. data/lib/sass/script/value/number.rb +60 -14
  39. data/lib/sass/script/value/string.rb +53 -9
  40. data/lib/sass/scss/css_parser.rb +8 -2
  41. data/lib/sass/scss/parser.rb +175 -319
  42. data/lib/sass/scss/rx.rb +14 -5
  43. data/lib/sass/scss/static_parser.rb +298 -1
  44. data/lib/sass/selector.rb +56 -193
  45. data/lib/sass/selector/abstract_sequence.rb +28 -13
  46. data/lib/sass/selector/comma_sequence.rb +91 -12
  47. data/lib/sass/selector/pseudo.rb +256 -0
  48. data/lib/sass/selector/sequence.rb +99 -31
  49. data/lib/sass/selector/simple.rb +14 -25
  50. data/lib/sass/selector/simple_sequence.rb +101 -37
  51. data/lib/sass/shared.rb +1 -1
  52. data/lib/sass/source/map.rb +23 -9
  53. data/lib/sass/stack.rb +0 -6
  54. data/lib/sass/supports.rb +1 -1
  55. data/lib/sass/tree/at_root_node.rb +1 -0
  56. data/lib/sass/tree/directive_node.rb +7 -1
  57. data/lib/sass/tree/error_node.rb +18 -0
  58. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  59. data/lib/sass/tree/prop_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -6
  61. data/lib/sass/tree/visitors/check_nesting.rb +3 -4
  62. data/lib/sass/tree/visitors/convert.rb +8 -17
  63. data/lib/sass/tree/visitors/cssize.rb +12 -24
  64. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  65. data/lib/sass/tree/visitors/perform.rb +43 -28
  66. data/lib/sass/tree/visitors/set_options.rb +5 -0
  67. data/lib/sass/tree/visitors/to_css.rb +14 -13
  68. data/lib/sass/util.rb +94 -90
  69. data/test/sass/cache_test.rb +1 -1
  70. data/test/sass/callbacks_test.rb +1 -1
  71. data/test/sass/compiler_test.rb +5 -14
  72. data/test/sass/conversion_test.rb +47 -1
  73. data/test/sass/css2sass_test.rb +3 -3
  74. data/test/sass/encoding_test.rb +219 -0
  75. data/test/sass/engine_test.rb +128 -191
  76. data/test/sass/exec_test.rb +2 -2
  77. data/test/sass/extend_test.rb +234 -17
  78. data/test/sass/functions_test.rb +268 -213
  79. data/test/sass/importer_test.rb +31 -21
  80. data/test/sass/logger_test.rb +1 -1
  81. data/test/sass/more_results/more_import.css +1 -1
  82. data/test/sass/plugin_test.rb +12 -11
  83. data/test/sass/results/compact.css +1 -1
  84. data/test/sass/results/complex.css +4 -4
  85. data/test/sass/results/expanded.css +1 -1
  86. data/test/sass/results/import.css +1 -1
  87. data/test/sass/results/import_charset_ibm866.css +2 -2
  88. data/test/sass/results/mixins.css +17 -17
  89. data/test/sass/results/nested.css +1 -1
  90. data/test/sass/results/parent_ref.css +2 -2
  91. data/test/sass/results/script.css +3 -3
  92. data/test/sass/results/scss_import.css +1 -1
  93. data/test/sass/script_conversion_test.rb +7 -4
  94. data/test/sass/script_test.rb +202 -79
  95. data/test/sass/scss/css_test.rb +95 -25
  96. data/test/sass/scss/rx_test.rb +4 -4
  97. data/test/sass/scss/scss_test.rb +363 -19
  98. data/test/sass/source_map_test.rb +48 -41
  99. data/test/sass/superselector_test.rb +191 -0
  100. data/test/sass/templates/scss_import.scss +2 -1
  101. data/test/sass/test_helper.rb +1 -1
  102. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  103. data/test/sass/util/normalized_map_test.rb +1 -1
  104. data/test/sass/util/subset_map_test.rb +2 -2
  105. data/test/sass/util_test.rb +1 -1
  106. data/test/sass/value_helpers_test.rb +3 -3
  107. data/test/test_helper.rb +2 -2
  108. metadata +30 -7
  109. data/lib/sass/importers/deprecated_path.rb +0 -51
  110. data/lib/sass/script/value/deprecated_false.rb +0 -55
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  module Sass
2
3
  module SCSS
3
4
  # A module containing regular expressions used
@@ -63,9 +64,9 @@ module Sass
63
64
  STRING1 = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/
64
65
  STRING2 = /\'((?:[^\n\r\f\\']|\\#{NL}|#{ESCAPE})*)\'/
65
66
 
66
- IDENT = /-?#{NMSTART}#{NMCHAR}*/
67
+ IDENT = /-*#{NMSTART}#{NMCHAR}*/
67
68
  NAME = /#{NMCHAR}+/
68
- NUM = /[0-9]+|[0-9]*\.[0-9]+/
69
+ NUM = //
69
70
  STRING = /#{STRING1}|#{STRING2}/
70
71
  URLCHAR = /[#%&*-~]|#{NONASCII}|#{ESCAPE}/
71
72
  URL = /(#{URLCHAR}*)/
@@ -95,7 +96,9 @@ module Sass
95
96
 
96
97
  IMPORTANT = /!#{W}important/i
97
98
 
98
- NUMBER = /#{NUM}(?:#{IDENT}|%)?/
99
+ UNITLESS_NUMBER = /(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?\d+)?/
100
+ NUMBER = /#{UNITLESS_NUMBER}(?:#{IDENT}|%)?/
101
+ PERCENTAGE = /#{UNITLESS_NUMBER}%/
99
102
 
100
103
  URI = /url\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
101
104
  FUNCTION = /#{IDENT}\(/
@@ -118,10 +121,16 @@ module Sass
118
121
  INTERP_START = /#\{/
119
122
  ANY = /:(-[-\w]+-)?any\(/i
120
123
  OPTIONAL = /!#{W}optional/i
124
+ IDENT_START = /-|#{NMSTART}/
125
+
126
+ # A unit is like an IDENT, but disallows a hyphen followed by a digit.
127
+ # This allows "1px-2px" to be interpreted as subtraction rather than "1"
128
+ # with the unit "px-2px". It also allows "%".
129
+ UNIT = /-?#{NMSTART}(?:[a-zA-Z0-9_]|#{NONASCII}|#{ESCAPE}|-(?!\d))*|%/
121
130
 
122
131
  IDENT_HYPHEN_INTERP = /-(#\{)/
123
- STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
124
- STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
132
+ STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|#{ESCAPE})*)\"/
133
+ STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|#{ESCAPE})*)\'/
125
134
  STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
126
135
 
127
136
  STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
@@ -41,6 +41,24 @@ module Sass
41
41
  return type, directives
42
42
  end
43
43
 
44
+ def parse_keyframes_selector
45
+ init_scanner!
46
+ sel = expr!(:keyframes_selector)
47
+ expected("keyframes selector") unless @scanner.eos?
48
+ sel
49
+ end
50
+
51
+ # @see Parser#initialize
52
+ # @param allow_parent_ref [Boolean] Whether to allow the
53
+ # parent-reference selector, `&`, when parsing the document.
54
+ # @comment
55
+ # rubocop:disable ParameterLists
56
+ def initialize(str, filename, importer, line = 1, offset = 1, allow_parent_ref = true)
57
+ # rubocop:enable ParameterLists
58
+ super(str, filename, importer, line, offset)
59
+ @allow_parent_ref = allow_parent_ref
60
+ end
61
+
44
62
  private
45
63
 
46
64
  def moz_document_function
@@ -52,7 +70,7 @@ module Sass
52
70
 
53
71
  def variable; nil; end
54
72
  def script_value; nil; end
55
- def interpolation; nil; end
73
+ def interpolation(warn_for_color = false); nil; end
56
74
  def var_expr; nil; end
57
75
  def interp_string; (s = tok(STRING)) && [s]; end
58
76
  def interp_uri; (s = tok(URI)) && [s]; end
@@ -64,6 +82,285 @@ module Sass
64
82
  super
65
83
  end
66
84
 
85
+ def selector_comma_sequence
86
+ sel = selector
87
+ return unless sel
88
+ selectors = [sel]
89
+ ws = ''
90
+ while tok(/,/)
91
+ ws << str {ss}
92
+ if (sel = selector)
93
+ selectors << sel
94
+ if ws.include?("\n")
95
+ selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members)
96
+ end
97
+ ws = ''
98
+ end
99
+ end
100
+ Selector::CommaSequence.new(selectors)
101
+ end
102
+
103
+ def selector_string
104
+ sel = selector
105
+ return unless sel
106
+ sel.to_s
107
+ end
108
+
109
+ def selector
110
+ start_pos = source_position
111
+ # The combinator here allows the "> E" hack
112
+ val = combinator || simple_selector_sequence
113
+ return unless val
114
+ nl = str {ss}.include?("\n")
115
+ res = []
116
+ res << val
117
+ res << "\n" if nl
118
+
119
+ while (val = combinator || simple_selector_sequence)
120
+ res << val
121
+ res << "\n" if str {ss}.include?("\n")
122
+ end
123
+ seq = Selector::Sequence.new(res.compact)
124
+
125
+ if seq.members.any? {|sseq| sseq.is_a?(Selector::SimpleSequence) && sseq.subject?}
126
+ location = " of #{@filename}" if @filename
127
+ Sass::Util.sass_warn <<MESSAGE
128
+ DEPRECATION WARNING on line #{start_pos.line}, column #{start_pos.offset}#{location}:
129
+ The subject selector operator "!" is deprecated and will be removed in a future release.
130
+ This operator has been replaced by ":has()" in the CSS spec.
131
+ For example: #{seq.subjectless}
132
+ MESSAGE
133
+ end
134
+
135
+ seq
136
+ end
137
+
138
+ def combinator
139
+ tok(PLUS) || tok(GREATER) || tok(TILDE) || reference_combinator
140
+ end
141
+
142
+ def reference_combinator
143
+ return unless tok(/\//)
144
+ res = '/'
145
+ ns, name = expr!(:qualified_name)
146
+ res << ns << '|' if ns
147
+ res << name << tok!(/\//)
148
+ res
149
+ end
150
+
151
+ def simple_selector_sequence
152
+ start_pos = source_position
153
+ e = element_name || id_selector || class_selector || placeholder_selector || attrib ||
154
+ pseudo || parent_selector
155
+ return unless e
156
+ res = [e]
157
+
158
+ # The tok(/\*/) allows the "E*" hack
159
+ while (v = id_selector || class_selector || placeholder_selector ||
160
+ attrib || pseudo || (tok(/\*/) && Selector::Universal.new(nil)))
161
+ res << v
162
+ end
163
+
164
+ pos = @scanner.pos
165
+ line = @line
166
+ if (sel = str? {simple_selector_sequence})
167
+ @scanner.pos = pos
168
+ @line = line
169
+ begin
170
+ # If we see "*E", don't force a throw because this could be the
171
+ # "*prop: val" hack.
172
+ expected('"{"') if res.length == 1 && res[0].is_a?(Selector::Universal)
173
+ throw_error {expected('"{"')}
174
+ rescue Sass::SyntaxError => e
175
+ e.message << "\n\n\"#{sel}\" may only be used at the beginning of a compound selector."
176
+ raise e
177
+ end
178
+ end
179
+
180
+ Selector::SimpleSequence.new(res, tok(/!/), range(start_pos))
181
+ end
182
+
183
+ def parent_selector
184
+ return unless @allow_parent_ref && tok(/&/)
185
+ Selector::Parent.new(tok(NAME))
186
+ end
187
+
188
+ def class_selector
189
+ return unless tok(/\./)
190
+ @expected = "class name"
191
+ Selector::Class.new(tok!(IDENT))
192
+ end
193
+
194
+ def id_selector
195
+ return unless tok(/#(?!\{)/)
196
+ @expected = "id name"
197
+ Selector::Id.new(tok!(NAME))
198
+ end
199
+
200
+ def placeholder_selector
201
+ return unless tok(/%/)
202
+ @expected = "placeholder name"
203
+ Selector::Placeholder.new(tok!(IDENT))
204
+ end
205
+
206
+ def element_name
207
+ ns, name = Sass::Util.destructure(qualified_name(:allow_star_name))
208
+ return unless ns || name
209
+
210
+ if name == '*'
211
+ Selector::Universal.new(ns)
212
+ else
213
+ Selector::Element.new(name, ns)
214
+ end
215
+ end
216
+
217
+ def qualified_name(allow_star_name = false)
218
+ name = tok(IDENT) || tok(/\*/) || (tok?(/\|/) && "")
219
+ return unless name
220
+ return nil, name unless tok(/\|/)
221
+
222
+ return name, tok!(IDENT) unless allow_star_name
223
+ @expected = "identifier or *"
224
+ return name, tok(IDENT) || tok!(/\*/)
225
+ end
226
+
227
+ def attrib
228
+ return unless tok(/\[/)
229
+ ss
230
+ ns, name = attrib_name!
231
+ ss
232
+
233
+ op = tok(/=/) ||
234
+ tok(INCLUDES) ||
235
+ tok(DASHMATCH) ||
236
+ tok(PREFIXMATCH) ||
237
+ tok(SUFFIXMATCH) ||
238
+ tok(SUBSTRINGMATCH)
239
+ if op
240
+ @expected = "identifier or string"
241
+ ss
242
+ val = tok(IDENT) || tok!(STRING)
243
+ ss
244
+ end
245
+ flags = tok(IDENT) || tok(STRING)
246
+ tok!(/\]/)
247
+
248
+ Selector::Attribute.new(name, ns, op, val, flags)
249
+ end
250
+
251
+ def attrib_name!
252
+ if (name_or_ns = tok(IDENT))
253
+ # E, E|E
254
+ if tok(/\|(?!=)/)
255
+ ns = name_or_ns
256
+ name = tok(IDENT)
257
+ else
258
+ name = name_or_ns
259
+ end
260
+ else
261
+ # *|E or |E
262
+ ns = tok(/\*/) || ""
263
+ tok!(/\|/)
264
+ name = tok!(IDENT)
265
+ end
266
+ return ns, name
267
+ end
268
+
269
+ SELECTOR_PSEUDO_CLASSES = %w[not matches current any has host host-context].to_set
270
+
271
+ PREFIXED_SELECTOR_PSEUDO_CLASSES = %w[nth-child nth-last-child].to_set
272
+
273
+ def pseudo
274
+ s = tok(/::?/)
275
+ return unless s
276
+ @expected = "pseudoclass or pseudoelement"
277
+ name = tok!(IDENT)
278
+ if tok(/\(/)
279
+ ss
280
+ deprefixed = deprefix(name)
281
+ if s == ':' && SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
282
+ sel = selector_comma_sequence
283
+ elsif s == ':' && PREFIXED_SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
284
+ arg, sel = prefixed_selector_pseudo
285
+ else
286
+ arg = expr!(:pseudo_args)
287
+ end
288
+
289
+ tok!(/\)/)
290
+ end
291
+ Selector::Pseudo.new(s == ':' ? :class : :element, name, arg, sel)
292
+ end
293
+
294
+ def pseudo_args
295
+ arg = expr!(:pseudo_expr)
296
+ while tok(/,/)
297
+ arg << ',' << str {ss}
298
+ arg.concat expr!(:pseudo_expr)
299
+ end
300
+ arg
301
+ end
302
+
303
+ def pseudo_expr
304
+ res = pseudo_expr_token
305
+ return unless res
306
+ res << str {ss}
307
+ while (e = pseudo_expr_token)
308
+ res << e << str {ss}
309
+ end
310
+ res
311
+ end
312
+
313
+ def pseudo_expr_token
314
+ tok(PLUS) || tok(/[-*]/) || tok(NUMBER) || tok(STRING) || tok(IDENT)
315
+ end
316
+
317
+ def prefixed_selector_pseudo
318
+ prefix = str do
319
+ expr = str {expr!(:a_n_plus_b)}
320
+ ss
321
+ return expr, nil unless tok(/of/)
322
+ ss
323
+ end
324
+ return prefix, expr!(:selector_comma_sequence)
325
+ end
326
+
327
+ def a_n_plus_b
328
+ if (parity = tok(/even|odd/i))
329
+ return parity
330
+ end
331
+
332
+ if tok(/[+-]?[0-9]+/)
333
+ ss
334
+ return true unless tok(/n/)
335
+ else
336
+ return unless tok(/[+-]?n/i)
337
+ end
338
+ ss
339
+
340
+ return true unless tok(/[+-]/)
341
+ ss
342
+ @expected = "number"
343
+ tok!(/[0-9]+/)
344
+ true
345
+ end
346
+
347
+ def keyframes_selector
348
+ ss
349
+ str do
350
+ return unless keyframes_selector_component
351
+ ss
352
+ while tok(/,/)
353
+ ss
354
+ expr!(:keyframes_selector_component)
355
+ ss
356
+ end
357
+ end
358
+ end
359
+
360
+ def keyframes_selector_component
361
+ tok(/from|to/i) || tok(PERCENTAGE)
362
+ end
363
+
67
364
  @sass_script_parser = Class.new(Sass::Script::CssParser)
68
365
  @sass_script_parser.send(:include, ScriptParser)
69
366
  end
@@ -1,6 +1,7 @@
1
1
  require 'sass/selector/simple'
2
2
  require 'sass/selector/abstract_sequence'
3
3
  require 'sass/selector/comma_sequence'
4
+ require 'sass/selector/pseudo'
4
5
  require 'sass/selector/sequence'
5
6
  require 'sass/selector/simple_sequence'
6
7
 
@@ -27,19 +28,19 @@ module Sass
27
28
  # The function of this is to be replaced by the parent selector
28
29
  # in the nested hierarchy.
29
30
  class Parent < Simple
30
- # The identifier following the `&`. Often empty.
31
+ # The identifier following the `&`. `nil` indicates no suffix.
31
32
  #
32
- # @return [Array<String, Sass::Script::Tree::Node>]
33
+ # @return [String, nil]
33
34
  attr_reader :suffix
34
35
 
35
- # @param name [Array<String, Sass::Script::Tree::Node>] See \{#suffix}
36
- def initialize(suffix = [])
36
+ # @param name [String, nil] See \{#suffix}
37
+ def initialize(suffix = nil)
37
38
  @suffix = suffix
38
39
  end
39
40
 
40
- # @see Selector#to_a
41
- def to_a
42
- ["&", *@suffix]
41
+ # @see Selector#to_s
42
+ def to_s
43
+ "&" + (@suffix || '')
43
44
  end
44
45
 
45
46
  # Always raises an exception.
@@ -55,17 +56,17 @@ module Sass
55
56
  class Class < Simple
56
57
  # The class name.
57
58
  #
58
- # @return [Array<String, Sass::Script::Tree::Node>]
59
+ # @return [String]
59
60
  attr_reader :name
60
61
 
61
- # @param name [Array<String, Sass::Script::Tree::Node>] The class name
62
+ # @param name [String] The class name
62
63
  def initialize(name)
63
64
  @name = name
64
65
  end
65
66
 
66
- # @see Selector#to_a
67
- def to_a
68
- [".", *@name]
67
+ # @see Selector#to_s
68
+ def to_s
69
+ "." + @name
69
70
  end
70
71
 
71
72
  # @see AbstractSequence#specificity
@@ -78,17 +79,17 @@ module Sass
78
79
  class Id < Simple
79
80
  # The id name.
80
81
  #
81
- # @return [Array<String, Sass::Script::Tree::Node>]
82
+ # @return [String]
82
83
  attr_reader :name
83
84
 
84
- # @param name [Array<String, Sass::Script::Tree::Node>] The id name
85
+ # @param name [String] The id name
85
86
  def initialize(name)
86
87
  @name = name
87
88
  end
88
89
 
89
- # @see Selector#to_a
90
- def to_a
91
- ["#", *@name]
90
+ # @see Selector#to_s
91
+ def to_s
92
+ "#" + @name
92
93
  end
93
94
 
94
95
  # Returns `nil` if `sels` contains an {Id} selector
@@ -113,17 +114,17 @@ module Sass
113
114
  class Placeholder < Simple
114
115
  # The placeholder name.
115
116
  #
116
- # @return [Array<String, Sass::Script::Tree::Node>]
117
+ # @return [String]
117
118
  attr_reader :name
118
119
 
119
- # @param name [Array<String, Sass::Script::Tree::Node>] The placeholder name
120
+ # @param name [String] The placeholder name
120
121
  def initialize(name)
121
122
  @name = name
122
123
  end
123
124
 
124
- # @see Selector#to_a
125
- def to_a
126
- ["%", *@name]
125
+ # @see Selector#to_s
126
+ def to_s
127
+ "%" + @name
127
128
  end
128
129
 
129
130
  # @see AbstractSequence#specificity
@@ -134,22 +135,20 @@ module Sass
134
135
 
135
136
  # A universal selector (`*` in CSS).
136
137
  class Universal < Simple
137
- # The selector namespace.
138
- # `nil` means the default namespace,
139
- # `[""]` means no namespace,
140
- # `["*"]` means any namespace.
138
+ # The selector namespace. `nil` means the default namespace, `""` means no
139
+ # namespace, `"*"` means any namespace.
141
140
  #
142
- # @return [Array<String, Sass::Script::Tree::Node>, nil]
141
+ # @return [String, nil]
143
142
  attr_reader :namespace
144
143
 
145
- # @param namespace [Array<String, Sass::Script::Tree::Node>, nil] See \{#namespace}
144
+ # @param namespace [String, nil] See \{#namespace}
146
145
  def initialize(namespace)
147
146
  @namespace = namespace
148
147
  end
149
148
 
150
- # @see Selector#to_a
151
- def to_a
152
- @namespace ? @namespace + ["|*"] : ["*"]
149
+ # @see Selector#to_s
150
+ def to_s
151
+ @namespace ? "#{@namespace}|*" : "*"
153
152
  end
154
153
 
155
154
  # Unification of a universal selector is somewhat complicated,
@@ -183,7 +182,7 @@ module Sass
183
182
  when Universal; :universal
184
183
  when Element; sels.first.name
185
184
  else
186
- return [self] + sels unless namespace.nil? || namespace == ['*']
185
+ return [self] + sels unless namespace.nil? || namespace == '*'
187
186
  return sels unless sels.empty?
188
187
  return [self]
189
188
  end
@@ -203,27 +202,25 @@ module Sass
203
202
  class Element < Simple
204
203
  # The element name.
205
204
  #
206
- # @return [Array<String, Sass::Script::Tree::Node>]
205
+ # @return [String]
207
206
  attr_reader :name
208
207
 
209
- # The selector namespace.
210
- # `nil` means the default namespace,
211
- # `[""]` means no namespace,
212
- # `["*"]` means any namespace.
208
+ # The selector namespace. `nil` means the default namespace, `""` means no
209
+ # namespace, `"*"` means any namespace.
213
210
  #
214
- # @return [Array<String, Sass::Script::Tree::Node>, nil]
211
+ # @return [String, nil]
215
212
  attr_reader :namespace
216
213
 
217
- # @param name [Array<String, Sass::Script::Tree::Node>] The element name
218
- # @param namespace [Array<String, Sass::Script::Tree::Node>, nil] See \{#namespace}
214
+ # @param name [String] The element name
215
+ # @param namespace [String, nil] See \{#namespace}
219
216
  def initialize(name, namespace)
220
217
  @name = name
221
218
  @namespace = namespace
222
219
  end
223
220
 
224
- # @see Selector#to_a
225
- def to_a
226
- @namespace ? @namespace + ["|"] + @name : @name
221
+ # @see Selector#to_s
222
+ def to_s
223
+ @namespace ? "#{@namespace}|#{@name}" : @name
227
224
  end
228
225
 
229
226
  # Unification of an element selector is somewhat complicated,
@@ -266,32 +263,6 @@ module Sass
266
263
  end
267
264
  end
268
265
 
269
- # Selector interpolation (`#{}` in Sass).
270
- class Interpolation < Simple
271
- # The script to run.
272
- #
273
- # @return [Sass::Script::Tree::Node]
274
- attr_reader :script
275
-
276
- # @param script [Sass::Script::Tree::Node] The script to run
277
- def initialize(script)
278
- @script = script
279
- end
280
-
281
- # @see Selector#to_a
282
- def to_a
283
- [@script]
284
- end
285
-
286
- # Always raises an exception.
287
- #
288
- # @raise [Sass::SyntaxError] Interpolation selectors should be resolved before unification
289
- # @see Selector#unify
290
- def unify(sels)
291
- raise Sass::SyntaxError.new("[BUG] Cannot unify interpolation selectors.")
292
- end
293
- end
294
-
295
266
  # An attribute selector (e.g. `[href^="http://"]`).
296
267
  class Attribute < Simple
297
268
  # The attribute name.
@@ -299,12 +270,10 @@ module Sass
299
270
  # @return [Array<String, Sass::Script::Tree::Node>]
300
271
  attr_reader :name
301
272
 
302
- # The attribute namespace.
303
- # `nil` means the default namespace,
304
- # `[""]` means no namespace,
305
- # `["*"]` means any namespace.
273
+ # The attribute namespace. `nil` means the default namespace, `""` means
274
+ # no namespace, `"*"` means any namespace.
306
275
  #
307
- # @return [Array<String, Sass::Script::Tree::Node>, nil]
276
+ # @return [String, nil]
308
277
  attr_reader :namespace
309
278
 
310
279
  # The matching operator, e.g. `"="` or `"^="`.
@@ -314,19 +283,19 @@ module Sass
314
283
 
315
284
  # The right-hand side of the operator.
316
285
  #
317
- # @return [Array<String, Sass::Script::Tree::Node>]
286
+ # @return [String]
318
287
  attr_reader :value
319
288
 
320
289
  # Flags for the attribute selector (e.g. `i`).
321
290
  #
322
- # @return [Array<String, Sass::Script::Tree::Node>]
291
+ # @return [String]
323
292
  attr_reader :flags
324
293
 
325
- # @param name [Array<String, Sass::Script::Tree::Node>] The attribute name
326
- # @param namespace [Array<String, Sass::Script::Tree::Node>, nil] See \{#namespace}
294
+ # @param name [String] The attribute name
295
+ # @param namespace [String, nil] See \{#namespace}
327
296
  # @param operator [String] The matching operator, e.g. `"="` or `"^="`
328
- # @param value [Array<String, Sass::Script::Tree::Node>] See \{#value}
329
- # @param flags [Array<String, Sass::Script::Tree::Node>] See \{#flags}
297
+ # @param value [String] See \{#value}
298
+ # @param flags [String] See \{#flags}
330
299
  # @comment
331
300
  # rubocop:disable ParameterLists
332
301
  def initialize(name, namespace, operator, value, flags)
@@ -338,13 +307,13 @@ module Sass
338
307
  @flags = flags
339
308
  end
340
309
 
341
- # @see Selector#to_a
342
- def to_a
343
- res = ["["]
344
- res.concat(@namespace) << "|" if @namespace
345
- res.concat @name
346
- (res << @operator).concat @value if @value
347
- (res << " ").concat @flags if @flags
310
+ # @see Selector#to_s
311
+ def to_s
312
+ res = "["
313
+ res << @namespace << "|" if @namespace
314
+ res << @name
315
+ res << @operator << @value if @value
316
+ res << " " << @flags if @flags
348
317
  res << "]"
349
318
  end
350
319
 
@@ -353,111 +322,5 @@ module Sass
353
322
  SPECIFICITY_BASE
354
323
  end
355
324
  end
356
-
357
- # A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`) selector.
358
- # It can have arguments (e.g. `:nth-child(2n+1)`).
359
- class Pseudo < Simple
360
- # Some psuedo-class-syntax selectors are actually considered
361
- # pseudo-elements and must be treated differently. This is a list of such
362
- # selectors
363
- #
364
- # @return [Array<String>]
365
- ACTUALLY_ELEMENTS = %w[after before first-line first-letter]
366
-
367
- # Like \{#type}, but returns the type of selector this looks like, rather
368
- # than the type it is semantically. This only differs from type for
369
- # selectors in \{ACTUALLY\_ELEMENTS}.
370
- #
371
- # @return [Symbol]
372
- attr_reader :syntactic_type
373
-
374
- # The name of the selector.
375
- #
376
- # @return [Array<String, Sass::Script::Tree::Node>]
377
- attr_reader :name
378
-
379
- # The argument to the selector,
380
- # or `nil` if no argument was given.
381
- #
382
- # This may include SassScript nodes that will be run during resolution.
383
- # Note that this should not include SassScript nodes
384
- # after resolution has taken place.
385
- #
386
- # @return [Array<String, Sass::Script::Tree::Node>, nil]
387
- attr_reader :arg
388
-
389
- # @param type [Symbol] See \{#type}
390
- # @param name [Array<String, Sass::Script::Tree::Node>] The name of the selector
391
- # @param arg [nil, Array<String, Sass::Script::Tree::Node>] The argument to the selector,
392
- # or nil if no argument was given
393
- def initialize(type, name, arg)
394
- @syntactic_type = type
395
- @name = name
396
- @arg = arg
397
- end
398
-
399
- # The type of the selector. `:class` if this is a pseudoclass selector,
400
- # `:element` if it's a pseudoelement.
401
- #
402
- # @return [Symbol]
403
- def type
404
- ACTUALLY_ELEMENTS.include?(name.first) ? :element : syntactic_type
405
- end
406
-
407
- # @see Selector#to_a
408
- def to_a
409
- res = [syntactic_type == :class ? ":" : "::"] + @name
410
- (res << "(").concat(Sass::Util.strip_string_array(@arg)) << ")" if @arg
411
- res
412
- end
413
-
414
- # Returns `nil` if this is a pseudoelement selector
415
- # and `sels` contains a pseudoelement selector different than this one.
416
- #
417
- # @see Selector#unify
418
- def unify(sels)
419
- return if type == :element && sels.any? do |sel|
420
- sel.is_a?(Pseudo) && sel.type == :element &&
421
- (sel.name != name || sel.arg != arg)
422
- end
423
- super
424
- end
425
-
426
- # @see AbstractSequence#specificity
427
- def specificity
428
- type == :class ? SPECIFICITY_BASE : 1
429
- end
430
- end
431
-
432
- # A pseudoclass selector whose argument is itself a selector
433
- # (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`).
434
- class SelectorPseudoClass < Simple
435
- # The name of the pseudoclass.
436
- #
437
- # @return [String]
438
- attr_reader :name
439
-
440
- # The selector argument.
441
- #
442
- # @return [Selector::Sequence]
443
- attr_reader :selector
444
-
445
- # @param name [String] The name of the pseudoclass
446
- # @param selector [Selector::CommaSequence] The selector argument
447
- def initialize(name, selector)
448
- @name = name
449
- @selector = selector
450
- end
451
-
452
- # @see Selector#to_a
453
- def to_a
454
- [":", @name, "("] + @selector.to_a + [")"]
455
- end
456
-
457
- # @see AbstractSequence#specificity
458
- def specificity
459
- SPECIFICITY_BASE
460
- end
461
- end
462
325
  end
463
326
  end