sass 3.4.25 → 3.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +1 -1
  3. data/CONTRIBUTING.md +3 -3
  4. data/README.md +17 -9
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/extra/sass-spec-ref.sh +9 -1
  9. data/lib/sass.rb +0 -7
  10. data/lib/sass/cache_stores/filesystem.rb +1 -1
  11. data/lib/sass/css.rb +1 -2
  12. data/lib/sass/engine.rb +39 -29
  13. data/lib/sass/environment.rb +26 -5
  14. data/lib/sass/error.rb +2 -2
  15. data/lib/sass/exec/base.rb +2 -13
  16. data/lib/sass/exec/sass_scss.rb +1 -5
  17. data/lib/sass/features.rb +1 -0
  18. data/lib/sass/importers/filesystem.rb +6 -4
  19. data/lib/sass/logger/base.rb +11 -0
  20. data/lib/sass/plugin/compiler.rb +20 -50
  21. data/lib/sass/plugin/configuration.rb +2 -2
  22. data/lib/sass/railtie.rb +1 -1
  23. data/lib/sass/script/css_parser.rb +4 -1
  24. data/lib/sass/script/functions.rb +308 -81
  25. data/lib/sass/script/lexer.rb +63 -9
  26. data/lib/sass/script/parser.rb +287 -118
  27. data/lib/sass/script/tree/funcall.rb +35 -34
  28. data/lib/sass/script/tree/interpolation.rb +0 -3
  29. data/lib/sass/script/tree/list_literal.rb +23 -8
  30. data/lib/sass/script/tree/map_literal.rb +2 -2
  31. data/lib/sass/script/tree/node.rb +0 -8
  32. data/lib/sass/script/tree/operation.rb +1 -8
  33. data/lib/sass/script/value.rb +2 -0
  34. data/lib/sass/script/value/arg_list.rb +1 -1
  35. data/lib/sass/script/value/base.rb +17 -0
  36. data/lib/sass/script/value/callable.rb +25 -0
  37. data/lib/sass/script/value/color.rb +8 -2
  38. data/lib/sass/script/value/function.rb +19 -0
  39. data/lib/sass/script/value/helpers.rb +37 -11
  40. data/lib/sass/script/value/list.rb +35 -14
  41. data/lib/sass/script/value/map.rb +2 -2
  42. data/lib/sass/script/value/number.rb +3 -2
  43. data/lib/sass/scss/css_parser.rb +6 -1
  44. data/lib/sass/scss/parser.rb +145 -56
  45. data/lib/sass/scss/rx.rb +5 -11
  46. data/lib/sass/scss/static_parser.rb +20 -42
  47. data/lib/sass/selector.rb +4 -0
  48. data/lib/sass/selector/abstract_sequence.rb +7 -6
  49. data/lib/sass/selector/comma_sequence.rb +9 -5
  50. data/lib/sass/selector/pseudo.rb +20 -3
  51. data/lib/sass/selector/sequence.rb +35 -10
  52. data/lib/sass/selector/simple.rb +9 -2
  53. data/lib/sass/selector/simple_sequence.rb +8 -4
  54. data/lib/sass/source/map.rb +2 -6
  55. data/lib/sass/stack.rb +21 -1
  56. data/lib/sass/tree/charset_node.rb +1 -1
  57. data/lib/sass/tree/prop_node.rb +45 -53
  58. data/lib/sass/tree/rule_node.rb +6 -8
  59. data/lib/sass/tree/visitors/check_nesting.rb +1 -1
  60. data/lib/sass/tree/visitors/convert.rb +2 -3
  61. data/lib/sass/tree/visitors/cssize.rb +4 -15
  62. data/lib/sass/tree/visitors/deep_copy.rb +1 -1
  63. data/lib/sass/tree/visitors/extend.rb +2 -8
  64. data/lib/sass/tree/visitors/perform.rb +23 -15
  65. data/lib/sass/tree/visitors/set_options.rb +1 -1
  66. data/lib/sass/tree/visitors/to_css.rb +49 -22
  67. data/lib/sass/util.rb +72 -310
  68. data/lib/sass/util/multibyte_string_scanner.rb +127 -131
  69. data/lib/sass/util/normalized_map.rb +1 -8
  70. data/lib/sass/version.rb +0 -4
  71. metadata +55 -202
  72. data/Rakefile +0 -453
  73. data/lib/sass/script/css_variable_warning.rb +0 -52
  74. data/lib/sass/util/cross_platform_random.rb +0 -19
  75. data/lib/sass/util/ordered_hash.rb +0 -192
  76. data/test/sass-spec.yml +0 -3
  77. data/test/sass/cache_test.rb +0 -131
  78. data/test/sass/callbacks_test.rb +0 -61
  79. data/test/sass/compiler_test.rb +0 -236
  80. data/test/sass/conversion_test.rb +0 -2188
  81. data/test/sass/css2sass_test.rb +0 -526
  82. data/test/sass/css_variable_test.rb +0 -132
  83. data/test/sass/data/hsl-rgb.txt +0 -319
  84. data/test/sass/encoding_test.rb +0 -219
  85. data/test/sass/engine_test.rb +0 -3447
  86. data/test/sass/exec_test.rb +0 -96
  87. data/test/sass/extend_test.rb +0 -1733
  88. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  89. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  90. data/test/sass/functions_test.rb +0 -1977
  91. data/test/sass/importer_test.rb +0 -421
  92. data/test/sass/logger_test.rb +0 -58
  93. data/test/sass/mock_importer.rb +0 -49
  94. data/test/sass/more_results/more1.css +0 -9
  95. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  96. data/test/sass/more_results/more_import.css +0 -29
  97. data/test/sass/more_templates/_more_partial.sass +0 -2
  98. data/test/sass/more_templates/more1.sass +0 -23
  99. data/test/sass/more_templates/more_import.sass +0 -11
  100. data/test/sass/plugin_test.rb +0 -556
  101. data/test/sass/results/alt.css +0 -4
  102. data/test/sass/results/basic.css +0 -9
  103. data/test/sass/results/cached_import_option.css +0 -3
  104. data/test/sass/results/compact.css +0 -5
  105. data/test/sass/results/complex.css +0 -86
  106. data/test/sass/results/compressed.css +0 -1
  107. data/test/sass/results/expanded.css +0 -19
  108. data/test/sass/results/filename_fn.css +0 -3
  109. data/test/sass/results/if.css +0 -3
  110. data/test/sass/results/import.css +0 -31
  111. data/test/sass/results/import_charset.css +0 -5
  112. data/test/sass/results/import_charset_1_8.css +0 -5
  113. data/test/sass/results/import_charset_ibm866.css +0 -5
  114. data/test/sass/results/import_content.css +0 -1
  115. data/test/sass/results/line_numbers.css +0 -49
  116. data/test/sass/results/mixins.css +0 -95
  117. data/test/sass/results/multiline.css +0 -24
  118. data/test/sass/results/nested.css +0 -22
  119. data/test/sass/results/options.css +0 -1
  120. data/test/sass/results/parent_ref.css +0 -13
  121. data/test/sass/results/script.css +0 -16
  122. data/test/sass/results/scss_import.css +0 -31
  123. data/test/sass/results/scss_importee.css +0 -2
  124. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  125. data/test/sass/results/subdir/subdir.css +0 -3
  126. data/test/sass/results/units.css +0 -11
  127. data/test/sass/results/warn.css +0 -0
  128. data/test/sass/results/warn_imported.css +0 -0
  129. data/test/sass/script_conversion_test.rb +0 -357
  130. data/test/sass/script_test.rb +0 -1431
  131. data/test/sass/scss/css_test.rb +0 -1281
  132. data/test/sass/scss/rx_test.rb +0 -160
  133. data/test/sass/scss/scss_test.rb +0 -4205
  134. data/test/sass/scss/test_helper.rb +0 -37
  135. data/test/sass/source_map_test.rb +0 -1055
  136. data/test/sass/superselector_test.rb +0 -210
  137. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  138. data/test/sass/templates/_double_import_loop2.sass +0 -1
  139. data/test/sass/templates/_filename_fn_import.scss +0 -11
  140. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  141. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  142. data/test/sass/templates/_imported_content.sass +0 -3
  143. data/test/sass/templates/_partial.sass +0 -2
  144. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/alt.sass +0 -16
  146. data/test/sass/templates/basic.sass +0 -23
  147. data/test/sass/templates/bork1.sass +0 -2
  148. data/test/sass/templates/bork2.sass +0 -2
  149. data/test/sass/templates/bork3.sass +0 -2
  150. data/test/sass/templates/bork4.sass +0 -2
  151. data/test/sass/templates/bork5.sass +0 -3
  152. data/test/sass/templates/cached_import_option.scss +0 -3
  153. data/test/sass/templates/compact.sass +0 -17
  154. data/test/sass/templates/complex.sass +0 -305
  155. data/test/sass/templates/compressed.sass +0 -15
  156. data/test/sass/templates/double_import_loop1.sass +0 -1
  157. data/test/sass/templates/expanded.sass +0 -17
  158. data/test/sass/templates/filename_fn.scss +0 -18
  159. data/test/sass/templates/if.sass +0 -11
  160. data/test/sass/templates/import.sass +0 -12
  161. data/test/sass/templates/import_charset.sass +0 -9
  162. data/test/sass/templates/import_charset_1_8.sass +0 -6
  163. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  164. data/test/sass/templates/import_content.sass +0 -4
  165. data/test/sass/templates/importee.less +0 -2
  166. data/test/sass/templates/importee.sass +0 -19
  167. data/test/sass/templates/line_numbers.sass +0 -13
  168. data/test/sass/templates/mixin_bork.sass +0 -5
  169. data/test/sass/templates/mixins.sass +0 -76
  170. data/test/sass/templates/multiline.sass +0 -20
  171. data/test/sass/templates/nested.sass +0 -25
  172. data/test/sass/templates/nested_bork1.sass +0 -2
  173. data/test/sass/templates/nested_bork2.sass +0 -2
  174. data/test/sass/templates/nested_bork3.sass +0 -2
  175. data/test/sass/templates/nested_bork4.sass +0 -2
  176. data/test/sass/templates/nested_import.sass +0 -2
  177. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  178. data/test/sass/templates/options.sass +0 -2
  179. data/test/sass/templates/parent_ref.sass +0 -25
  180. data/test/sass/templates/same_name_different_ext.sass +0 -2
  181. data/test/sass/templates/same_name_different_ext.scss +0 -1
  182. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  183. data/test/sass/templates/script.sass +0 -101
  184. data/test/sass/templates/scss_import.scss +0 -12
  185. data/test/sass/templates/scss_importee.scss +0 -1
  186. data/test/sass/templates/single_import_loop.sass +0 -1
  187. data/test/sass/templates/subdir/import_up1.scss +0 -1
  188. data/test/sass/templates/subdir/import_up2.scss +0 -1
  189. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  190. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  191. data/test/sass/templates/subdir/subdir.sass +0 -6
  192. data/test/sass/templates/units.sass +0 -11
  193. data/test/sass/templates/warn.sass +0 -3
  194. data/test/sass/templates/warn_imported.sass +0 -4
  195. data/test/sass/test_helper.rb +0 -8
  196. data/test/sass/util/multibyte_string_scanner_test.rb +0 -155
  197. data/test/sass/util/normalized_map_test.rb +0 -51
  198. data/test/sass/util/subset_map_test.rb +0 -91
  199. data/test/sass/util_test.rb +0 -438
  200. data/test/sass/value_helpers_test.rb +0 -179
  201. data/test/test_helper.rb +0 -110
  202. data/vendor/listen/CHANGELOG.md +0 -1
  203. data/vendor/listen/CONTRIBUTING.md +0 -38
  204. data/vendor/listen/Gemfile +0 -20
  205. data/vendor/listen/Guardfile +0 -8
  206. data/vendor/listen/LICENSE +0 -20
  207. data/vendor/listen/README.md +0 -349
  208. data/vendor/listen/Rakefile +0 -5
  209. data/vendor/listen/Vagrantfile +0 -96
  210. data/vendor/listen/lib/listen.rb +0 -54
  211. data/vendor/listen/lib/listen/adapter.rb +0 -327
  212. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -75
  213. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -48
  214. data/vendor/listen/lib/listen/adapters/linux.rb +0 -81
  215. data/vendor/listen/lib/listen/adapters/polling.rb +0 -58
  216. data/vendor/listen/lib/listen/adapters/windows.rb +0 -91
  217. data/vendor/listen/lib/listen/directory_record.rb +0 -406
  218. data/vendor/listen/lib/listen/listener.rb +0 -323
  219. data/vendor/listen/lib/listen/turnstile.rb +0 -32
  220. data/vendor/listen/lib/listen/version.rb +0 -3
  221. data/vendor/listen/listen.gemspec +0 -28
  222. data/vendor/listen/spec/listen/adapter_spec.rb +0 -149
  223. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  224. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  225. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  226. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  227. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  228. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1250
  229. data/vendor/listen/spec/listen/listener_spec.rb +0 -258
  230. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  231. data/vendor/listen/spec/listen_spec.rb +0 -67
  232. data/vendor/listen/spec/spec_helper.rb +0 -25
  233. data/vendor/listen/spec/support/adapter_helper.rb +0 -666
  234. data/vendor/listen/spec/support/directory_record_helper.rb +0 -57
  235. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  236. data/vendor/listen/spec/support/listeners_helper.rb +0 -179
  237. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -163,7 +163,7 @@ module Sass
163
163
  next sel if seen.include?([sel])
164
164
  extended = sel.selector.do_extend(extends, parent_directives, replace, seen, false)
165
165
  next sel if extended == sel.selector
166
- extended.members.reject! {|seq| seq.has_placeholder?}
166
+ extended.members.reject! {|seq| seq.invisible?}
167
167
 
168
168
  # For `:not()`, we usually want to get rid of any complex
169
169
  # selectors because that will cause the selector to fail to
@@ -184,17 +184,16 @@ module Sass
184
184
  result
185
185
  end.flatten
186
186
 
187
- groups = Sass::Util.group_by_to_a(extends[members.to_set]) {|ex| ex.extender}
187
+ groups = extends[members.to_set].group_by {|ex| ex.extender}.to_a
188
188
  groups.map! do |seq, group|
189
189
  sels = group.map {|e| e.target}.flatten
190
190
  # If A {@extend B} and C {...},
191
191
  # seq is A, sels is B, and self is C
192
192
 
193
193
  self_without_sel = Sass::Util.array_minus(members, sels)
194
- group.each {|e| e.result = :failed_to_unify unless e.result == :succeeded}
194
+ group.each {|e| e.success = true}
195
195
  unified = seq.members.last.unify(SimpleSequence.new(self_without_sel, subject?))
196
196
  next unless unified
197
- group.each {|e| e.result = :succeeded}
198
197
  group.each {|e| check_directives_match!(e, parent_directives)}
199
198
  new_seq = Sequence.new(seq.members[0...-1] + [unified])
200
199
  new_seq.add_sources!(sources + [seq])
@@ -287,6 +286,11 @@ module Sass
287
286
  # @see Simple#to_s
288
287
  def to_s(opts = {})
289
288
  res = @members.map {|m| m.to_s(opts)}.join
289
+
290
+ # :not(%foo) may resolve to the empty string, but it should match every
291
+ # selector so we replace it with "*".
292
+ res = '*' if res.empty?
293
+
290
294
  res << '!' if subject?
291
295
  res
292
296
  end
@@ -84,8 +84,6 @@ module Sass::Source
84
84
  # @return [String] The JSON string.
85
85
  # @raise [ArgumentError] If neither `:css_uri` nor `:css_path` and
86
86
  # `:sourcemap_path` are specified.
87
- # @comment
88
- # rubocop:disable MethodLength
89
87
  def to_json(options)
90
88
  css_uri, css_path, sourcemap_path =
91
89
  options[:css_uri], options[:css_path], options[:sourcemap_path]
@@ -93,8 +91,8 @@ module Sass::Source
93
91
  raise ArgumentError.new("Sass::Source::Map#to_json requires either " \
94
92
  "the :css_uri option or both the :css_path and :soucemap_path options.")
95
93
  end
96
- css_path &&= Sass::Util.pathname(Sass::Util.absolute_path(css_path))
97
- sourcemap_path &&= Sass::Util.pathname(Sass::Util.absolute_path(sourcemap_path))
94
+ css_path &&= Sass::Util.pathname(File.absolute_path(css_path))
95
+ sourcemap_path &&= Sass::Util.pathname(File.absolute_path(sourcemap_path))
98
96
  css_uri ||= Sass::Util.file_uri_from_path(
99
97
  Sass::Util.relative_path_from(css_path, sourcemap_path.dirname))
100
98
 
@@ -197,8 +195,6 @@ module Sass::Source
197
195
  result << "\n}"
198
196
  result
199
197
  end
200
- # @comment
201
- # rubocop:enable MethodLength
202
198
 
203
199
  private
204
200
 
@@ -98,8 +98,28 @@ module Sass
98
98
  with_frame(filename, line, :mixin, name) {yield}
99
99
  end
100
100
 
101
+ # Pushes a function frame onto the stack.
102
+ #
103
+ # @param filename [String] See \{Frame#filename}.
104
+ # @param line [String] See \{Frame#line}.
105
+ # @param name [String] See \{Frame#name}.
106
+ # @yield [] A block in which the new frame is on the stack.
107
+ def with_function(filename, line, name)
108
+ with_frame(filename, line, :function, name) {yield}
109
+ end
110
+
111
+ # Pushes a function frame onto the stack.
112
+ #
113
+ # @param filename [String] See \{Frame#filename}.
114
+ # @param line [String] See \{Frame#line}.
115
+ # @param name [String] See \{Frame#name}.
116
+ # @yield [] A block in which the new frame is on the stack.
117
+ def with_directive(filename, line, name)
118
+ with_frame(filename, line, :directive, name) {yield}
119
+ end
120
+
101
121
  def to_s
102
- Sass::Util.enum_with_index(Sass::Util.enum_cons(frames.reverse + [nil], 2)).
122
+ (frames.reverse + [nil]).each_cons(2).each_with_index.
103
123
  map do |(frame, caller), i|
104
124
  "#{i == 0 ? 'on' : 'from'} line #{frame.line}" +
105
125
  " of #{frame.filename || 'an unknown file'}" +
@@ -16,7 +16,7 @@ module Sass::Tree
16
16
 
17
17
  # @see Node#invisible?
18
18
  def invisible?
19
- !Sass::Util.ruby1_8?
19
+ true
20
20
  end
21
21
  end
22
22
  end
@@ -20,7 +20,11 @@ module Sass::Tree
20
20
 
21
21
  # The value of the property.
22
22
  #
23
- # @return [Sass::Script::Tree::Node]
23
+ # For most properties, this will just contain a single Node. However, for
24
+ # CSS variables, it will contain multiple strings and nodes representing
25
+ # interpolation. Any adjacent strings will be merged together.
26
+ #
27
+ # @return [Array<String, Sass::Script::Tree::Node>]
24
28
  attr_accessor :value
25
29
 
26
30
  # The value of the property
@@ -52,14 +56,22 @@ module Sass::Tree
52
56
  # @return [Sass::Source::Range]
53
57
  attr_accessor :value_source_range
54
58
 
59
+ # Whether this represents a CSS custom property.
60
+ #
61
+ # @return [Boolean]
62
+ def custom_property?
63
+ name.first.is_a?(String) && name.first.start_with?("--")
64
+ end
65
+
55
66
  # @param name [Array<String, Sass::Script::Tree::Node>] See \{#name}
56
- # @param value [Sass::Script::Tree::Node] See \{#value}
67
+ # @param value [Array<String, Sass::Script::Tree::Node>] See \{#value}
57
68
  # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
58
69
  # `:old` if it uses `:a b`-style syntax
59
70
  def initialize(name, value, prop_syntax)
60
71
  @name = Sass::Util.strip_string_array(
61
72
  Sass::Util.merge_adjacent_strings(name))
62
- @value = value
73
+ @value = Sass::Util.merge_adjacent_strings(value)
74
+ @value = Sass::Util.strip_string_array(@value) unless custom_property?
63
75
  @tabs = 0
64
76
  @prop_syntax = prop_syntax
65
77
  super()
@@ -81,9 +93,10 @@ module Sass::Tree
81
93
  # @return [String] The message
82
94
  def pseudo_class_selector_message
83
95
  if @prop_syntax == :new ||
84
- !value.is_a?(Sass::Script::Tree::Literal) ||
85
- !value.value.is_a?(Sass::Script::Value::String) ||
86
- !value.value.value.empty?
96
+ custom_property? ||
97
+ !value.first.is_a?(Sass::Script::Tree::Literal) ||
98
+ !value.first.value.is_a?(Sass::Script::Value::String) ||
99
+ !value.first.value.value.empty?
87
100
  return ""
88
101
  end
89
102
 
@@ -98,73 +111,52 @@ module Sass::Tree
98
111
  # @param fmt [Symbol] `:scss` or `:sass`.
99
112
  def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
100
113
  name = self.name.map {|n| n.is_a?(String) ? n : n.to_sass(opts)}.join
114
+ value = self.value.map {|n| n.is_a?(String) ? n : n.to_sass(opts)}.join
115
+ value = "(#{value})" if value_needs_parens?
116
+
101
117
  if name[0] == ?:
102
- raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\"" +
118
+ raise Sass::SyntaxError.new("The \"#{name}: #{value}\"" +
103
119
  " hack is not allowed in the Sass indented syntax")
104
120
  end
105
121
 
122
+ # The indented syntax doesn't support newlines in custom property values,
123
+ # but we can losslessly convert them to spaces instead.
124
+ value = value.tr("\n", " ") if fmt == :sass
125
+
106
126
  old = opts[:old] && fmt == :sass
107
- initial = old ? ':' : ''
108
- mid = old ? '' : ':'
109
- "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
127
+ "#{old ? ':' : ''}#{name}#{old ? '' : ':'}#{custom_property? ? '' : ' '}#{value}".rstrip
110
128
  end
111
129
 
112
130
  # A property node is invisible if its value is empty.
113
131
  #
114
132
  # @return [Boolean]
115
133
  def invisible?
116
- resolved_value.empty?
134
+ !custom_property? && resolved_value.empty?
117
135
  end
118
136
 
119
137
  private
120
138
 
139
+ # Returns whether \{#value} neesd parentheses in order to be parsed
140
+ # properly as division.
141
+ def value_needs_parens?
142
+ return false if custom_property?
143
+
144
+ root = value.first
145
+ root.is_a?(Sass::Script::Tree::Operation) &&
146
+ root.operator == :div &&
147
+ root.operand1.is_a?(Sass::Script::Tree::Literal) &&
148
+ root.operand1.value.is_a?(Sass::Script::Value::Number) &&
149
+ root.operand1.value.original.nil? &&
150
+ root.operand2.is_a?(Sass::Script::Tree::Literal) &&
151
+ root.operand2.value.is_a?(Sass::Script::Value::Number) &&
152
+ root.operand2.value.original.nil?
153
+ end
154
+
121
155
  def check!
122
156
  return unless @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
123
157
  raise Sass::SyntaxError.new(
124
158
  "Illegal property syntax: can't use #{@prop_syntax} syntax when " +
125
159
  ":property_syntax => #{@options[:property_syntax].inspect} is set.")
126
160
  end
127
-
128
- class << self
129
- # @private
130
- def val_to_sass(value, opts)
131
- val_to_sass_comma(value, opts).to_sass(opts)
132
- end
133
-
134
- private
135
-
136
- def val_to_sass_comma(node, opts)
137
- return node unless node.is_a?(Sass::Script::Tree::Operation)
138
- return val_to_sass_concat(node, opts) unless node.operator == :comma
139
-
140
- Sass::Script::Tree::Operation.new(
141
- val_to_sass_concat(node.operand1, opts),
142
- val_to_sass_comma(node.operand2, opts),
143
- node.operator)
144
- end
145
-
146
- def val_to_sass_concat(node, opts)
147
- return node unless node.is_a?(Sass::Script::Tree::Operation)
148
- return val_to_sass_div(node, opts) unless node.operator == :space
149
-
150
- Sass::Script::Tree::Operation.new(
151
- val_to_sass_div(node.operand1, opts),
152
- val_to_sass_concat(node.operand2, opts),
153
- node.operator)
154
- end
155
-
156
- def val_to_sass_div(node, opts)
157
- unless node.is_a?(Sass::Script::Tree::Operation) && node.operator == :div &&
158
- node.operand1.is_a?(Sass::Script::Tree::Literal) &&
159
- node.operand1.value.is_a?(Sass::Script::Value::Number) &&
160
- node.operand2.is_a?(Sass::Script::Tree::Literal) &&
161
- node.operand2.value.is_a?(Sass::Script::Value::Number) &&
162
- (!node.operand1.value.original || !node.operand2.value.original)
163
- return node
164
- end
165
-
166
- Sass::Script::Value::String.new("(#{node.to_sass(opts)})")
167
- end
168
- end
169
161
  end
170
162
  end
@@ -120,13 +120,14 @@ module Sass::Tree
120
120
  #
121
121
  # @return [{#to_s => #to_s}]
122
122
  def debug_info
123
- {:filename => filename && ("file://" + Sass::Util.escape_uri(File.expand_path(filename))),
123
+ {:filename => filename &&
124
+ ("file://" + URI::DEFAULT_PARSER.escape(File.expand_path(filename))),
124
125
  :line => line}
125
126
  end
126
127
 
127
128
  # A rule node is invisible if it has only placeholder selectors.
128
129
  def invisible?
129
- resolved_rules.members.all? {|seq| seq.has_placeholder?}
130
+ resolved_rules.members.all? {|seq| seq.invisible?}
130
131
  end
131
132
 
132
133
  private
@@ -138,13 +139,10 @@ module Sass::Tree
138
139
  # We don't use real filename/line info because we don't have it yet.
139
140
  # When we get it, we'll set it on the parsed rules if possible.
140
141
  parser = nil
141
- warnings = Sass::Util.silence_warnings do
142
- parser = Sass::SCSS::StaticParser.new(@rule.join.strip, nil, nil, 1)
143
- # rubocop:disable RescueModifier
142
+ warnings = Sass.logger.capture do
143
+ parser = Sass::SCSS::StaticParser.new(
144
+ Sass::Util.strip_except_escapes(@rule.join), nil, nil, 1)
144
145
  @parsed_rules = parser.parse_selector rescue nil
145
- # rubocop:enable RescueModifier
146
-
147
- $stderr.string
148
146
  end
149
147
 
150
148
  # If parsing produces a warning, throw away the result so we can parse
@@ -31,7 +31,7 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
31
31
  if parent.is_a?(Sass::Tree::AtRootNode) && parent.resolved_value
32
32
  old_parents = @parents
33
33
  @parents = @parents.reject {|p| parent.exclude_node?(p)}
34
- @parent = Sass::Util.enum_with_index(@parents.reverse).
34
+ @parent = @parents.reverse.each_with_index.
35
35
  find {|p, i| !transparent_parent?(p, @parents[-i - 2])}.first
36
36
 
37
37
  begin
@@ -203,8 +203,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
203
203
 
204
204
  unless node.args.empty? && node.keywords.empty? && node.splat.nil?
205
205
  args = node.args.map(&arg_to_sass)
206
- keywords = Sass::Util.hash_to_a(node.keywords.as_stored).
207
- map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
206
+ keywords = node.keywords.as_stored.to_a.map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
208
207
 
209
208
  if node.splat
210
209
  splat = "#{arg_to_sass[node.splat]}..."
@@ -281,7 +280,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
281
280
  # Visit rule-level nodes and return their conversion with appropriate
282
281
  # whitespace added.
283
282
  def visit_rule_level(nodes)
284
- Sass::Util.enum_cons(nodes + [nil], 2).map do |child, nxt|
283
+ (nodes + [nil]).each_cons(2).map do |child, nxt|
285
284
  visit(child) +
286
285
  if nxt &&
287
286
  (child.is_a?(Sass::Tree::CommentNode) && child.line + child.lines + 1 == nxt.line) ||
@@ -56,8 +56,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
56
56
  @parents.pop
57
57
  end
58
58
 
59
- # In Ruby 1.8, ensures that there's only one `@charset` directive
60
- # and that it's at the top of the document.
59
+ # Converts the entire document to CSS.
61
60
  #
62
61
  # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
63
62
  # *and* the extensions defined for this tree
@@ -65,14 +64,6 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
65
64
  yield
66
65
 
67
66
  if parent.nil?
68
- # In Ruby 1.9 we can make all @charset nodes invisible
69
- # and infer the final @charset from the encoding of the final string.
70
- if Sass::Util.ruby1_8?
71
- charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
72
- node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
73
- node.children.unshift charset if charset
74
- end
75
-
76
67
  imports_to_move = []
77
68
  import_limit = nil
78
69
  i = -1
@@ -115,11 +106,9 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
115
106
  # @attr node [Sass::Tree::ExtendNode] The node that produced this extend.
116
107
  # @attr directives [Array<Sass::Tree::DirectiveNode>]
117
108
  # The directives containing the `@extend`.
118
- # @attr result [Symbol]
119
- # The result of this extend. One of `:not_found` (the target doesn't exist
120
- # in the document), `:failed_to_unify` (the target exists but cannot be
121
- # unified with the extender), or `:succeeded`.
122
- Extend = Struct.new(:extender, :target, :node, :directives, :result)
109
+ # @attr success [Boolean]
110
+ # Whether this extend successfully matched a selector.
111
+ Extend = Struct.new(:extender, :target, :node, :directives, :success)
123
112
 
124
113
  # Registers an extension in the `@extends` subset map.
125
114
  def visit_extend(node)
@@ -61,7 +61,7 @@ class Sass::Tree::Visitors::DeepCopy < Sass::Tree::Visitors::Base
61
61
 
62
62
  def visit_prop(node)
63
63
  node.name = node.name.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
64
- node.value = node.value.deep_copy
64
+ node.value = node.value.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
65
65
  yield
66
66
  end
67
67
 
@@ -49,19 +49,13 @@ class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
49
49
 
50
50
  def check_extends_fired!(extends)
51
51
  extends.each_value do |ex|
52
- next if ex.result == :succeeded || ex.node.optional?
52
+ next if ex.success || ex.node.optional?
53
53
  message = "\"#{ex.extender}\" failed to @extend \"#{ex.target.join}\"."
54
- reason =
55
- if ex.result == :not_found
56
- "The selector \"#{ex.target.join}\" was not found."
57
- else
58
- "No selectors matching \"#{ex.target.join}\" could be unified with \"#{ex.extender}\"."
59
- end
60
54
 
61
55
  # TODO(nweiz): this should use the Sass stack trace of the extend node.
62
56
  raise Sass::SyntaxError.new(<<MESSAGE, :filename => ex.node.filename, :line => ex.node.line)
63
57
  #{message}
64
- #{reason}
58
+ The selector "#{ex.target.join}" was not found.
65
59
  Use "@extend #{ex.target.join} !optional" if the extend should be able to fail.
66
60
  MESSAGE
67
61
  end
@@ -11,8 +11,6 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
11
11
  end
12
12
 
13
13
  # @api private
14
- # @comment
15
- # rubocop:disable MethodLength
16
14
  def perform_arguments(callable, args, splat, environment)
17
15
  desc = "#{callable.type.capitalize} #{callable.name}"
18
16
  downcase_desc = "#{callable.type} #{callable.name}"
@@ -145,8 +143,6 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
145
143
  end
146
144
  end
147
145
  end
148
- # @comment
149
- # rubocop:enable MethodLength
150
146
 
151
147
  protected
152
148
 
@@ -290,7 +286,7 @@ WARNING
290
286
 
291
287
  @environment.set_local_function(node.name,
292
288
  Sass::Callable.new(node.name, node.args, node.splat, env,
293
- node.children, false, "function"))
289
+ node.children, false, "function", :stylesheet))
294
290
  []
295
291
  end
296
292
 
@@ -341,7 +337,7 @@ WARNING
341
337
  env = Sass::Environment.new(@environment, node.options)
342
338
  @environment.set_local_mixin(node.name,
343
339
  Sass::Callable.new(node.name, node.args, node.splat, env,
344
- node.children, node.has_content, "mixin"))
340
+ node.children, node.has_content, "mixin", :stylesheet))
345
341
  []
346
342
  end
347
343
 
@@ -351,7 +347,7 @@ WARNING
351
347
  mixin = @environment.mixin(node.name)
352
348
  raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin
353
349
 
354
- if node.children.any? && !mixin.has_content
350
+ if node.has_children && !mixin.has_content
355
351
  raise Sass::SyntaxError.new(%(Mixin "#{node.name}" does not accept a content block.))
356
352
  end
357
353
 
@@ -395,9 +391,19 @@ WARNING
395
391
  # Runs any SassScript that may be embedded in a property.
396
392
  def visit_prop(node)
397
393
  node.resolved_name = run_interp(node.name)
398
- val = node.value.perform(@environment)
399
- node.resolved_value = val.to_s
400
- node.value_source_range = val.source_range if val.source_range
394
+
395
+ # If the node's value is just a variable or similar, we may get a useful
396
+ # source range from evaluating it.
397
+ if node.value.length == 1 && node.value.first.is_a?(Sass::Script::Tree::Node)
398
+ result = node.value.first.perform(@environment)
399
+ node.resolved_value = result.to_s
400
+ node.value_source_range = result.source_range if result.source_range
401
+ elsif node.custom_property?
402
+ node.resolved_value = run_interp_no_strip(node.value)
403
+ else
404
+ node.resolved_value = run_interp(node.value)
405
+ end
406
+
401
407
  yield
402
408
  end
403
409
 
@@ -483,9 +489,11 @@ WARNING
483
489
  def visit_warn(node)
484
490
  res = node.expr.perform(@environment)
485
491
  res = res.value if res.is_a?(Sass::Script::Value::String)
486
- msg = "WARNING: #{res}\n "
487
- msg << @environment.stack.to_s.gsub("\n", "\n ") << "\n"
488
- Sass::Util.sass_warn msg
492
+ @environment.stack.with_directive(node.filename, node.line, "@warn") do
493
+ msg = "WARNING: #{res}\n "
494
+ msg << @environment.stack.to_s.gsub("\n", "\n ") << "\n"
495
+ Sass::Util.sass_warn msg
496
+ end
489
497
  []
490
498
  end
491
499
 
@@ -545,7 +553,7 @@ WARNING
545
553
  end
546
554
 
547
555
  def run_interp(text)
548
- run_interp_no_strip(text).strip
556
+ Sass::Util.strip_except_escapes(run_interp_no_strip(text))
549
557
  end
550
558
 
551
559
  def handle_import_loop!(node)
@@ -556,7 +564,7 @@ WARNING
556
564
  end
557
565
 
558
566
  files << node.filename << node.imported_file.options[:filename]
559
- msg << "\n" << Sass::Util.enum_cons(files, 2).map do |m1, m2|
567
+ msg << "\n" << files.each_cons(2).map do |m1, m2|
560
568
  " #{m1} imports #{m2}"
561
569
  end.join("\n")
562
570
  raise Sass::SyntaxError.new(msg)