sass 3.7.4 → 4.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +13 -5
  2. data/.yardopts +1 -1
  3. data/CODE_OF_CONDUCT.md +1 -1
  4. data/CONTRIBUTING.md +1 -146
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +25 -39
  7. data/Rakefile +274 -0
  8. data/VERSION +1 -1
  9. data/VERSION_DATE +1 -1
  10. data/lib/sass.rb +3 -3
  11. data/lib/sass/cache_stores/filesystem.rb +2 -2
  12. data/lib/sass/cache_stores/memory.rb +5 -4
  13. data/lib/sass/callbacks.rb +2 -2
  14. data/lib/sass/css.rb +12 -12
  15. data/lib/sass/engine.rb +44 -62
  16. data/lib/sass/environment.rb +7 -35
  17. data/lib/sass/error.rb +14 -14
  18. data/lib/sass/exec/base.rb +14 -3
  19. data/lib/sass/exec/sass_convert.rb +6 -20
  20. data/lib/sass/exec/sass_scss.rb +29 -5
  21. data/lib/sass/features.rb +2 -3
  22. data/lib/sass/importers/filesystem.rb +6 -11
  23. data/lib/sass/logger.rb +3 -8
  24. data/lib/sass/logger/base.rb +2 -19
  25. data/lib/sass/plugin.rb +2 -3
  26. data/lib/sass/plugin/compiler.rb +67 -48
  27. data/lib/sass/plugin/configuration.rb +3 -3
  28. data/lib/sass/plugin/merb.rb +1 -1
  29. data/lib/sass/plugin/rack.rb +3 -3
  30. data/lib/sass/plugin/staleness_checker.rb +3 -3
  31. data/lib/sass/railtie.rb +1 -1
  32. data/lib/sass/script.rb +3 -3
  33. data/lib/sass/script/css_parser.rb +15 -5
  34. data/lib/sass/script/functions.rb +121 -337
  35. data/lib/sass/script/lexer.rb +36 -102
  36. data/lib/sass/script/parser.rb +153 -529
  37. data/lib/sass/script/tree/funcall.rb +34 -42
  38. data/lib/sass/script/tree/interpolation.rb +26 -171
  39. data/lib/sass/script/tree/list_literal.rb +8 -23
  40. data/lib/sass/script/tree/map_literal.rb +2 -2
  41. data/lib/sass/script/tree/node.rb +3 -3
  42. data/lib/sass/script/tree/operation.rb +16 -43
  43. data/lib/sass/script/tree/string_interpolation.rb +43 -64
  44. data/lib/sass/script/tree/variable.rb +1 -1
  45. data/lib/sass/script/value.rb +0 -2
  46. data/lib/sass/script/value/arg_list.rb +1 -1
  47. data/lib/sass/script/value/base.rb +9 -27
  48. data/lib/sass/script/value/color.rb +18 -26
  49. data/lib/sass/script/value/helpers.rb +18 -44
  50. data/lib/sass/script/value/list.rb +14 -35
  51. data/lib/sass/script/value/map.rb +2 -2
  52. data/lib/sass/script/value/number.rb +16 -26
  53. data/lib/sass/script/value/string.rb +1 -30
  54. data/lib/sass/scss.rb +2 -0
  55. data/lib/sass/scss/css_parser.rb +3 -7
  56. data/lib/sass/scss/parser.rb +78 -196
  57. data/lib/sass/scss/rx.rb +14 -7
  58. data/lib/sass/scss/script_lexer.rb +15 -0
  59. data/lib/sass/scss/script_parser.rb +25 -0
  60. data/lib/sass/scss/static_parser.rb +55 -38
  61. data/lib/sass/selector.rb +10 -7
  62. data/lib/sass/selector/abstract_sequence.rb +12 -15
  63. data/lib/sass/selector/comma_sequence.rb +6 -24
  64. data/lib/sass/selector/pseudo.rb +6 -19
  65. data/lib/sass/selector/sequence.rb +16 -14
  66. data/lib/sass/selector/simple.rb +7 -9
  67. data/lib/sass/selector/simple_sequence.rb +12 -16
  68. data/lib/sass/shared.rb +1 -1
  69. data/lib/sass/source/map.rb +9 -7
  70. data/lib/sass/source/position.rb +4 -4
  71. data/lib/sass/stack.rb +3 -23
  72. data/lib/sass/tree/charset_node.rb +1 -1
  73. data/lib/sass/tree/comment_node.rb +1 -1
  74. data/lib/sass/tree/function_node.rb +3 -2
  75. data/lib/sass/tree/node.rb +3 -5
  76. data/lib/sass/tree/prop_node.rb +58 -49
  77. data/lib/sass/tree/rule_node.rb +8 -15
  78. data/lib/sass/tree/visitors/check_nesting.rb +23 -19
  79. data/lib/sass/tree/visitors/convert.rb +13 -15
  80. data/lib/sass/tree/visitors/cssize.rb +15 -4
  81. data/lib/sass/tree/visitors/deep_copy.rb +2 -2
  82. data/lib/sass/tree/visitors/extend.rb +14 -10
  83. data/lib/sass/tree/visitors/perform.rb +18 -29
  84. data/lib/sass/tree/visitors/set_options.rb +2 -2
  85. data/lib/sass/tree/visitors/to_css.rb +47 -77
  86. data/lib/sass/util.rb +311 -98
  87. data/lib/sass/util/cross_platform_random.rb +19 -0
  88. data/lib/sass/util/multibyte_string_scanner.rb +133 -127
  89. data/lib/sass/util/normalized_map.rb +8 -1
  90. data/lib/sass/util/ordered_hash.rb +192 -0
  91. data/lib/sass/version.rb +6 -2
  92. data/test/sass/cache_test.rb +131 -0
  93. data/test/sass/callbacks_test.rb +61 -0
  94. data/test/sass/compiler_test.rb +236 -0
  95. data/test/sass/conversion_test.rb +2171 -0
  96. data/test/sass/css2sass_test.rb +526 -0
  97. data/test/sass/data/hsl-rgb.txt +319 -0
  98. data/test/sass/encoding_test.rb +219 -0
  99. data/test/sass/engine_test.rb +3400 -0
  100. data/test/sass/exec_test.rb +86 -0
  101. data/test/sass/extend_test.rb +1719 -0
  102. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  103. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  104. data/test/sass/functions_test.rb +1984 -0
  105. data/test/sass/importer_test.rb +421 -0
  106. data/test/sass/logger_test.rb +58 -0
  107. data/test/sass/mock_importer.rb +49 -0
  108. data/test/sass/more_results/more1.css +9 -0
  109. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  110. data/test/sass/more_results/more_import.css +29 -0
  111. data/test/sass/more_templates/_more_partial.sass +2 -0
  112. data/test/sass/more_templates/more1.sass +23 -0
  113. data/test/sass/more_templates/more_import.sass +11 -0
  114. data/test/sass/plugin_test.rb +556 -0
  115. data/test/sass/results/alt.css +4 -0
  116. data/test/sass/results/basic.css +9 -0
  117. data/test/sass/results/cached_import_option.css +3 -0
  118. data/test/sass/results/compact.css +5 -0
  119. data/test/sass/results/complex.css +86 -0
  120. data/test/sass/results/compressed.css +1 -0
  121. data/test/sass/results/expanded.css +19 -0
  122. data/test/sass/results/filename_fn.css +3 -0
  123. data/test/sass/results/if.css +3 -0
  124. data/test/sass/results/import.css +31 -0
  125. data/test/sass/results/import_charset.css +5 -0
  126. data/test/sass/results/import_charset_1_8.css +5 -0
  127. data/test/sass/results/import_charset_ibm866.css +5 -0
  128. data/test/sass/results/import_content.css +1 -0
  129. data/test/sass/results/line_numbers.css +49 -0
  130. data/test/sass/results/mixins.css +95 -0
  131. data/test/sass/results/multiline.css +24 -0
  132. data/test/sass/results/nested.css +22 -0
  133. data/test/sass/results/options.css +1 -0
  134. data/test/sass/results/parent_ref.css +13 -0
  135. data/test/sass/results/script.css +16 -0
  136. data/test/sass/results/scss_import.css +31 -0
  137. data/test/sass/results/scss_importee.css +2 -0
  138. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/test/sass/results/subdir/subdir.css +3 -0
  140. data/test/sass/results/units.css +11 -0
  141. data/test/sass/results/warn.css +0 -0
  142. data/test/sass/results/warn_imported.css +0 -0
  143. data/test/sass/script_conversion_test.rb +306 -0
  144. data/test/sass/script_test.rb +1206 -0
  145. data/test/sass/scss/css_test.rb +1281 -0
  146. data/test/sass/scss/rx_test.rb +160 -0
  147. data/test/sass/scss/scss_test.rb +4147 -0
  148. data/test/sass/scss/test_helper.rb +37 -0
  149. data/test/sass/source_map_test.rb +1055 -0
  150. data/test/sass/superselector_test.rb +210 -0
  151. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  152. data/test/sass/templates/_double_import_loop2.sass +1 -0
  153. data/test/sass/templates/_filename_fn_import.scss +11 -0
  154. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  155. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  156. data/test/sass/templates/_imported_content.sass +3 -0
  157. data/test/sass/templates/_partial.sass +2 -0
  158. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  159. data/test/sass/templates/alt.sass +16 -0
  160. data/test/sass/templates/basic.sass +23 -0
  161. data/test/sass/templates/bork1.sass +2 -0
  162. data/test/sass/templates/bork2.sass +2 -0
  163. data/test/sass/templates/bork3.sass +2 -0
  164. data/test/sass/templates/bork4.sass +2 -0
  165. data/test/sass/templates/bork5.sass +3 -0
  166. data/test/sass/templates/cached_import_option.scss +3 -0
  167. data/test/sass/templates/compact.sass +17 -0
  168. data/test/sass/templates/complex.sass +305 -0
  169. data/test/sass/templates/compressed.sass +15 -0
  170. data/test/sass/templates/double_import_loop1.sass +1 -0
  171. data/test/sass/templates/expanded.sass +17 -0
  172. data/test/sass/templates/filename_fn.scss +18 -0
  173. data/test/sass/templates/if.sass +11 -0
  174. data/test/sass/templates/import.sass +12 -0
  175. data/test/sass/templates/import_charset.sass +9 -0
  176. data/test/sass/templates/import_charset_1_8.sass +6 -0
  177. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  178. data/test/sass/templates/import_content.sass +4 -0
  179. data/test/sass/templates/importee.less +2 -0
  180. data/test/sass/templates/importee.sass +19 -0
  181. data/test/sass/templates/line_numbers.sass +13 -0
  182. data/test/sass/templates/mixin_bork.sass +5 -0
  183. data/test/sass/templates/mixins.sass +76 -0
  184. data/test/sass/templates/multiline.sass +20 -0
  185. data/test/sass/templates/nested.sass +25 -0
  186. data/test/sass/templates/nested_bork1.sass +2 -0
  187. data/test/sass/templates/nested_bork2.sass +2 -0
  188. data/test/sass/templates/nested_bork3.sass +2 -0
  189. data/test/sass/templates/nested_bork4.sass +2 -0
  190. data/test/sass/templates/nested_import.sass +2 -0
  191. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  192. data/test/sass/templates/options.sass +2 -0
  193. data/test/sass/templates/parent_ref.sass +25 -0
  194. data/test/sass/templates/same_name_different_ext.sass +2 -0
  195. data/test/sass/templates/same_name_different_ext.scss +1 -0
  196. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  197. data/test/sass/templates/script.sass +101 -0
  198. data/test/sass/templates/scss_import.scss +12 -0
  199. data/test/sass/templates/scss_importee.scss +1 -0
  200. data/test/sass/templates/single_import_loop.sass +1 -0
  201. data/test/sass/templates/subdir/import_up1.scss +1 -0
  202. data/test/sass/templates/subdir/import_up2.scss +1 -0
  203. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  204. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  205. data/test/sass/templates/subdir/subdir.sass +6 -0
  206. data/test/sass/templates/units.sass +11 -0
  207. data/test/sass/templates/warn.sass +3 -0
  208. data/test/sass/templates/warn_imported.sass +4 -0
  209. data/test/sass/test_helper.rb +8 -0
  210. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  211. data/test/sass/util/normalized_map_test.rb +51 -0
  212. data/test/sass/util/subset_map_test.rb +91 -0
  213. data/test/sass/util_test.rb +438 -0
  214. data/test/sass/value_helpers_test.rb +179 -0
  215. data/test/test_helper.rb +110 -0
  216. data/vendor/listen/CHANGELOG.md +1 -0
  217. data/vendor/listen/CONTRIBUTING.md +38 -0
  218. data/vendor/listen/Gemfile +20 -0
  219. data/vendor/listen/Guardfile +8 -0
  220. data/vendor/listen/LICENSE +20 -0
  221. data/vendor/listen/README.md +349 -0
  222. data/vendor/listen/Rakefile +5 -0
  223. data/vendor/listen/Vagrantfile +96 -0
  224. data/vendor/listen/lib/listen.rb +54 -0
  225. data/vendor/listen/lib/listen/adapter.rb +327 -0
  226. data/vendor/listen/lib/listen/adapters/bsd.rb +75 -0
  227. data/vendor/listen/lib/listen/adapters/darwin.rb +48 -0
  228. data/vendor/listen/lib/listen/adapters/linux.rb +81 -0
  229. data/vendor/listen/lib/listen/adapters/polling.rb +58 -0
  230. data/vendor/listen/lib/listen/adapters/windows.rb +91 -0
  231. data/vendor/listen/lib/listen/directory_record.rb +406 -0
  232. data/vendor/listen/lib/listen/listener.rb +323 -0
  233. data/vendor/listen/lib/listen/turnstile.rb +32 -0
  234. data/vendor/listen/lib/listen/version.rb +3 -0
  235. data/vendor/listen/listen.gemspec +28 -0
  236. data/vendor/listen/spec/listen/adapter_spec.rb +149 -0
  237. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  238. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  239. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  240. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  241. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  242. data/vendor/listen/spec/listen/directory_record_spec.rb +1250 -0
  243. data/vendor/listen/spec/listen/listener_spec.rb +258 -0
  244. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  245. data/vendor/listen/spec/listen_spec.rb +67 -0
  246. data/vendor/listen/spec/spec_helper.rb +25 -0
  247. data/vendor/listen/spec/support/adapter_helper.rb +666 -0
  248. data/vendor/listen/spec/support/directory_record_helper.rb +57 -0
  249. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  250. data/vendor/listen/spec/support/listeners_helper.rb +179 -0
  251. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  252. metadata +217 -76
  253. data/extra/sass-spec-ref.sh +0 -40
  254. data/lib/sass/deprecation.rb +0 -55
  255. data/lib/sass/logger/delayed.rb +0 -50
  256. data/lib/sass/script/value/callable.rb +0 -25
  257. data/lib/sass/script/value/function.rb +0 -19
@@ -66,35 +66,26 @@ module Sass::Script::Value
66
66
  Number.new(number, *parse_unit_string(unit_string))
67
67
  end
68
68
 
69
- # @overload list(*elements, separator:, bracketed: false)
69
+ # @overload list(*elements, separator)
70
70
  # Create a space-separated list from the arguments given.
71
71
  # @param elements [Array<Sass::Script::Value::Base>] Each argument will be a list element.
72
72
  # @param separator [Symbol] Either :space or :comma.
73
- # @param bracketed [Boolean] Whether the list uses square brackets.
74
73
  # @return [Sass::Script::Value::List] The space separated list.
75
74
  #
76
- # @overload list(array, separator:, bracketed: false)
75
+ # @overload list(array, separator)
77
76
  # Create a space-separated list from the array given.
78
77
  # @param array [Array<Sass::Script::Value::Base>] A ruby array of Sass values
79
78
  # to make into a list.
80
- # @param separator [Symbol] Either :space or :comma.
81
- # @param bracketed [Boolean] Whether the list uses square brackets.
82
79
  # @return [Sass::Script::Value::List] The space separated list.
83
- def list(*elements, separator: nil, bracketed: false)
84
- # Support passing separator as the last value in elements for
85
- # backwards-compatibility.
86
- if separator.nil?
87
- if elements.last.is_a?(Symbol)
88
- separator = elements.pop
89
- else
90
- raise ArgumentError.new("A separator of :space or :comma must be specified.")
91
- end
80
+ def list(*elements)
81
+ unless elements.last.is_a?(Symbol)
82
+ raise ArgumentError.new("A list type of :space or :comma must be specified.")
92
83
  end
93
-
84
+ separator = elements.pop
94
85
  if elements.size == 1 && elements.first.is_a?(Array)
95
86
  elements = elements.first
96
87
  end
97
- Sass::Script::Value::List.new(elements, separator: separator, bracketed: bracketed)
88
+ Sass::Script::Value::List.new(elements, separator)
98
89
  end
99
90
 
100
91
  # Construct a Sass map.
@@ -148,7 +139,7 @@ module Sass::Script::Value
148
139
  Sass::SCSS::StaticParser.new(str, nil, nil, 1, 1, allow_parent_ref).parse_selector
149
140
  rescue Sass::SyntaxError => e
150
141
  err = "#{value.inspect} is not a valid selector: #{e}"
151
- err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
142
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
152
143
  raise ArgumentError.new(err)
153
144
  end
154
145
  end
@@ -172,7 +163,7 @@ module Sass::Script::Value
172
163
  return seq if selector.members.length == 1
173
164
 
174
165
  err = "#{value.inspect} is not a complex selector"
175
- err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
166
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
176
167
  raise ArgumentError.new(err)
177
168
  end
178
169
 
@@ -199,35 +190,18 @@ module Sass::Script::Value
199
190
  end
200
191
 
201
192
  err = "#{value.inspect} is not a compound selector"
202
- err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
193
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
203
194
  raise ArgumentError.new(err)
204
195
  end
205
196
 
206
- # Returns true when the literal is a string containing a calc().
207
- #
208
- # Use \{#special_number?} in preference to this.
197
+ # Returns true when the literal is a string containing a calc()
209
198
  #
210
199
  # @param literal [Sass::Script::Value::Base] The value to check
211
- # @return Boolean
200
+ # @return boolean
212
201
  def calc?(literal)
213
- literal.is_a?(Sass::Script::Value::String) && literal.value =~ /calc\(/
214
- end
215
-
216
- # Returns true when the literal is a string containing a var().
217
- #
218
- # @param literal [Sass::Script::Value::Base] The value to check
219
- # @return Boolean
220
- def var?(literal)
221
- literal.is_a?(Sass::Script::Value::String) && literal.value =~ /var\(/
222
- end
223
-
224
- # Returns whether the literal is a special CSS value that may evaluate to a
225
- # number, such as `calc()` or `var()`.
226
- #
227
- # @param literal [Sass::Script::Value::Base] The value to check
228
- # @return Boolean
229
- def special_number?(literal)
230
- literal.is_a?(Sass::Script::Value::String) && literal.value =~ /(calc|var)\(/
202
+ if literal.is_a?(Sass::Script::Value::String)
203
+ literal.value =~ /calc\(/
204
+ end
231
205
  end
232
206
 
233
207
  private
@@ -241,7 +215,7 @@ module Sass::Script::Value
241
215
 
242
216
  err = "#{value.inspect} is not a valid selector: it must be a string,\n" +
243
217
  "a list of strings, or a list of lists of strings"
244
- err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
218
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
245
219
  raise ArgumentError.new(err)
246
220
  end
247
221
 
@@ -278,14 +252,14 @@ module Sass::Script::Value
278
252
  def parse_unit_string(unit_string)
279
253
  denominator_units = numerator_units = Sass::Script::Value::Number::NO_UNITS
280
254
  return numerator_units, denominator_units unless unit_string && unit_string.length > 0
281
- num_over_denominator = unit_string.split(%r{ */ *})
255
+ num_over_denominator = unit_string.split(/ *\/ */)
282
256
  unless (1..2).include?(num_over_denominator.size)
283
257
  raise ArgumentError.new("Malformed unit string: #{unit_string}")
284
258
  end
285
259
  numerator_units = num_over_denominator[0].split(/ *\* */)
286
260
  denominator_units = (num_over_denominator[1] || "").split(/ *\* */)
287
261
  [[numerator_units, "numerator"], [denominator_units, "denominator"]].each do |units, name|
288
- if unit_string =~ %r{/} && units.size == 0
262
+ if unit_string =~ /\// && units.size == 0
289
263
  raise ArgumentError.new("Malformed unit string: #{unit_string}")
290
264
  end
291
265
  if units.any? {|unit| unit !~ VALID_UNIT}
@@ -14,20 +14,13 @@ module Sass::Script::Value
14
14
  # @return [Symbol]
15
15
  attr_reader :separator
16
16
 
17
- # Whether the list is surrounded by square brackets.
18
- #
19
- # @return [Boolean]
20
- attr_reader :bracketed
21
-
22
17
  # Creates a new list.
23
18
  #
24
19
  # @param value [Array<Value>] See \{#value}
25
20
  # @param separator [Symbol] See \{#separator}
26
- # @param bracketed [Boolean] See \{#bracketed}
27
- def initialize(value, separator: nil, bracketed: false)
21
+ def initialize(value, separator)
28
22
  super(value)
29
23
  @separator = separator
30
- @bracketed = bracketed
31
24
  end
32
25
 
33
26
  # @see Value#options=
@@ -40,30 +33,24 @@ module Sass::Script::Value
40
33
  def eq(other)
41
34
  Sass::Script::Value::Bool.new(
42
35
  other.is_a?(List) && value == other.value &&
43
- separator == other.separator && bracketed == other.bracketed)
36
+ separator == other.separator)
44
37
  end
45
38
 
46
39
  def hash
47
- @hash ||= [value, separator, bracketed].hash
40
+ @hash ||= [value, separator].hash
48
41
  end
49
42
 
50
43
  # @see Value#to_s
51
44
  def to_s(opts = {})
52
- if !bracketed && value.empty?
53
- raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.")
54
- end
55
-
56
- members = value.
45
+ raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty?
46
+ value.
57
47
  reject {|e| e.is_a?(Null) || e.is_a?(List) && e.value.empty?}.
58
- map {|e| e.to_s(opts)}
59
-
60
- contents = members.join(sep_str)
61
- bracketed ? "[#{contents}]" : contents
48
+ map {|e| e.to_s(opts)}.join(sep_str)
62
49
  end
63
50
 
64
51
  # @see Value#to_sass
65
52
  def to_sass(opts = {})
66
- return bracketed ? "[]" : "()" if value.empty?
53
+ return "()" if value.empty?
67
54
  members = value.map do |v|
68
55
  if element_needs_parens?(v)
69
56
  "(#{v.to_sass(opts)})"
@@ -71,26 +58,19 @@ module Sass::Script::Value
71
58
  v.to_sass(opts)
72
59
  end
73
60
  end
74
-
75
- if separator == :comma && members.length == 1
76
- return "#{bracketed ? '[' : '('}#{members.first},#{bracketed ? ']' : ')'}"
77
- end
78
-
79
- contents = members.join(sep_str(nil))
80
- bracketed ? "[#{contents}]" : contents
61
+ return "(#{members.first},)" if members.length == 1 && separator == :comma
62
+ members.join(sep_str(nil))
81
63
  end
82
64
 
83
65
  # @see Value#to_h
84
66
  def to_h
85
- return {} if value.empty?
67
+ return Sass::Util.ordered_hash if value.empty?
86
68
  super
87
69
  end
88
70
 
89
71
  # @see Value#inspect
90
72
  def inspect
91
- (bracketed ? '[' : '(') +
92
- value.map {|e| e.inspect}.join(sep_str(nil)) +
93
- (bracketed ? ']' : ')')
73
+ "(#{value.map {|e| e.inspect}.join(sep_str(nil))})"
94
74
  end
95
75
 
96
76
  # Asserts an index is within the list.
@@ -114,10 +94,9 @@ module Sass::Script::Value
114
94
 
115
95
  def element_needs_parens?(element)
116
96
  if element.is_a?(List)
117
- return false if element.value.length < 2
118
- return false if element.bracketed
119
- precedence = Sass::Script::Parser.precedence_of(separator || :space)
120
- return Sass::Script::Parser.precedence_of(element.separator || :space) <= precedence
97
+ return false if element.value.empty?
98
+ precedence = Sass::Script::Parser.precedence_of(separator)
99
+ return Sass::Script::Parser.precedence_of(element.separator) <= precedence
121
100
  end
122
101
 
123
102
  return false unless separator == :space
@@ -12,7 +12,7 @@ module Sass::Script::Value
12
12
  #
13
13
  # @param hash [Hash<Node, Node>]
14
14
  def initialize(hash)
15
- super(hash)
15
+ super(Sass::Util.ordered_hash(hash))
16
16
  end
17
17
 
18
18
  # @see Value#options=
@@ -32,7 +32,7 @@ module Sass::Script::Value
32
32
  # @see Value#to_a
33
33
  def to_a
34
34
  value.map do |k, v|
35
- list = List.new([k, v], separator: :space)
35
+ list = List.new([k, v], :space)
36
36
  list.options = options
37
37
  list
38
38
  end
@@ -34,35 +34,33 @@ module Sass::Script::Value
34
34
  attr_accessor :original
35
35
 
36
36
  def self.precision
37
- Thread.current[:sass_numeric_precision] || Thread.main[:sass_numeric_precision] || 10
37
+ @precision ||= 5
38
38
  end
39
39
 
40
40
  # Sets the number of digits of precision
41
41
  # For example, if this is `3`,
42
42
  # `3.1415926` will be printed as `3.142`.
43
- # The numeric precision is stored as a thread local for thread safety reasons.
44
- # To set for all threads, be sure to set the precision on the main thread.
45
43
  def self.precision=(digits)
46
- Thread.current[:sass_numeric_precision] = digits.round
47
- Thread.current[:sass_numeric_precision_factor] = nil
48
- Thread.current[:sass_numeric_epsilon] = nil
44
+ @precision = digits.round
45
+ @precision_factor = 10.0**@precision
46
+ @epsilon = 1 / (@precision_factor * 10)
49
47
  end
50
48
 
51
49
  # the precision factor used in numeric output
52
50
  # it is derived from the `precision` method.
53
51
  def self.precision_factor
54
- Thread.current[:sass_numeric_precision_factor] ||= 10.0**precision
52
+ @precision_factor ||= 10.0**precision
55
53
  end
56
54
 
57
55
  # Used in checking equality of floating point numbers. Any
58
56
  # numbers within an `epsilon` of each other are considered functionally equal.
59
57
  # The value for epsilon is one tenth of the current numeric precision.
60
58
  def self.epsilon
61
- Thread.current[:sass_numeric_epsilon] ||= 1 / (precision_factor * 10)
59
+ @epsilon ||= 1 / (precision_factor * 10)
62
60
  end
63
61
 
64
62
  # Used so we don't allocate two new arrays for each new number.
65
- NO_UNITS = []
63
+ NO_UNITS = []
66
64
 
67
65
  # @param value [Numeric] The value of the number
68
66
  # @param numerator_units [::String, Array<::String>] See \{#numerator\_units}
@@ -73,7 +71,6 @@ module Sass::Script::Value
73
71
  super(value)
74
72
  @numerator_units = numerator_units
75
73
  @denominator_units = denominator_units
76
- @options = nil
77
74
  normalize!
78
75
  end
79
76
 
@@ -189,7 +186,6 @@ module Sass::Script::Value
189
186
  # @raise [Sass::UnitConversionError] if `other` has incompatible units
190
187
  def mod(other)
191
188
  if other.is_a?(Number)
192
- return Number.new(Float::NAN) if other.value == 0
193
189
  operate(other, :%)
194
190
  else
195
191
  raise NoMethodError.new(nil, :mod)
@@ -293,21 +289,14 @@ module Sass::Script::Value
293
289
  # and confusing.
294
290
  str = ("%0.#{self.class.precision}f" % value).gsub(/0*$/, '') if str.include?('e')
295
291
 
296
- # Sometimes numeric formatting will result in a decimal number with a trailing zero (x.0)
297
- if str =~ /(.*)\.0$/
298
- str = $1
299
- end
300
-
301
- # We omit a leading zero before the decimal point in compressed mode.
302
292
  if @options && options[:style] == :compressed
303
293
  str.sub!(/^(-)?0\./, '\1.')
304
294
  end
305
-
306
295
  unitless? ? str : "#{str}#{unit_str}"
307
296
  end
308
297
  alias_method :to_sass, :inspect
309
298
 
310
- # @return [Integer] The integer value of the number
299
+ # @return [Fixnum] The integer value of the number
311
300
  # @raise [Sass::SyntaxError] if the number isn't an integer
312
301
  def to_i
313
302
  super unless int?
@@ -414,7 +403,7 @@ module Sass::Script::Value
414
403
  if num.is_a?(Float) && (num.infinite? || num.nan?)
415
404
  num
416
405
  elsif basically_equal?(num % 1, 0.0)
417
- num.round
406
+ num.to_i
418
407
  else
419
408
  ((num * precision_factor).round / precision_factor).to_f
420
409
  end
@@ -473,10 +462,11 @@ module Sass::Script::Value
473
462
  sans_common_units(@numerator_units, @denominator_units)
474
463
 
475
464
  @denominator_units.each_with_index do |d, i|
476
- next unless convertable?(d) && (u = @numerator_units.find {|n| convertable?([n, d])})
477
- @value /= conversion_factor(d, u)
478
- @denominator_units.delete_at(i)
479
- @numerator_units.delete_at(@numerator_units.index(u))
465
+ if convertable?(d) && (u = @numerator_units.find(&method(:convertable?)))
466
+ @value /= conversion_factor(d, u)
467
+ @denominator_units.delete_at(i)
468
+ @numerator_units.delete_at(@numerator_units.index(u))
469
+ end
480
470
  end
481
471
  end
482
472
 
@@ -511,8 +501,8 @@ module Sass::Script::Value
511
501
  },
512
502
  {
513
503
  'dpi' => Rational(1),
514
- 'dpcm' => Rational(254, 100),
515
- 'dppx' => Rational(96)
504
+ 'dpcm' => Rational(1, 2.54),
505
+ 'dppx' => Rational(1, 96)
516
506
  }
517
507
  ]
518
508
 
@@ -2,8 +2,6 @@
2
2
  module Sass::Script::Value
3
3
  # A SassScript object representing a CSS string *or* a CSS identifier.
4
4
  class String < Base
5
- @@interpolation_deprecation = Sass::Deprecation.new
6
-
7
5
  # The Ruby value of the string.
8
6
  #
9
7
  # @return [String]
@@ -78,13 +76,9 @@ module Sass::Script::Value
78
76
  #
79
77
  # @param value [String] See \{#value}
80
78
  # @param type [Symbol] See \{#type}
81
- # @param deprecated_interp_equivalent [String?]
82
- # If this was created via a potentially-deprecated string interpolation,
83
- # this is the replacement expression that should be suggested to the user.
84
- def initialize(value, type = :identifier, deprecated_interp_equivalent = nil)
79
+ def initialize(value, type = :identifier)
85
80
  super(value)
86
81
  @type = type
87
- @deprecated_interp_equivalent = deprecated_interp_equivalent
88
82
  end
89
83
 
90
84
  # @see Value#plus
@@ -108,29 +102,6 @@ module Sass::Script::Value
108
102
  to_s(opts.merge(:sass => true))
109
103
  end
110
104
 
111
- def separator
112
- check_deprecated_interp
113
- super
114
- end
115
-
116
- def to_a
117
- check_deprecated_interp
118
- super
119
- end
120
-
121
- # Prints a warning if this string was created using potentially-deprecated
122
- # interpolation.
123
- def check_deprecated_interp
124
- return unless @deprecated_interp_equivalent
125
-
126
- @@interpolation_deprecation.warn(source_range.file, source_range.start_pos.line, <<WARNING)
127
- \#{} interpolation near operators will be simplified in a future version of Sass.
128
- To preserve the current behavior, use quotes:
129
-
130
- #{@deprecated_interp_equivalent}
131
- WARNING
132
- end
133
-
134
105
  def inspect
135
106
  String.quote(value)
136
107
  end
@@ -1,4 +1,6 @@
1
1
  require 'sass/scss/rx'
2
+ require 'sass/scss/script_lexer'
3
+ require 'sass/scss/script_parser'
2
4
  require 'sass/scss/parser'
3
5
  require 'sass/scss/static_parser'
4
6
  require 'sass/scss/css_parser'
@@ -47,15 +47,11 @@ module Sass
47
47
  def keyframes_ruleset
48
48
  start_pos = source_position
49
49
  return unless (selector = keyframes_selector)
50
- block(
51
- node(
52
- Sass::Tree::KeyframeRuleNode.new(
53
- Sass::Util.strip_except_escapes(selector)),
54
- start_pos),
55
- :ruleset)
50
+ block(node(Sass::Tree::KeyframeRuleNode.new(selector.strip), start_pos), :ruleset)
56
51
  end
57
52
 
58
- @sass_script_parser = Sass::Script::CssParser
53
+ @sass_script_parser = Class.new(Sass::Script::CssParser)
54
+ @sass_script_parser.send(:include, ScriptParser)
59
55
  end
60
56
  end
61
57
  end
@@ -16,20 +16,21 @@ module Sass
16
16
  # warnings and source maps.
17
17
  # @param importer [Sass::Importers::Base] The importer used to import the
18
18
  # file being parsed. Used for source maps.
19
- # @param line [Integer] The 1-based line on which the source string appeared,
19
+ # @param line [Fixnum] The 1-based line on which the source string appeared,
20
20
  # if it's part of another document.
21
- # @param offset [Integer] The 1-based character (not byte) offset in the line on
21
+ # @param offset [Fixnum] The 1-based character (not byte) offset in the line on
22
22
  # which the source string starts. Used for error reporting and sourcemap
23
23
  # building.
24
+ # @comment
25
+ # rubocop:disable ParameterLists
24
26
  def initialize(str, filename, importer, line = 1, offset = 1)
27
+ # rubocop:enable ParameterLists
25
28
  @template = str
26
29
  @filename = filename
27
30
  @importer = importer
28
31
  @line = line
29
32
  @offset = offset
30
33
  @strs = []
31
- @expected = nil
32
- @throw_error = false
33
34
  end
34
35
 
35
36
  # Parses an SCSS document.
@@ -99,18 +100,6 @@ module Sass
99
100
  condition
100
101
  end
101
102
 
102
- # Parses a custom property value.
103
- #
104
- # @return [Array<String, Sass::Script;:Tree::Node>] The interpolated value.
105
- # @raise [Sass::SyntaxError] if there's a syntax error in the value,
106
- # or if it doesn't take up the entire input string.
107
- def parse_declaration_value
108
- init_scanner!
109
- value = declaration_value
110
- expected('"}"') unless value && @scanner.eos?
111
- value
112
- end
113
-
114
103
  private
115
104
 
116
105
  include Sass::SCSS::RX
@@ -128,7 +117,7 @@ module Sass
128
117
  if @template.is_a?(StringScanner)
129
118
  @template
130
119
  else
131
- Sass::Util::MultibyteStringScanner.new(@template.tr("\r", ""))
120
+ Sass::Util::MultibyteStringScanner.new(@template.gsub("\r", ""))
132
121
  end
133
122
  end
134
123
 
@@ -203,7 +192,7 @@ module Sass
203
192
  def directive
204
193
  start_pos = source_position
205
194
  return unless tok(/@/)
206
- name = ident!
195
+ name = tok!(IDENT)
207
196
  ss
208
197
 
209
198
  if (dir = special_directive(name, start_pos))
@@ -240,14 +229,14 @@ module Sass
240
229
  end
241
230
 
242
231
  def mixin_directive(start_pos)
243
- name = ident!
232
+ name = tok! IDENT
244
233
  args, splat = sass_script(:parse_mixin_definition_arglist)
245
234
  ss
246
235
  block(node(Sass::Tree::MixinDefNode.new(name, args, splat), start_pos), :directive)
247
236
  end
248
237
 
249
238
  def include_directive(start_pos)
250
- name = ident!
239
+ name = tok! IDENT
251
240
  args, keywords, splat, kwarg_splat = sass_script(:parse_mixin_include_arglist)
252
241
  ss
253
242
  include_node = node(
@@ -266,7 +255,7 @@ module Sass
266
255
  end
267
256
 
268
257
  def function_directive(start_pos)
269
- name = ident!
258
+ name = tok! IDENT
270
259
  args, splat = sass_script(:parse_function_definition_arglist)
271
260
  ss
272
261
  block(node(Sass::Tree::FunctionNode.new(name, args, splat), start_pos), :function)
@@ -286,7 +275,7 @@ module Sass
286
275
 
287
276
  def for_directive(start_pos)
288
277
  tok!(/\$/)
289
- var = ident!
278
+ var = tok! IDENT
290
279
  ss
291
280
 
292
281
  tok!(/from/)
@@ -303,12 +292,12 @@ module Sass
303
292
 
304
293
  def each_directive(start_pos)
305
294
  tok!(/\$/)
306
- vars = [ident!]
295
+ vars = [tok!(IDENT)]
307
296
  ss
308
297
  while tok(/,/)
309
298
  ss
310
299
  tok!(/\$/)
311
- vars << ident!
300
+ vars << tok!(IDENT)
312
301
  ss
313
302
  end
314
303
 
@@ -407,8 +396,7 @@ module Sass
407
396
  ss
408
397
  media = media_query_list
409
398
  if str =~ %r{^(https?:)?//} || media || supports || use_css_import?
410
- return node(
411
- Sass::Tree::CssImportNode.new(
399
+ return node(Sass::Tree::CssImportNode.new(
412
400
  Sass::Script::Value::String.quote(str), media.to_a, supports), start_pos)
413
401
  end
414
402
 
@@ -477,23 +465,12 @@ module Sass
477
465
  return unless tok(/\(/)
478
466
  res = ['(']
479
467
  ss
480
- stop_at = Set[:single_eq, :lt, :lte, :gt, :gte]
481
- res << sass_script(:parse_until, stop_at)
468
+ res << sass_script(:parse)
482
469
 
483
470
  if tok(/:/)
484
471
  res << ': '
485
472
  ss
486
473
  res << sass_script(:parse)
487
- elsif comparison1 = tok(/=|[<>]=?/)
488
- res << ' ' << comparison1 << ' '
489
- ss
490
- res << sass_script(:parse_until, stop_at)
491
- if ((comparison1 == ">" || comparison1 == ">=") && comparison2 = tok(/>=?/)) ||
492
- ((comparison1 == "<" || comparison1 == "<=") && comparison2 = tok(/<=?/))
493
- res << ' ' << comparison2 << ' '
494
- ss
495
- res << sass_script(:parse_until, stop_at)
496
- end
497
474
  end
498
475
  res << tok!(/\)/)
499
476
  ss
@@ -534,7 +511,7 @@ module Sass
534
511
 
535
512
  def moz_document_function
536
513
  val = interp_uri || _interp_string(:url_prefix) ||
537
- _interp_string(:domain) || function(false) || interpolation
514
+ _interp_string(:domain) || function(!:allow_var) || interpolation
538
515
  return unless val
539
516
  ss
540
517
  val
@@ -553,10 +530,10 @@ module Sass
553
530
  end
554
531
 
555
532
  def at_root_directive_list
556
- return unless (first = ident)
533
+ return unless (first = tok(IDENT))
557
534
  arr = [first]
558
535
  ss
559
- while (e = ident)
536
+ while (e = tok(IDENT))
560
537
  arr << e
561
538
  ss
562
539
  end
@@ -583,7 +560,7 @@ module Sass
583
560
  def supports_clause
584
561
  return unless tok(/supports\(/i)
585
562
  ss
586
- supports = import_supports_condition
563
+ supports = supports_condition
587
564
  ss
588
565
  tok!(/\)/)
589
566
  supports
@@ -593,10 +570,6 @@ module Sass
593
570
  supports_negation || supports_operator || supports_interpolation
594
571
  end
595
572
 
596
- def import_supports_condition
597
- supports_condition || supports_declaration
598
- end
599
-
600
573
  def supports_negation
601
574
  return unless tok(/not/i)
602
575
  ss
@@ -616,13 +589,6 @@ module Sass
616
589
  cond
617
590
  end
618
591
 
619
- def supports_declaration
620
- name = sass_script(:parse)
621
- tok!(/:/); ss
622
- value = sass_script(:parse)
623
- Sass::Supports::Declaration.new(name, value)
624
- end
625
-
626
592
  def supports_condition_in_parens
627
593
  interp = supports_interpolation
628
594
  return interp if interp
@@ -631,9 +597,11 @@ module Sass
631
597
  tok!(/\)/); ss
632
598
  cond
633
599
  else
634
- decl = supports_declaration
600
+ name = sass_script(:parse)
601
+ tok!(/:/); ss
602
+ value = sass_script(:parse)
635
603
  tok!(/\)/); ss
636
- decl
604
+ Sass::Supports::Declaration.new(name, value)
637
605
  end
638
606
  end
639
607
 
@@ -647,12 +615,12 @@ module Sass
647
615
  def variable
648
616
  return unless tok(/\$/)
649
617
  start_pos = source_position
650
- name = ident!
618
+ name = tok!(IDENT)
651
619
  ss; tok!(/:/); ss
652
620
 
653
621
  expr = sass_script(:parse)
654
622
  while tok(/!/)
655
- flag_name = ident!
623
+ flag_name = tok!(IDENT)
656
624
  if flag_name == 'default'
657
625
  guarded ||= true
658
626
  elsif flag_name == 'global'
@@ -672,15 +640,14 @@ module Sass
672
640
  # are disallowed by the CSS spec,
673
641
  # but they're included here for compatibility
674
642
  # with some proprietary MS properties
675
- str {ss if tok(%r{[/,:.=]})}
643
+ str {ss if tok(/[\/,:.=]/)}
676
644
  end
677
645
 
678
646
  def ruleset
679
647
  start_pos = source_position
680
648
  return unless (rules = almost_any_value)
681
- block(
682
- node(
683
- Sass::Tree::RuleNode.new(rules, range(start_pos)), start_pos), :ruleset)
649
+ block(node(
650
+ Sass::Tree::RuleNode.new(rules, range(start_pos)), start_pos), :ruleset)
684
651
  end
685
652
 
686
653
  def block(node, context)
@@ -755,9 +722,8 @@ module Sass
755
722
  selector << additional_selector
756
723
  end
757
724
 
758
- block(
759
- node(
760
- Sass::Tree::RuleNode.new(merge(selector), range(start_pos)), start_pos), :ruleset)
725
+ block(node(
726
+ Sass::Tree::RuleNode.new(merge(selector), range(start_pos)), start_pos), :ruleset)
761
727
  end
762
728
 
763
729
  # Tries to parse a declaration, and returns the value parsed so far if it
@@ -790,12 +756,6 @@ module Sass
790
756
  mid = [str {ss}]
791
757
  return name + mid unless tok(/:/)
792
758
  mid << ':'
793
-
794
- # If this is a CSS variable, parse it as a property no matter what.
795
- if name.first.is_a?(String) && name.first.start_with?("--")
796
- return css_variable_declaration(name, name_start_pos, name_end_pos)
797
- end
798
-
799
759
  return name + mid + [':'] if tok(/:/)
800
760
  mid << str {ss}
801
761
  post_colon_whitespace = !mid.last.empty?
@@ -831,7 +791,7 @@ module Sass
831
791
  ss
832
792
  require_block = tok?(/\{/)
833
793
 
834
- node = node(Sass::Tree::PropNode.new(name.flatten.compact, [value], :new),
794
+ node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new),
835
795
  name_start_pos, value_end_pos)
836
796
  node.name_source_range = range(name_start_pos, name_end_pos)
837
797
  node.value_source_range = range(value_start_pos, value_end_pos)
@@ -840,21 +800,13 @@ module Sass
840
800
  nested_properties! node
841
801
  end
842
802
 
843
- def css_variable_declaration(name, name_start_pos, name_end_pos)
844
- value_start_pos = source_position
845
- value = declaration_value
846
- value_end_pos = source_position
847
-
848
- node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new),
849
- name_start_pos, value_end_pos)
850
- node.name_source_range = range(name_start_pos, name_end_pos)
851
- node.value_source_range = range(value_start_pos, value_end_pos)
852
- node
853
- end
854
-
855
- # This production consumes values that could be a selector, an expression,
856
- # or a combination of both. It respects strings and comments and supports
857
- # interpolation. It will consume up to "{", "}", ";", or "!".
803
+ # This production is similar to the CSS [`<any-value>`][any-value]
804
+ # production, but as the name implies, not quite the same. It's meant to
805
+ # consume values that could be a selector, an expression, or a combination
806
+ # of both. It respects strings and comments and supports interpolation. It
807
+ # will consume up to "{", "}", ";", or "!".
808
+ #
809
+ # [any-value]: http://dev.w3.org/csswg/css-variables/#typedef-any-value
858
810
  #
859
811
  # Values consumed by this production will usually be parsed more
860
812
  # thoroughly once interpolation has been resolved.
@@ -874,9 +826,6 @@ module Sass
874
826
  |
875
827
  (?!url\()
876
828
  [^"'/\#!;\{\}] # "
877
- |
878
- # interp_uri will handle most url() calls, but not ones that take strings
879
- url\(#{W}(?=")
880
829
  |
881
830
  /(?![/*])
882
831
  |
@@ -888,60 +837,6 @@ module Sass
888
837
  interpolation(:warn_for_color)
889
838
  end
890
839
 
891
- def declaration_value(top_level: true)
892
- return unless (tok = declaration_value_token(top_level))
893
- value = [tok]
894
- while (tok = declaration_value_token(top_level))
895
- value << tok
896
- end
897
- merge(value)
898
- end
899
-
900
- def declaration_value_token(top_level)
901
- # This comes, more or less, from the [token consumption algorithm][].
902
- # However, since we don't have to worry about the token semantics, we
903
- # just consume everything until we come across a token with special
904
- # semantics.
905
- #
906
- # [token consumption algorithm]: https://drafts.csswg.org/css-syntax-3/#consume-token.
907
- result = tok(%r{
908
- (
909
- (?!
910
- url\(
911
- )
912
- [^()\[\]{}"'#/ \t\r\n\f#{top_level ? ";" : ""}]
913
- |
914
- \#(?!\{)
915
- |
916
- /(?!\*)
917
- )+
918
- }xi) || interp_string || interp_uri || interpolation || tok(COMMENT)
919
- return result if result
920
-
921
- # Fold together multiple characters of whitespace that don't include
922
- # newlines. The value only cares about the tokenization, so this is safe
923
- # as long as we don't delete whitespace entirely. It's important that we
924
- # fold here rather than post-processing, since we aren't allowed to fold
925
- # whitespace within strings and we lose that context later on.
926
- if (ws = tok(S))
927
- return ws.include?("\n") ? ws.gsub(/\A[^\n]*/, '') : ' '
928
- end
929
-
930
- if tok(/\(/)
931
- value = declaration_value(top_level: false)
932
- tok!(/\)/)
933
- ['(', *value, ')']
934
- elsif tok(/\[/)
935
- value = declaration_value(top_level: false)
936
- tok!(/\]/)
937
- ['[', *value, ']']
938
- elsif tok(/\{/)
939
- value = declaration_value(top_level: false)
940
- tok!(/\}/)
941
- ['{', *value, '}']
942
- end
943
- end
944
-
945
840
  def declaration
946
841
  # This allows the "*prop: val", ":prop: val", "#prop: val", and ".prop:
947
842
  # val" hacks.
@@ -967,7 +862,7 @@ module Sass
967
862
  ss
968
863
  require_block = tok?(/\{/)
969
864
 
970
- node = node(Sass::Tree::PropNode.new(name.flatten.compact, [value], :new),
865
+ node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new),
971
866
  name_start_pos, value_end_pos)
972
867
  node.name_source_range = range(name_start_pos, name_end_pos)
973
868
  node.value_source_range = range(value_start_pos, value_end_pos)
@@ -990,11 +885,8 @@ module Sass
990
885
  # we don't parse it at all, and instead return a plain old string
991
886
  # containing the value.
992
887
  # This results in a dramatic speed increase.
993
- if (val = tok(STATIC_VALUE))
994
- # If val ends with escaped whitespace, leave it be.
995
- str = Sass::Script::Tree::Literal.new(
996
- Sass::Script::Value::String.new(
997
- Sass::Util.strip_except_escapes(val)))
888
+ if (val = tok(STATIC_VALUE, true))
889
+ str = Sass::Script::Tree::Literal.new(Sass::Script::Value::String.new(val.strip))
998
890
  str.line = start_pos.line
999
891
  str.source_range = range(start_pos)
1000
892
  return str
@@ -1051,7 +943,7 @@ module Sass
1051
943
  def var_expr
1052
944
  return unless tok(/\$/)
1053
945
  line = @line
1054
- var = Sass::Script::Tree::Variable.new(ident!)
946
+ var = Sass::Script::Tree::Variable.new(tok!(IDENT))
1055
947
  var.line = line
1056
948
  var
1057
949
  end
@@ -1089,27 +981,11 @@ module Sass
1089
981
  res
1090
982
  end
1091
983
 
1092
- def ident
1093
- (ident = tok(IDENT)) && Sass::Util.normalize_ident_escapes(ident)
1094
- end
1095
-
1096
- def ident!
1097
- Sass::Util.normalize_ident_escapes(tok!(IDENT))
1098
- end
1099
-
1100
- def name
1101
- (name = tok(NAME)) && Sass::Util.normalize_ident_escapes(name)
1102
- end
1103
-
1104
- def name!
1105
- Sass::Util.normalize_ident_escapes(tok!(NAME))
1106
- end
1107
-
1108
- def interp_ident
1109
- val = ident || interpolation(:warn_for_color) || tok(IDENT_HYPHEN_INTERP)
984
+ def interp_ident(start = IDENT)
985
+ val = tok(start) || interpolation(:warn_for_color) || tok(IDENT_HYPHEN_INTERP, true)
1110
986
  return unless val
1111
987
  res = [val]
1112
- while (val = name || interpolation(:warn_for_color))
988
+ while (val = tok(NAME) || interpolation(:warn_for_color))
1113
989
  res << val
1114
990
  end
1115
991
  res
@@ -1123,7 +999,7 @@ module Sass
1123
999
  end
1124
1000
 
1125
1001
  def str
1126
- @strs.push String.new("")
1002
+ @strs.push ""
1127
1003
  yield
1128
1004
  @strs.last
1129
1005
  ensure
@@ -1151,7 +1027,8 @@ module Sass
1151
1027
  node
1152
1028
  end
1153
1029
 
1154
- @sass_script_parser = Sass::Script::Parser
1030
+ @sass_script_parser = Class.new(Sass::Script::Parser)
1031
+ @sass_script_parser.send(:include, ScriptParser)
1155
1032
 
1156
1033
  class << self
1157
1034
  # @private
@@ -1160,7 +1037,7 @@ module Sass
1160
1037
 
1161
1038
  def sass_script(*args)
1162
1039
  parser = self.class.sass_script_parser.new(@scanner, @line, @offset,
1163
- :filename => @filename, :importer => @importer, :allow_extra_text => true)
1040
+ :filename => @filename, :importer => @importer)
1164
1041
  result = parser.send(*args)
1165
1042
  unless @strs.empty?
1166
1043
  # Convert to CSS manually so that comments are ignored.
@@ -1185,7 +1062,7 @@ module Sass
1185
1062
  :media_expr => "media expression (e.g. (min-device-width: 800px))",
1186
1063
  :at_root_query => "@at-root query (e.g. (without: media))",
1187
1064
  :at_root_directive_list => '* or identifier',
1188
- :declaration_value => "expression (e.g. fr, 2n+1)",
1065
+ :pseudo_args => "expression (e.g. fr, 2n+1)",
1189
1066
  :interp_ident => "identifier",
1190
1067
  :qualified_name => "identifier",
1191
1068
  :expr => "expression (e.g. 1px, bold)",
@@ -1200,9 +1077,9 @@ module Sass
1200
1077
  :keyframes_selector => "keyframes selector (e.g. 10%)"
1201
1078
  }
1202
1079
 
1203
- TOK_NAMES = Hash[Sass::SCSS::RX.constants.map do |c|
1080
+ TOK_NAMES = Sass::Util.to_hash(Sass::SCSS::RX.constants.map do |c|
1204
1081
  [Sass::SCSS::RX.const_get(c), c.downcase]
1205
- end].merge(
1082
+ end).merge(
1206
1083
  IDENT => "identifier",
1207
1084
  /[;{}]/ => '";"',
1208
1085
  /\b(without|with)\b/ => '"with" or "without"'
@@ -1225,7 +1102,7 @@ module Sass
1225
1102
 
1226
1103
  unless name
1227
1104
  # Display basic regexps as plain old strings
1228
- source = rx.source.gsub(%r{\\/}, '/')
1105
+ source = rx.source.gsub(/\\\//, '/')
1229
1106
  string = rx.source.gsub(/\\(.)/, '\1')
1230
1107
  name = source == Regexp.escape(string) ? string.inspect : rx.inspect
1231
1108
  end
@@ -1256,20 +1133,14 @@ module Sass
1256
1133
  line = @line
1257
1134
  offset = @offset
1258
1135
  expected = @expected
1259
-
1260
- logger = Sass::Logger::Delayed.install!
1261
1136
  if catch(:_sass_parser_error) {yield; false}
1262
1137
  @scanner.pos = pos
1263
1138
  @line = line
1264
1139
  @offset = offset
1265
1140
  @expected = expected
1266
1141
  {:pos => pos, :line => line, :expected => @expected, :block => block}
1267
- else
1268
- logger.flush
1269
- nil
1270
1142
  end
1271
1143
  ensure
1272
- logger.uninstall! if logger
1273
1144
  @throw_error = old_throw_error
1274
1145
  end
1275
1146
 
@@ -1314,24 +1185,35 @@ module Sass
1314
1185
  # This is important because `#tok` is called all the time.
1315
1186
  NEWLINE = "\n"
1316
1187
 
1317
- def tok(rx)
1188
+ def tok(rx, last_group_lookahead = false)
1318
1189
  res = @scanner.scan(rx)
1190
+ if res
1191
+ # This fixes https://github.com/nex3/sass/issues/104, which affects
1192
+ # Ruby 1.8.7 and REE. This fix is to replace the ?= zero-width
1193
+ # positive lookahead operator in the Regexp (which matches without
1194
+ # consuming the matched group), with a match that does consume the
1195
+ # group, but then rewinds the scanner and removes the group from the
1196
+ # end of the matched string. This fix makes the assumption that the
1197
+ # matched group will always occur at the end of the match.
1198
+ if last_group_lookahead && @scanner[-1]
1199
+ @scanner.pos -= @scanner[-1].length
1200
+ res.slice!(-@scanner[-1].length..-1)
1201
+ end
1319
1202
 
1320
- return unless res
1321
-
1322
- newline_count = res.count(NEWLINE)
1323
- if newline_count > 0
1324
- @line += newline_count
1325
- @offset = res[res.rindex(NEWLINE)..-1].size
1326
- else
1327
- @offset += res.size
1328
- end
1203
+ newline_count = res.count(NEWLINE)
1204
+ if newline_count > 0
1205
+ @line += newline_count
1206
+ @offset = res[res.rindex(NEWLINE)..-1].size
1207
+ else
1208
+ @offset += res.size
1209
+ end
1329
1210
 
1330
- @expected = nil
1331
- if !@strs.empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT
1332
- @strs.each {|s| s << res}
1211
+ @expected = nil
1212
+ if !@strs.empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT
1213
+ @strs.each {|s| s << res}
1214
+ end
1215
+ res
1333
1216
  end
1334
- res
1335
1217
  end
1336
1218
 
1337
1219
  # Remove a vendor prefix from `str`.