sass 3.7.4 → 4.0.0.alpha.1

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 (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
@@ -98,31 +98,11 @@ 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
-
121
101
  def to_s
122
- (frames.reverse + [nil]).each_cons(2).each_with_index.
102
+ Sass::Util.enum_with_index(Sass::Util.enum_cons(frames.reverse + [nil], 2)).
123
103
  map do |(frame, caller), i|
124
- "#{i == 0 ? 'on' : 'from'} line #{frame.line}" +
125
- " of #{frame.filename || 'an unknown file'}" +
104
+ "#{i == 0 ? "on" : "from"} line #{frame.line}" +
105
+ " of #{frame.filename || "an unknown file"}" +
126
106
  (caller && caller.name ? ", in `#{caller.name}'" : "")
127
107
  end.join("\n")
128
108
  end
@@ -16,7 +16,7 @@ module Sass::Tree
16
16
 
17
17
  # @see Node#invisible?
18
18
  def invisible?
19
- true
19
+ !Sass::Util.ruby1_8?
20
20
  end
21
21
  end
22
22
  end
@@ -59,7 +59,7 @@ module Sass::Tree
59
59
 
60
60
  # Returns the number of lines in the comment.
61
61
  #
62
- # @return [Integer]
62
+ # @return [Fixnum]
63
63
  def lines
64
64
  @value.inject(0) do |s, e|
65
65
  next s + e.count("\n") if e.is_a?(String)
@@ -36,8 +36,9 @@ module Sass
36
36
  @splat = splat
37
37
  super()
38
38
 
39
- return unless %w(and or not).include?(name)
40
- raise Sass::SyntaxError.new("Invalid function name \"#{name}\".")
39
+ if %w[and or not].include?(name)
40
+ raise Sass::SyntaxError.new("Invalid function name \"#{name}\".")
41
+ end
41
42
  end
42
43
  end
43
44
  end
@@ -69,7 +69,7 @@ module Sass
69
69
 
70
70
  # The line of the document on which this node appeared.
71
71
  #
72
- # @return [Integer]
72
+ # @return [Fixnum]
73
73
  attr_accessor :line
74
74
 
75
75
  # The source range in the document on which this node appeared.
@@ -83,15 +83,13 @@ module Sass
83
83
  attr_writer :filename
84
84
 
85
85
  # The options hash for the node.
86
- # See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
86
+ # See {file:SASS_REFERENCE.md#options the Sass options documentation}.
87
87
  #
88
88
  # @return [{Symbol => Object}]
89
89
  attr_reader :options
90
90
 
91
91
  def initialize
92
92
  @children = []
93
- @filename = nil
94
- @options = nil
95
93
  end
96
94
 
97
95
  # Sets the options hash for the node and all its children.
@@ -151,7 +149,7 @@ module Sass
151
149
  # @return [Boolean]
152
150
  def invisible?; false; end
153
151
 
154
- # The output style. See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
152
+ # The output style. See {file:SASS_REFERENCE.md#options the Sass options documentation}.
155
153
  #
156
154
  # @return [Symbol]
157
155
  def style
@@ -20,11 +20,7 @@ module Sass::Tree
20
20
 
21
21
  # The value of the property.
22
22
  #
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>]
23
+ # @return [Sass::Script::Tree::Node]
28
24
  attr_accessor :value
29
25
 
30
26
  # The value of the property
@@ -43,7 +39,7 @@ module Sass::Tree
43
39
  # * This is a child property of another property
44
40
  # * The parent property has a value, and thus will be rendered
45
41
  #
46
- # @return [Integer]
42
+ # @return [Fixnum]
47
43
  attr_accessor :tabs
48
44
 
49
45
  # The source range in which the property name appears.
@@ -56,22 +52,14 @@ module Sass::Tree
56
52
  # @return [Sass::Source::Range]
57
53
  attr_accessor :value_source_range
58
54
 
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
-
66
55
  # @param name [Array<String, Sass::Script::Tree::Node>] See \{#name}
67
- # @param value [Array<String, Sass::Script::Tree::Node>] See \{#value}
56
+ # @param value [Sass::Script::Tree::Node] See \{#value}
68
57
  # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
69
58
  # `:old` if it uses `:a b`-style syntax
70
59
  def initialize(name, value, prop_syntax)
71
60
  @name = Sass::Util.strip_string_array(
72
61
  Sass::Util.merge_adjacent_strings(name))
73
- @value = Sass::Util.merge_adjacent_strings(value)
74
- @value = Sass::Util.strip_string_array(@value) unless custom_property?
62
+ @value = value
75
63
  @tabs = 0
76
64
  @prop_syntax = prop_syntax
77
65
  super()
@@ -93,10 +81,9 @@ module Sass::Tree
93
81
  # @return [String] The message
94
82
  def pseudo_class_selector_message
95
83
  if @prop_syntax == :new ||
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?
84
+ !value.is_a?(Sass::Script::Tree::Literal) ||
85
+ !value.value.is_a?(Sass::Script::Value::String) ||
86
+ !value.value.value.empty?
100
87
  return ""
101
88
  end
102
89
 
@@ -111,52 +98,74 @@ module Sass::Tree
111
98
  # @param fmt [Symbol] `:scss` or `:sass`.
112
99
  def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
113
100
  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
-
117
101
  if name[0] == ?:
118
- raise Sass::SyntaxError.new("The \"#{name}: #{value}\"" +
102
+ raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\"" +
119
103
  " hack is not allowed in the Sass indented syntax")
120
104
  end
121
105
 
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
-
126
106
  old = opts[:old] && fmt == :sass
127
- "#{old ? ':' : ''}#{name}#{old ? '' : ':'}#{custom_property? ? '' : ' '}#{value}".rstrip
107
+ initial = old ? ':' : ''
108
+ mid = old ? '' : ':'
109
+ "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
128
110
  end
129
111
 
130
112
  # A property node is invisible if its value is empty.
131
113
  #
132
114
  # @return [Boolean]
133
115
  def invisible?
134
- !custom_property? && resolved_value.empty?
116
+ resolved_value.empty?
135
117
  end
136
118
 
137
119
  private
138
120
 
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?
121
+ def check!
122
+ if @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
123
+ raise Sass::SyntaxError.new(
124
+ "Illegal property syntax: can't use #{@prop_syntax} syntax when " +
125
+ ":property_syntax => #{@options[:property_syntax].inspect} is set.")
126
+ end
153
127
  end
154
128
 
155
- def check!
156
- return unless @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
157
- raise Sass::SyntaxError.new(
158
- "Illegal property syntax: can't use #{@prop_syntax} syntax when " +
159
- ":property_syntax => #{@options[:property_syntax].inspect} is set.")
129
+ class << self
130
+ # @private
131
+ def val_to_sass(value, opts)
132
+ val_to_sass_comma(value, opts).to_sass(opts)
133
+ end
134
+
135
+ private
136
+
137
+ def val_to_sass_comma(node, opts)
138
+ return node unless node.is_a?(Sass::Script::Tree::Operation)
139
+ return val_to_sass_concat(node, opts) unless node.operator == :comma
140
+
141
+ Sass::Script::Tree::Operation.new(
142
+ val_to_sass_concat(node.operand1, opts),
143
+ val_to_sass_comma(node.operand2, opts),
144
+ node.operator)
145
+ end
146
+
147
+ def val_to_sass_concat(node, opts)
148
+ return node unless node.is_a?(Sass::Script::Tree::Operation)
149
+ return val_to_sass_div(node, opts) unless node.operator == :space
150
+
151
+ Sass::Script::Tree::Operation.new(
152
+ val_to_sass_div(node.operand1, opts),
153
+ val_to_sass_concat(node.operand2, opts),
154
+ node.operator)
155
+ end
156
+
157
+ def val_to_sass_div(node, opts)
158
+ unless node.is_a?(Sass::Script::Tree::Operation) && node.operator == :div &&
159
+ node.operand1.is_a?(Sass::Script::Tree::Literal) &&
160
+ node.operand1.value.is_a?(Sass::Script::Value::Number) &&
161
+ node.operand2.is_a?(Sass::Script::Tree::Literal) &&
162
+ node.operand2.value.is_a?(Sass::Script::Value::Number) &&
163
+ (!node.operand1.value.original || !node.operand2.value.original)
164
+ return node
165
+ end
166
+
167
+ Sass::Script::Value::String.new("(#{node.to_sass(opts)})")
168
+ end
160
169
  end
161
170
  end
162
171
  end
@@ -40,7 +40,7 @@ module Sass::Tree
40
40
  # * This is a child rule of another rule
41
41
  # * The parent rule has properties, and thus will be rendered
42
42
  #
43
- # @return [Integer]
43
+ # @return [Fixnum]
44
44
  attr_accessor :tabs
45
45
 
46
46
  # The entire selector source range for this rule.
@@ -120,34 +120,27 @@ module Sass::Tree
120
120
  #
121
121
  # @return [{#to_s => #to_s}]
122
122
  def debug_info
123
- {:filename => filename &&
124
- ("file://" + URI::DEFAULT_PARSER.escape(File.expand_path(filename))),
123
+ {:filename => filename && ("file://" + Sass::Util.escape_uri(File.expand_path(filename))),
125
124
  :line => line}
126
125
  end
127
126
 
128
127
  # A rule node is invisible if it has only placeholder selectors.
129
128
  def invisible?
130
- resolved_rules.members.all? {|seq| seq.invisible?}
129
+ resolved_rules.members.all? {|seq| seq.has_placeholder?}
131
130
  end
132
131
 
133
132
  private
134
133
 
135
134
  def try_to_parse_non_interpolated_rules
136
135
  @parsed_rules = nil
137
- return unless @rule.all? {|t| t.is_a?(String)}
136
+ return unless @rule.all? {|t| t.kind_of?(String)}
138
137
 
139
138
  # We don't use real filename/line info because we don't have it yet.
140
139
  # When we get it, we'll set it on the parsed rules if possible.
141
- parser = nil
142
- warnings = Sass.logger.capture do
143
- parser = Sass::SCSS::StaticParser.new(
144
- Sass::Util.strip_except_escapes(@rule.join), nil, nil, 1)
145
- @parsed_rules = parser.parse_selector rescue nil
146
- end
147
-
148
- # If parsing produces a warning, throw away the result so we can parse
149
- # later with the real filename info.
150
- @parsed_rules = nil unless warnings.empty?
140
+ parser = Sass::SCSS::StaticParser.new(@rule.join.strip, nil, nil, 1)
141
+ # rubocop:disable RescueModifier
142
+ @parsed_rules = parser.parse_selector rescue nil
143
+ # rubocop:enable RescueModifier
151
144
  end
152
145
  end
153
146
  end
@@ -4,8 +4,6 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
4
4
 
5
5
  def initialize
6
6
  @parents = []
7
- @parent = nil
8
- @current_mixin_def = nil
9
7
  end
10
8
 
11
9
  def visit(node)
@@ -31,7 +29,7 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
31
29
  if parent.is_a?(Sass::Tree::AtRootNode) && parent.resolved_value
32
30
  old_parents = @parents
33
31
  @parents = @parents.reject {|p| parent.exclude_node?(p)}
34
- @parent = @parents.reverse.each_with_index.
32
+ @parent = Sass::Util.enum_with_index(@parents.reverse).
35
33
  find {|p, i| !transparent_parent?(p, @parents[-i - 2])}.first
36
34
 
37
35
  begin
@@ -92,8 +90,9 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
92
90
 
93
91
  VALID_EXTEND_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
94
92
  def invalid_extend_parent?(parent, child)
95
- return if is_any_of?(parent, VALID_EXTEND_PARENTS)
96
- "Extend directives may only be used within rules."
93
+ unless is_any_of?(parent, VALID_EXTEND_PARENTS)
94
+ return "Extend directives may only be used within rules."
95
+ end
97
96
  end
98
97
 
99
98
  INVALID_IMPORT_PARENTS = CONTROL_NODES +
@@ -111,13 +110,15 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
111
110
  end
112
111
 
113
112
  def invalid_mixindef_parent?(parent, child)
114
- return if (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
115
- "Mixins may not be defined within control directives or other mixins."
113
+ unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
114
+ return "Mixins may not be defined within control directives or other mixins."
115
+ end
116
116
  end
117
117
 
118
118
  def invalid_function_parent?(parent, child)
119
- return if (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
120
- "Functions may not be defined within control directives or other mixins."
119
+ unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
120
+ return "Functions may not be defined within control directives or other mixins."
121
+ end
121
122
  end
122
123
 
123
124
  VALID_FUNCTION_CHILDREN = [
@@ -125,24 +126,27 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
125
126
  Sass::Tree::VariableNode, Sass::Tree::WarnNode, Sass::Tree::ErrorNode
126
127
  ] + CONTROL_NODES
127
128
  def invalid_function_child?(parent, child)
128
- return if is_any_of?(child, VALID_FUNCTION_CHILDREN)
129
- "Functions can only contain variable declarations and control directives."
129
+ unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
130
+ "Functions can only contain variable declarations and control directives."
131
+ end
130
132
  end
131
133
 
132
- VALID_PROP_CHILDREN = CONTROL_NODES + [Sass::Tree::CommentNode,
133
- Sass::Tree::PropNode,
134
- Sass::Tree::MixinNode]
134
+ VALID_PROP_CHILDREN = CONTROL_NODES + [Sass::Tree::CommentNode,
135
+ Sass::Tree::PropNode,
136
+ Sass::Tree::MixinNode]
135
137
  def invalid_prop_child?(parent, child)
136
- return if is_any_of?(child, VALID_PROP_CHILDREN)
137
- "Illegal nesting: Only properties may be nested beneath properties."
138
+ unless is_any_of?(child, VALID_PROP_CHILDREN)
139
+ "Illegal nesting: Only properties may be nested beneath properties."
140
+ end
138
141
  end
139
142
 
140
143
  VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::KeyframeRuleNode, Sass::Tree::PropNode,
141
144
  Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode, Sass::Tree::MixinNode]
142
145
  def invalid_prop_parent?(parent, child)
143
- return if is_any_of?(parent, VALID_PROP_PARENTS)
144
- "Properties are only allowed within rules, directives, mixin includes, or other properties." +
145
- child.pseudo_class_selector_message
146
+ unless is_any_of?(parent, VALID_PROP_PARENTS)
147
+ "Properties are only allowed within rules, directives, mixin includes, or other properties." +
148
+ child.pseudo_class_selector_message
149
+ end
146
150
  end
147
151
 
148
152
  def invalid_return_parent?(parent, child)
@@ -18,7 +18,6 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
18
18
  @tabs = 0
19
19
  # 2 spaces by default
20
20
  @tab_chars = @options[:indent] || " "
21
- @is_else = false
22
21
  end
23
22
 
24
23
  def visit_children(parent)
@@ -28,9 +27,9 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
28
27
  res = visit_rule_level(parent.children)
29
28
 
30
29
  if @format == :sass
31
- "\n" + res.rstrip + "\n"
30
+ "\n" + res.rstrip + "\n"
32
31
  else
33
- " {\n" + res.rstrip + "\n#{@tab_chars * (@tabs - 1)}}\n"
32
+ " {\n" + res.rstrip + "\n#{ @tab_chars * (@tabs - 1)}}\n"
34
33
  end
35
34
  ensure
36
35
  @tabs -= 1
@@ -48,14 +47,14 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
48
47
  def visit_comment(node)
49
48
  value = interp_to_src(node.value)
50
49
  if @format == :sass
51
- content = value.gsub(%r{\*/$}, '').rstrip
50
+ content = value.gsub(/\*\/$/, '').rstrip
52
51
  if content =~ /\A[ \t]/
53
52
  # Re-indent SCSS comments like this:
54
53
  # /* foo
55
54
  # bar
56
55
  # baz */
57
56
  content.gsub!(/^/, ' ')
58
- content.sub!(%r{\A([ \t]*)/\*}, '/*\1')
57
+ content.sub!(/\A([ \t]*)\/\*/, '/*\1')
59
58
  end
60
59
 
61
60
  if content.include?("\n")
@@ -69,13 +68,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
69
68
  end
70
69
  end
71
70
 
72
- content.gsub!(%r{\A/\*}, '//') if node.type == :silent
71
+ content.gsub!(/\A\/\*/, '//') if node.type == :silent
73
72
  content.gsub!(/^/, tab_str)
74
73
  content = content.rstrip + "\n"
75
74
  else
76
75
  spaces = (@tab_chars * [@tabs - value[/^ */].size, 0].max)
77
76
  content = if node.type == :silent
78
- value.gsub(%r{^[/ ]\*}, '//').gsub(%r{ *\*/$}, '')
77
+ value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
79
78
  else
80
79
  value
81
80
  end.gsub(/^/, spaces) + "\n"
@@ -105,12 +104,12 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
105
104
 
106
105
  def visit_extend(node)
107
106
  "#{tab_str}@extend #{selector_to_src(node.selector).lstrip}" +
108
- "#{' !optional' if node.optional?}#{semi}\n"
107
+ "#{" !optional" if node.optional?}#{semi}\n"
109
108
  end
110
109
 
111
110
  def visit_for(node)
112
111
  "#{tab_str}@for $#{dasherize(node.var)} from #{node.from.to_sass(@options)} " +
113
- "#{node.exclusive ? 'to' : 'through'} #{node.to.to_sass(@options)}#{yield}"
112
+ "#{node.exclusive ? "to" : "through"} #{node.to.to_sass(@options)}#{yield}"
114
113
  end
115
114
 
116
115
  def visit_function(node)
@@ -203,7 +202,8 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
203
202
 
204
203
  unless node.args.empty? && node.keywords.empty? && node.splat.nil?
205
204
  args = node.args.map(&arg_to_sass)
206
- keywords = node.keywords.as_stored.to_a.map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
205
+ keywords = Sass::Util.hash_to_a(node.keywords.as_stored).
206
+ map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
207
207
 
208
208
  if node.splat
209
209
  splat = "#{arg_to_sass[node.splat]}..."
@@ -280,7 +280,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
280
280
  # Visit rule-level nodes and return their conversion with appropriate
281
281
  # whitespace added.
282
282
  def visit_rule_level(nodes)
283
- (nodes + [nil]).each_cons(2).map do |child, nxt|
283
+ Sass::Util.enum_cons(nodes + [nil], 2).map do |child, nxt|
284
284
  visit(child) +
285
285
  if nxt &&
286
286
  (child.is_a?(Sass::Tree::CommentNode) && child.line + child.lines + 1 == nxt.line) ||
@@ -288,9 +288,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
288
288
  child.line + 1 == nxt.line) ||
289
289
  (child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
290
290
  child.line + 1 == nxt.line) ||
291
- (child.is_a?(Sass::Tree::PropNode) && nxt.is_a?(Sass::Tree::PropNode)) ||
292
- (child.is_a?(Sass::Tree::MixinNode) && nxt.is_a?(Sass::Tree::MixinNode) &&
293
- child.line + 1 == nxt.line)
291
+ (child.is_a?(Sass::Tree::PropNode) && nxt.is_a?(Sass::Tree::PropNode))
294
292
  ""
295
293
  else
296
294
  "\n"
@@ -342,7 +340,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
342
340
 
343
341
  def dasherize(s)
344
342
  if @options[:dasherize]
345
- s.tr('_', '-')
343
+ s.gsub('_', '-')
346
344
  else
347
345
  s
348
346
  end