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
@@ -69,14 +69,14 @@ module Sass
69
69
  # The name of the mixin in which the error occurred.
70
70
  # This could be `nil` if the error occurred outside a mixin.
71
71
  #
72
- # @return [String]
72
+ # @return [Fixnum]
73
73
  def sass_mixin
74
74
  sass_backtrace.first[:mixin]
75
75
  end
76
76
 
77
77
  # The line of the Sass template on which the error occurred.
78
78
  #
79
- # @return [Integer]
79
+ # @return [Fixnum]
80
80
  def sass_line
81
81
  sass_backtrace.first[:line]
82
82
  end
@@ -86,7 +86,7 @@ module Sass
86
86
  # @param attrs [{Symbol => Object}] The information in the backtrace entry.
87
87
  # See \{#sass\_backtrace}
88
88
  def add_backtrace(attrs)
89
- sass_backtrace << attrs.reject {|_k, v| v.nil?}
89
+ sass_backtrace << attrs.reject {|k, v| v.nil?}
90
90
  end
91
91
 
92
92
  # Modify the top Sass backtrace entries
@@ -104,12 +104,12 @@ module Sass
104
104
  # @param attrs [{Symbol => Object}] The information to add to the backtrace entry.
105
105
  # See \{#sass\_backtrace}
106
106
  def modify_backtrace(attrs)
107
- attrs = attrs.reject {|_k, v| v.nil?}
107
+ attrs = attrs.reject {|k, v| v.nil?}
108
108
  # Move backwards through the backtrace
109
- (0...sass_backtrace.size).to_a.reverse_each do |i|
109
+ (0...sass_backtrace.size).to_a.reverse.each do |i|
110
110
  entry = sass_backtrace[i]
111
111
  sass_backtrace[i] = attrs.merge(entry)
112
- attrs.reject! {|k, _v| entry.include?(k)}
112
+ attrs.reject! {|k, v| entry.include?(k)}
113
113
  break if attrs.empty?
114
114
  end
115
115
  end
@@ -127,7 +127,7 @@ module Sass
127
127
  return nil if super.nil?
128
128
  return super if sass_backtrace.all? {|h| h.empty?}
129
129
  sass_backtrace.map do |h|
130
- "#{h[:filename] || '(sass)'}:#{h[:line]}" +
130
+ "#{h[:filename] || "(sass)"}:#{h[:line]}" +
131
131
  (h[:mixin] ? ":in `#{h[:mixin]}'" : "")
132
132
  end + super
133
133
  end
@@ -142,8 +142,8 @@ module Sass
142
142
  msg = lines[0] + lines[1..-1].
143
143
  map {|l| "\n" + (" " * "Error: ".size) + l}.join
144
144
  "Error: #{msg}" +
145
- sass_backtrace.each_with_index.map do |entry, i|
146
- "\n #{i == 0 ? 'on' : 'from'} line #{entry[:line]}" +
145
+ Sass::Util.enum_with_index(sass_backtrace).map do |entry, i|
146
+ "\n #{i == 0 ? "on" : "from"} line #{entry[:line]}" +
147
147
  " of #{entry[:filename] || default_filename}" +
148
148
  (entry[:mixin] ? ", in `#{entry[:mixin]}'" : "")
149
149
  end.join
@@ -153,7 +153,7 @@ module Sass
153
153
  # Returns an error report for an exception in CSS format.
154
154
  #
155
155
  # @param e [Exception]
156
- # @param line_offset [Integer] The number of the first line of the Sass template.
156
+ # @param line_offset [Fixnum] The number of the first line of the Sass template.
157
157
  # @return [String] The error report
158
158
  # @raise [Exception] `e`, if the
159
159
  # {file:SASS_REFERENCE.md#full_exception-option `:full_exception`} option
@@ -163,9 +163,9 @@ module Sass
163
163
 
164
164
  <<END
165
165
  /*
166
- #{header.gsub('*/', '*\\/')}
166
+ #{header.gsub("*/", "*\\/")}
167
167
 
168
- Backtrace:\n#{e.backtrace.join("\n").gsub('*/', '*\\/')}
168
+ Backtrace:\n#{e.backtrace.join("\n").gsub("*/", "*\\/")}
169
169
  */
170
170
  body:before {
171
171
  white-space: pre;
@@ -183,10 +183,10 @@ END
183
183
 
184
184
  line_num = e.sass_line + 1 - line_offset
185
185
  min = [line_num - 6, 0].max
186
- section = e.sass_template.rstrip.split("\n")[min...line_num + 5]
186
+ section = e.sass_template.rstrip.split("\n")[min ... line_num + 5]
187
187
  return e.sass_backtrace_str if section.nil? || section.empty?
188
188
 
189
- e.sass_backtrace_str + "\n\n" + section.each_with_index.
189
+ e.sass_backtrace_str + "\n\n" + Sass::Util.enum_with_index(section).
190
190
  map {|line, i| "#{line_offset + min + i}: #{line}"}.join("\n")
191
191
  end
192
192
  end
@@ -14,6 +14,7 @@ module Sass::Exec
14
14
  #
15
15
  # @see #parse
16
16
  def parse!
17
+ # rubocop:disable RescueException
17
18
  begin
18
19
  parse
19
20
  rescue Exception => e
@@ -22,7 +23,7 @@ module Sass::Exec
22
23
  # at_exit is a bit of a hack, but it allows us to rethrow when --trace
23
24
  # is active and get both the built-in exception formatting and the
24
25
  # correct exit code.
25
- at_exit {exit Sass::Util.windows? ? 13 : 65} if e.is_a?(Sass::SyntaxError)
26
+ at_exit {exit 65} if e.is_a?(Sass::SyntaxError)
26
27
 
27
28
  raise e if @options[:trace] || e.is_a?(SystemExit)
28
29
 
@@ -37,6 +38,7 @@ module Sass::Exec
37
38
  exit 1
38
39
  end
39
40
  exit 0
41
+ # rubocop:enable RescueException
40
42
  end
41
43
 
42
44
  # Parses the command-line arguments and runs the executable.
@@ -88,9 +90,18 @@ module Sass::Exec
88
90
  #
89
91
  # @param opts [OptionParser]
90
92
  def encoding_option(opts)
91
- encoding_desc = 'Specify the default encoding for input files.'
93
+ encoding_desc = if Sass::Util.ruby1_8?
94
+ 'Does not work in Ruby 1.8.'
95
+ else
96
+ 'Specify the default encoding for input files.'
97
+ end
92
98
  opts.on('-E', '--default-encoding ENCODING', encoding_desc) do |encoding|
93
- Encoding.default_external = encoding
99
+ if Sass::Util.ruby1_8?
100
+ $stderr.puts "Specifying the encoding is not supported in ruby 1.8."
101
+ exit 1
102
+ else
103
+ Encoding.default_external = encoding
104
+ end
94
105
  end
95
106
  end
96
107
 
@@ -108,11 +108,10 @@ END
108
108
  @options[:for_tree][:dasherize] = true
109
109
  end
110
110
 
111
- opts.on(
112
- '--indent NUM',
111
+ opts.on('--indent NUM',
113
112
  'How many spaces to use for each level of indentation. Defaults to 2.',
114
- '"t" means use hard tabs.'
115
- ) do |indent|
113
+ '"t" means use hard tabs.') do |indent|
114
+
116
115
  if indent == 't'
117
116
  @options[:for_tree][:indent] = "\t"
118
117
  else
@@ -157,18 +156,13 @@ END
157
156
  @options[:for_engine][:read_cache] = false
158
157
  end
159
158
 
160
- opts.on('-q', '--quiet', 'Silence warnings and status messages during conversion.') do |bool|
161
- @options[:for_engine][:quiet] = bool
162
- end
163
-
164
159
  opts.on('--trace', :NONE, 'Show a full Ruby stack trace on error') do
165
160
  @options[:trace] = true
166
161
  end
167
162
  end
168
163
 
169
164
  def process_directory
170
- @options[:input] = @args.shift
171
- unless @options[:input]
165
+ unless @options[:input] = @args.shift
172
166
  raise "Error: directory required when using --recursive."
173
167
  end
174
168
 
@@ -247,12 +241,12 @@ END
247
241
  Sass::Util.silence_sass_warnings do
248
242
  if @options[:from] == :css
249
243
  require 'sass/css'
250
- Sass::CSS.new(read(input), @options[:for_tree]).render(@options[:to])
244
+ Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
251
245
  else
252
246
  if input_path
253
247
  Sass::Engine.for_file(input_path, @options[:for_engine])
254
248
  else
255
- Sass::Engine.new(read(input), @options[:for_engine])
249
+ Sass::Engine.new(input.read, @options[:for_engine])
256
250
  end.to_tree.send("to_#{@options[:to]}", @options[:for_tree])
257
251
  end
258
252
  end
@@ -271,13 +265,5 @@ END
271
265
  return file.path if file.is_a?(File)
272
266
  return file if file.is_a?(String)
273
267
  end
274
-
275
- def read(file)
276
- if file.respond_to?(:read)
277
- file.read
278
- else
279
- open(file, 'rb') {|f| f.read}
280
- end
281
- end
282
268
  end
283
269
  end
@@ -92,7 +92,7 @@ END
92
92
  end
93
93
 
94
94
  opts.on("-v", "--version", "Print the Sass version.") do
95
- puts("Ruby Sass #{Sass.version[:string]}")
95
+ puts("Sass #{Sass.version[:string]}")
96
96
  exit
97
97
  end
98
98
  end
@@ -156,7 +156,7 @@ END
156
156
  ' file: always absolute file URIs',
157
157
  ' inline: include the source text in the sourcemap',
158
158
  ' none: no sourcemaps') do |type|
159
- if type && !%w(auto file inline none).include?(type)
159
+ if type && !%w[auto file inline none].include?(type)
160
160
  $stderr.puts "Unknown sourcemap type #{type}.\n\n"
161
161
  $stderr.puts opts
162
162
  exit
@@ -256,6 +256,8 @@ MESSAGE
256
256
  Sass::Repl.new(@options).run
257
257
  end
258
258
 
259
+ # @comment
260
+ # rubocop:disable MethodLength
259
261
  def watch_or_update
260
262
  require 'sass/plugin'
261
263
  Sass::Plugin.options.merge! @options[:for_engine]
@@ -288,6 +290,27 @@ File #{@args[1]} #{err}.
288
290
  MSG
289
291
  end
290
292
 
293
+ # Watch the working directory for changes without adding it to the load
294
+ # path. This preserves the pre-3.4 behavior when the working directory was
295
+ # on the load path. We should remove this when we can look for directories
296
+ # to watch by traversing the import graph.
297
+ class << Sass::Plugin.compiler
298
+ # We have to use a class var to make this visible to #watched_file? and
299
+ # #watched_paths.
300
+ # rubocop:disable ClassVars
301
+ @@working_directory = Sass::Util.realpath('.').to_s
302
+ # rubocop:ensable ClassVars
303
+
304
+ def watched_file?(file)
305
+ super(file) ||
306
+ (file =~ /\.s[ac]ss$/ && file.start_with?(@@working_directory + File::SEPARATOR))
307
+ end
308
+
309
+ def watched_paths
310
+ @watched_paths ||= super + [@@working_directory]
311
+ end
312
+ end
313
+
291
314
  dirs, files = @args.map {|name| split_colon_path(name)}.
292
315
  partition {|i, _| File.directory? i}
293
316
 
@@ -357,6 +380,8 @@ WARNING
357
380
 
358
381
  Sass::Plugin.watch(files)
359
382
  end
383
+ # @comment
384
+ # rubocop:enable MethodLength
360
385
 
361
386
  def run
362
387
  input = @options[:input]
@@ -386,8 +411,7 @@ WARNING
386
411
  @options[:sourcemap_filename], Sass::Util.pathname(@options[:output_filename]).dirname)
387
412
  rendered, mapping = engine.render_with_sourcemap(relative_sourcemap_path.to_s)
388
413
  write_output(rendered, output)
389
- write_output(
390
- mapping.to_json(
414
+ write_output(mapping.to_json(
391
415
  :type => @options[:sourcemap],
392
416
  :css_path => @options[:output_filename],
393
417
  :sourcemap_path => @options[:sourcemap_filename]) + "\n",
@@ -409,7 +433,7 @@ WARNING
409
433
  def split_colon_path(path)
410
434
  one, two = path.split(':', 2)
411
435
  if one && two && Sass::Util.windows? &&
412
- one =~ /\A[A-Za-z]\Z/ && two =~ %r{\A[/\\]}
436
+ one =~ /\A[A-Za-z]\Z/ && two =~ /\A[\/\\]/
413
437
  # If we're on Windows and we were passed a drive letter path,
414
438
  # don't split on that colon.
415
439
  one2, two = two.split(':', 2)
@@ -7,13 +7,12 @@ module Sass
7
7
  #
8
8
  # When this is updated, the documentation of `feature-exists()` should be
9
9
  # updated as well.
10
- KNOWN_FEATURES = Set[*%w(
10
+ KNOWN_FEATURES = Set[*%w{
11
11
  global-variable-shadowing
12
12
  extend-selector-pseudoclass
13
13
  units-level-3
14
14
  at-error
15
- custom-property
16
- )]
15
+ }]
17
16
 
18
17
  # Check if a feature exists by name. This is used to implement
19
18
  # the Sass function `feature-exists($feature)`
@@ -67,7 +67,7 @@ module Sass
67
67
  end
68
68
 
69
69
  def public_url(name, sourcemap_directory)
70
- file_pathname = Sass::Util.cleanpath(File.absolute_path(name, @root))
70
+ file_pathname = Sass::Util.cleanpath(Sass::Util.absolute_path(name, @root))
71
71
  return Sass::Util.file_uri_from_path(file_pathname) if sourcemap_directory.nil?
72
72
 
73
73
  sourcemap_pathname = Sass::Util.cleanpath(sourcemap_directory)
@@ -122,7 +122,7 @@ module Sass
122
122
  end
123
123
 
124
124
  # JRuby chokes when trying to import files from JARs when the path starts with './'.
125
- ret.map {|f, s| [f.sub(%r{^\./}, ''), s]}
125
+ ret.map {|f, s| [f.sub(/^\.\//, ''), s]}
126
126
  end
127
127
 
128
128
  def escape_glob_characters(name)
@@ -144,19 +144,14 @@ module Sass
144
144
  name = name.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless File::ALT_SEPARATOR.nil?
145
145
 
146
146
  found = possible_files(remove_root(name)).map do |f, s|
147
- path = if dir == "." || Sass::Util.pathname(f).absolute?
148
- f
149
- else
150
- "#{escape_glob_characters(dir)}/#{f}"
151
- end
147
+ path = (dir == "." || Sass::Util.pathname(f).absolute?) ? f :
148
+ "#{escape_glob_characters(dir)}/#{f}"
152
149
  Dir[path].map do |full_path|
153
150
  full_path.gsub!(REDUNDANT_DIRECTORY, File::SEPARATOR)
154
151
  [Sass::Util.cleanpath(full_path).to_s, s]
155
152
  end
156
153
  end.flatten(1)
157
- if found.empty? && split(name)[2].nil? && File.directory?("#{dir}/#{name}")
158
- return find_real_file("#{dir}/#{name}", "index", options)
159
- end
154
+ return if found.empty?
160
155
 
161
156
  if found.size > 1 && !@same_name_warnings.include?(found.first.first)
162
157
  found.each {|(f, _)| @same_name_warnings << f}
@@ -204,7 +199,7 @@ WARNING
204
199
 
205
200
  def _find(dir, name, options)
206
201
  full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options))
207
- return unless full_filename && File.file?(full_filename) && File.readable?(full_filename)
202
+ return unless full_filename && File.readable?(full_filename)
208
203
 
209
204
  # TODO: this preserves historical behavior, but it's possible
210
205
  # :filename should be either normalized to the native format
@@ -2,16 +2,11 @@ module Sass::Logger; end
2
2
 
3
3
  require "sass/logger/log_level"
4
4
  require "sass/logger/base"
5
- require "sass/logger/delayed"
6
5
 
7
6
  module Sass
8
7
  class << self
9
- def logger=(l)
10
- Thread.current[:sass_logger] = l
11
- end
12
-
13
- def logger
14
- Thread.current[:sass_logger] ||= Sass::Logger::Base.new
15
- end
8
+ attr_accessor :logger
16
9
  end
10
+
11
+ self.logger = Sass::Logger::Base.new
17
12
  end
@@ -5,7 +5,6 @@ class Sass::Logger::Base
5
5
 
6
6
  attr_accessor :log_level
7
7
  attr_accessor :disabled
8
- attr_accessor :io
9
8
 
10
9
  log_level :trace
11
10
  log_level :debug
@@ -13,35 +12,19 @@ class Sass::Logger::Base
13
12
  log_level :warn
14
13
  log_level :error
15
14
 
16
- def initialize(log_level = :debug, io = nil)
15
+ def initialize(log_level = :debug)
17
16
  self.log_level = log_level
18
- self.io = io
19
17
  end
20
18
 
21
19
  def logging_level?(level)
22
20
  !disabled && self.class.log_level?(level, log_level)
23
21
  end
24
22
 
25
- # Captures all logger messages emitted during a block and returns them as a
26
- # string.
27
- def capture
28
- old_io = io
29
- self.io = StringIO.new
30
- yield
31
- io.string
32
- ensure
33
- self.io = old_io
34
- end
35
-
36
23
  def log(level, message)
37
24
  _log(level, message) if logging_level?(level)
38
25
  end
39
26
 
40
27
  def _log(level, message)
41
- if io
42
- io.puts(message)
43
- else
44
- Kernel.warn(message)
45
- end
28
+ Kernel.warn(message)
46
29
  end
47
30
  end
@@ -12,7 +12,7 @@ module Sass
12
12
  # when it's used as a plugin for various frameworks.
13
13
  # All Rack-enabled frameworks are supported out of the box.
14
14
  # The plugin is
15
- # {file:SASS_REFERENCE.md#Rack_Rails_Merb_Plugin automatically activated for Rails and Merb}.
15
+ # {file:SASS_REFERENCE.md#rails_merb_plugin automatically activated for Rails and Merb}.
16
16
  # Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
17
17
  #
18
18
  # This module has a large set of callbacks available
@@ -93,8 +93,7 @@ module Sass
93
93
  # the second is the location of the CSS file that it should be compiled to.
94
94
  # @see #update_stylesheets
95
95
  def force_update_stylesheets(individual_files = [])
96
- Compiler.new(
97
- options.dup.merge(
96
+ Compiler.new(options.dup.merge(
98
97
  :never_update => false,
99
98
  :always_update => true,
100
99
  :cache => false)).update_stylesheets(individual_files)
@@ -31,7 +31,7 @@ module Sass::Plugin
31
31
  # Creates a new compiler.
32
32
  #
33
33
  # @param opts [{Symbol => Object}]
34
- # See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
34
+ # See {file:SASS_REFERENCE.md#options the Sass options documentation}.
35
35
  def initialize(opts = {})
36
36
  @watched_files = Set.new
37
37
  options.merge!(opts)
@@ -289,7 +289,6 @@ module Sass::Plugin
289
289
  # @option options [Boolean] :skip_initial_update
290
290
  # Don't do an initial update when starting the watcher when true
291
291
  def watch(individual_files = [], options = {})
292
- @inferred_directories = []
293
292
  options, individual_files = individual_files, [] if individual_files.is_a?(Hash)
294
293
  update_stylesheets(individual_files) unless options[:skip_initial_update]
295
294
 
@@ -297,36 +296,46 @@ module Sass::Plugin
297
296
  individual_files.each do |(source, _, _)|
298
297
  source = File.expand_path(source)
299
298
  @watched_files << Sass::Util.realpath(source).to_s
300
- @inferred_directories << File.dirname(source)
299
+ directories << File.dirname(source)
301
300
  end
302
-
303
- directories += @inferred_directories
304
301
  directories = remove_redundant_directories(directories)
305
302
 
303
+ # A Listen version prior to 2.0 will write a test file to a directory to
304
+ # see if a watcher supports watching that directory. That breaks horribly
305
+ # on read-only directories, so we filter those out.
306
+ unless Sass::Util.listen_geq_2?
307
+ directories = directories.select {|d| File.directory?(d) && File.writable?(d)}
308
+ end
309
+
306
310
  # TODO: Keep better track of what depends on what
307
311
  # so we don't have to run a global update every time anything changes.
308
312
  # XXX The :additional_watch_paths option exists for Compass to use until
309
313
  # a deprecated feature is removed. It may be removed without warning.
310
- directories += Array(options[:additional_watch_paths])
311
-
312
- options = {
313
- :relative_paths => false,
314
- # The native windows listener is much slower than the polling option, according to
315
- # https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e
316
- :force_polling => @options[:poll] || Sass::Util.windows?
317
- }
314
+ listener_args = directories +
315
+ Array(options[:additional_watch_paths]) +
316
+ [{:relative_paths => false}]
317
+
318
+ # The native windows listener is much slower than the polling option, according to
319
+ # https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e
320
+ poll = @options[:poll] || Sass::Util.windows?
321
+ if poll && Sass::Util.listen_geq_2?
322
+ # In Listen 2.0.0 and on, :force_polling is an option. In earlier
323
+ # versions, it's a method on the listener (called below).
324
+ listener_args.last[:force_polling] = true
325
+ end
318
326
 
319
- listener = create_listener(*directories, options) do |modified, added, removed|
327
+ listener = create_listener(*listener_args) do |modified, added, removed|
320
328
  on_file_changed(individual_files, modified, added, removed)
321
329
  yield(modified, added, removed) if block_given?
322
330
  end
323
331
 
324
- begin
325
- listener.start
326
- sleep
327
- rescue Interrupt
328
- # Squelch Interrupt for clean exit from Listen::Listener
332
+ if poll && !Sass::Util.listen_geq_2?
333
+ # In Listen 2.0.0 and on, :force_polling is an option (set above). In
334
+ # earlier versions, it's a method on the listener.
335
+ listener.force_polling(true)
329
336
  end
337
+
338
+ listen_to(listener)
330
339
  end
331
340
 
332
341
  # Non-destructively modifies \{#options} so that default values are properly set,
@@ -375,10 +384,28 @@ module Sass::Plugin
375
384
 
376
385
  private
377
386
 
378
- # This is mocked out in compiler_test.rb.
379
387
  def create_listener(*args, &block)
380
- require 'sass-listen'
381
- SassListen.to(*args, &block)
388
+ Sass::Util.load_listen!
389
+ if Sass::Util.listen_geq_2?
390
+ # Work around guard/listen#243.
391
+ options = args.pop if args.last.is_a?(Hash)
392
+ args.map do |dir|
393
+ Listen.to(dir, options, &block)
394
+ end
395
+ else
396
+ Listen::Listener.new(*args, &block)
397
+ end
398
+ end
399
+
400
+ def listen_to(listener)
401
+ if Sass::Util.listen_geq_2?
402
+ listener.map {|l| l.start}
403
+ sleep
404
+ else
405
+ listener.start!
406
+ end
407
+ rescue Interrupt
408
+ # Squelch Interrupt for clean exit from Listen::Listener
382
409
  end
383
410
 
384
411
  def remove_redundant_directories(directories)
@@ -427,20 +454,21 @@ module Sass::Plugin
427
454
  # And try to remove the css file that corresponds to it
428
455
  template_location_array.each do |(sass_dir, css_dir)|
429
456
  sass_dir = File.expand_path(sass_dir)
430
- next unless child_of_directory?(sass_dir, f)
431
- remainder = f[(sass_dir.size + 1)..-1]
432
- try_delete_css(css_filename(remainder, css_dir))
433
- break
457
+ if child_of_directory?(sass_dir, f)
458
+ remainder = f[(sass_dir.size + 1)..-1]
459
+ try_delete_css(css_filename(remainder, css_dir))
460
+ break
461
+ end
434
462
  end
435
463
  end
436
464
  end
437
465
 
438
- return unless recompile_required
439
-
440
- # In case a file we're watching is removed and then recreated we
441
- # prune out the non-existant files here.
442
- watched_files_remaining = individual_files.select {|(source, _, _)| File.exist?(source)}
443
- update_stylesheets(watched_files_remaining)
466
+ if recompile_required
467
+ # In case a file we're watching is removed and then recreated we
468
+ # prune out the non-existent files here.
469
+ watched_files_remaining = individual_files.select {|(source, _, _)| File.exist?(source)}
470
+ update_stylesheets(watched_files_remaining)
471
+ end
444
472
  end
445
473
 
446
474
  def update_stylesheet(filename, css, sourcemap)
@@ -472,9 +500,7 @@ module Sass::Plugin
472
500
 
473
501
  write_file(css, rendered)
474
502
  if mapping
475
- write_file(
476
- sourcemap,
477
- mapping.to_json(
503
+ write_file(sourcemap, mapping.to_json(
478
504
  :css_path => css, :sourcemap_path => sourcemap, :type => options[:sourcemap]))
479
505
  end
480
506
  run_updated_stylesheet(filename, css, sourcemap) unless compilation_error_occurred
@@ -484,7 +510,7 @@ module Sass::Plugin
484
510
  flag = 'w'
485
511
  flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
486
512
  File.open(fileName, flag) do |file|
487
- file.set_encoding(content.encoding)
513
+ file.set_encoding(content.encoding) unless Sass::Util.ruby1_8?
488
514
  file.print(content)
489
515
  end
490
516
  end
@@ -495,21 +521,14 @@ module Sass::Plugin
495
521
  File.delete css
496
522
  end
497
523
  map = Sass::Util.sourcemap_name(css)
498
-
499
- return unless File.exist?(map)
500
-
501
- run_deleting_sourcemap map
502
- File.delete map
524
+ if File.exist?(map)
525
+ run_deleting_sourcemap map
526
+ File.delete map
527
+ end
503
528
  end
504
529
 
505
530
  def watched_file?(file)
506
- @watched_files.include?(file) ||
507
- normalized_load_paths.any? {|lp| lp.watched_file?(file)} ||
508
- @inferred_directories.any? {|d| sass_file_in_directory?(d, file)}
509
- end
510
-
511
- def sass_file_in_directory?(directory, filename)
512
- filename =~ /\.s[ac]ss$/ && filename.start_with?(directory + File::SEPARATOR)
531
+ @watched_files.include?(file) || normalized_load_paths.any? {|lp| lp.watched_file?(file)}
513
532
  end
514
533
 
515
534
  def watched_paths