sass 3.1.21 → 3.2.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. data/README.md +5 -4
  2. data/REVISION +1 -1
  3. data/Rakefile +6 -15
  4. data/VERSION +1 -1
  5. data/VERSION_NAME +1 -1
  6. data/lib/sass.rb +0 -1
  7. data/lib/sass/cache_stores/base.rb +1 -3
  8. data/lib/sass/cache_stores/filesystem.rb +0 -3
  9. data/lib/sass/css.rb +49 -145
  10. data/lib/sass/engine.rb +23 -47
  11. data/lib/sass/environment.rb +5 -30
  12. data/lib/sass/exec.rb +7 -30
  13. data/lib/sass/importers/base.rb +1 -2
  14. data/lib/sass/importers/filesystem.rb +13 -18
  15. data/lib/sass/less.rb +1 -1
  16. data/lib/sass/plugin.rb +8 -4
  17. data/lib/sass/plugin/compiler.rb +67 -93
  18. data/lib/sass/plugin/configuration.rb +2 -0
  19. data/lib/sass/plugin/staleness_checker.rb +4 -14
  20. data/lib/sass/repl.rb +3 -2
  21. data/lib/sass/script.rb +1 -0
  22. data/lib/sass/script/color.rb +9 -4
  23. data/lib/sass/script/funcall.rb +3 -16
  24. data/lib/sass/script/functions.rb +55 -98
  25. data/lib/sass/script/interpolation.rb +0 -9
  26. data/lib/sass/script/lexer.rb +4 -2
  27. data/lib/sass/script/list.rb +0 -8
  28. data/lib/sass/script/literal.rb +20 -5
  29. data/lib/sass/script/node.rb +0 -8
  30. data/lib/sass/script/number.rb +11 -35
  31. data/lib/sass/script/operation.rb +0 -16
  32. data/lib/sass/script/parser.rb +5 -12
  33. data/lib/sass/script/string_interpolation.rb +0 -9
  34. data/lib/sass/script/unary_operation.rb +0 -7
  35. data/lib/sass/script/variable.rb +1 -5
  36. data/lib/sass/scss/parser.rb +54 -191
  37. data/lib/sass/scss/rx.rb +3 -15
  38. data/lib/sass/scss/static_parser.rb +3 -3
  39. data/lib/sass/selector.rb +3 -15
  40. data/lib/sass/selector/abstract_sequence.rb +2 -11
  41. data/lib/sass/selector/comma_sequence.rb +3 -8
  42. data/lib/sass/selector/sequence.rb +11 -74
  43. data/lib/sass/selector/simple.rb +1 -7
  44. data/lib/sass/selector/simple_sequence.rb +8 -28
  45. data/lib/sass/shared.rb +5 -3
  46. data/lib/sass/tree/comment_node.rb +12 -25
  47. data/lib/sass/tree/debug_node.rb +1 -1
  48. data/lib/sass/tree/directive_node.rb +0 -5
  49. data/lib/sass/tree/each_node.rb +1 -1
  50. data/lib/sass/tree/extend_node.rb +1 -1
  51. data/lib/sass/tree/for_node.rb +2 -2
  52. data/lib/sass/tree/function_node.rb +1 -1
  53. data/lib/sass/tree/if_node.rb +14 -1
  54. data/lib/sass/tree/media_node.rb +4 -4
  55. data/lib/sass/tree/mixin_def_node.rb +1 -1
  56. data/lib/sass/tree/mixin_node.rb +2 -2
  57. data/lib/sass/tree/node.rb +26 -10
  58. data/lib/sass/tree/return_node.rb +1 -1
  59. data/lib/sass/tree/root_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -9
  61. data/lib/sass/tree/variable_node.rb +1 -1
  62. data/lib/sass/tree/visitors/base.rb +1 -1
  63. data/lib/sass/tree/visitors/check_nesting.rb +36 -29
  64. data/lib/sass/tree/visitors/convert.rb +9 -16
  65. data/lib/sass/tree/visitors/cssize.rb +9 -40
  66. data/lib/sass/tree/visitors/perform.rb +23 -79
  67. data/lib/sass/tree/visitors/to_css.rb +21 -23
  68. data/lib/sass/tree/warn_node.rb +1 -1
  69. data/lib/sass/tree/while_node.rb +1 -1
  70. data/lib/sass/util.rb +9 -147
  71. data/lib/sass/version.rb +0 -14
  72. data/test/sass/cache_test.rb +0 -15
  73. data/test/sass/conversion_test.rb +8 -50
  74. data/test/sass/css2sass_test.rb +0 -33
  75. data/test/sass/engine_test.rb +32 -283
  76. data/test/sass/extend_test.rb +0 -315
  77. data/test/sass/functions_test.rb +23 -60
  78. data/test/sass/importer_test.rb +0 -110
  79. data/test/sass/more_results/more_import.css +2 -2
  80. data/test/sass/plugin_test.rb +13 -40
  81. data/test/sass/results/import.css +2 -2
  82. data/test/sass/results/import_charset.css +0 -1
  83. data/test/sass/results/import_charset_1_8.css +0 -1
  84. data/test/sass/results/import_charset_ibm866.css +0 -1
  85. data/test/sass/results/scss_import.css +2 -2
  86. data/test/sass/results/units.css +1 -1
  87. data/test/sass/script_conversion_test.rb +0 -2
  88. data/test/sass/script_test.rb +4 -28
  89. data/test/sass/scss/css_test.rb +1 -79
  90. data/test/sass/scss/scss_test.rb +16 -96
  91. data/test/sass/templates/import_charset.sass +0 -2
  92. data/test/sass/templates/import_charset_1_8.sass +0 -2
  93. data/test/sass/templates/import_charset_ibm866.sass +0 -2
  94. data/test/sass/test_helper.rb +1 -1
  95. data/test/sass/util_test.rb +0 -28
  96. data/test/test_helper.rb +0 -2
  97. data/vendor/{listen → fssm}/LICENSE +1 -1
  98. data/vendor/fssm/README.markdown +55 -0
  99. data/vendor/fssm/Rakefile +59 -0
  100. data/vendor/fssm/VERSION.yml +5 -0
  101. data/vendor/fssm/example.rb +9 -0
  102. data/vendor/fssm/fssm.gemspec +77 -0
  103. data/vendor/fssm/lib/fssm.rb +33 -0
  104. data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  105. data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  106. data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  107. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  108. data/vendor/fssm/lib/fssm/monitor.rb +26 -0
  109. data/vendor/fssm/lib/fssm/path.rb +91 -0
  110. data/vendor/fssm/lib/fssm/pathname.rb +502 -0
  111. data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  112. data/vendor/fssm/lib/fssm/state/file.rb +24 -0
  113. data/vendor/fssm/lib/fssm/support.rb +63 -0
  114. data/vendor/fssm/lib/fssm/tree.rb +176 -0
  115. data/vendor/fssm/profile/prof-cache.rb +40 -0
  116. data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  117. data/vendor/fssm/profile/prof-pathname.rb +68 -0
  118. data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  119. data/vendor/fssm/profile/prof.html +2379 -0
  120. data/vendor/fssm/spec/path_spec.rb +75 -0
  121. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  122. data/vendor/fssm/spec/root/file.css +0 -0
  123. data/vendor/fssm/spec/root/file.rb +0 -0
  124. data/vendor/fssm/spec/root/file.yml +0 -0
  125. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  126. data/vendor/fssm/spec/spec_helper.rb +14 -0
  127. metadata +246 -281
  128. data/VERSION_DATE +0 -1
  129. data/lib/sass/logger.rb +0 -15
  130. data/lib/sass/logger/base.rb +0 -32
  131. data/lib/sass/logger/log_level.rb +0 -49
  132. data/lib/sass/tree/visitors/deep_copy.rb +0 -87
  133. data/lib/sass/tree/visitors/extend.rb +0 -42
  134. data/lib/sass/tree/visitors/set_options.rb +0 -97
  135. data/lib/sass/util/multibyte_string_scanner.rb +0 -134
  136. data/test/Gemfile +0 -4
  137. data/test/Gemfile.lock +0 -19
  138. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  139. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  140. data/test/sass/logger_test.rb +0 -58
  141. data/test/sass/templates/_double_import_loop2.sass +0 -1
  142. data/test/sass/templates/bork5.sass +0 -3
  143. data/test/sass/templates/double_import_loop1.sass +0 -1
  144. data/test/sass/templates/nested_bork5.sass +0 -2
  145. data/test/sass/templates/single_import_loop.sass +0 -1
  146. data/test/sass/util/multibyte_string_scanner_test.rb +0 -147
  147. data/vendor/listen/CHANGELOG.md +0 -147
  148. data/vendor/listen/Gemfile +0 -23
  149. data/vendor/listen/Guardfile +0 -8
  150. data/vendor/listen/README.md +0 -312
  151. data/vendor/listen/Rakefile +0 -47
  152. data/vendor/listen/Vagrantfile +0 -96
  153. data/vendor/listen/lib/listen.rb +0 -38
  154. data/vendor/listen/lib/listen/adapter.rb +0 -167
  155. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -84
  156. data/vendor/listen/lib/listen/adapters/linux.rb +0 -110
  157. data/vendor/listen/lib/listen/adapters/polling.rb +0 -66
  158. data/vendor/listen/lib/listen/adapters/windows.rb +0 -81
  159. data/vendor/listen/lib/listen/directory_record.rb +0 -318
  160. data/vendor/listen/lib/listen/listener.rb +0 -203
  161. data/vendor/listen/lib/listen/multi_listener.rb +0 -121
  162. data/vendor/listen/lib/listen/turnstile.rb +0 -28
  163. data/vendor/listen/lib/listen/version.rb +0 -3
  164. data/vendor/listen/listen.gemspec +0 -26
  165. data/vendor/listen/spec/listen/adapter_spec.rb +0 -142
  166. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -31
  167. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -41
  168. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  169. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -24
  170. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1138
  171. data/vendor/listen/spec/listen/listener_spec.rb +0 -155
  172. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -156
  173. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  174. data/vendor/listen/spec/listen_spec.rb +0 -73
  175. data/vendor/listen/spec/spec_helper.rb +0 -18
  176. data/vendor/listen/spec/support/adapter_helper.rb +0 -716
  177. data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
  178. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  179. data/vendor/listen/spec/support/listeners_helper.rb +0 -144
  180. data/vendor/listen/spec/support/platform_helper.rb +0 -11
@@ -26,7 +26,7 @@ module Sass
26
26
  unless parent
27
27
  @stack = []
28
28
  @mixins_in_use = Set.new
29
- @files_in_use = Set.new
29
+ set_var("important", Script::String.new("!important"))
30
30
  end
31
31
  end
32
32
 
@@ -59,8 +59,7 @@ module Sass
59
59
  else
60
60
  stack.push(top_of_stack = frame_info)
61
61
  end
62
- mixins_in_use << top_of_stack[:mixin] if top_of_stack[:mixin]
63
- files_in_use << top_of_stack[:filename] if top_of_stack[:filename]
62
+ mixins_in_use << top_of_stack[:mixin] if top_of_stack[:mixin] && !top_of_stack[:prepared]
64
63
  end
65
64
 
66
65
  # Like \{#push\_frame}, but next time a stack frame is pushed,
@@ -73,8 +72,9 @@ module Sass
73
72
 
74
73
  # Pop a stack frame from the mixin/include stack.
75
74
  def pop_frame
76
- pop_and_unuse if stack.last && stack.last[:prepared]
77
- pop_and_unuse
75
+ stack.pop if stack.last && stack.last[:prepared]
76
+ popped = stack.pop
77
+ mixins_in_use.delete(popped[:mixin]) if popped && popped[:mixin]
78
78
  end
79
79
 
80
80
  # A list of stack frames in the mixin/include stack.
@@ -93,33 +93,8 @@ module Sass
93
93
  @mixins_in_use ||= @parent.mixins_in_use
94
94
  end
95
95
 
96
- # A set of names of files currently present in the stack.
97
- #
98
- # @return [Set<String>] The filenames.
99
- def files_in_use
100
- @files_in_use ||= @parent.files_in_use
101
- end
102
-
103
- def stack_trace
104
- trace = []
105
- stack.reverse.each_with_index do |entry, i|
106
- msg = "#{i == 0 ? "on" : "from"} line #{entry[:line]}"
107
- msg << " of #{entry[:filename] || "an unknown file"}"
108
- msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
109
- trace << msg
110
- end
111
- trace
112
- end
113
-
114
96
  private
115
97
 
116
- def pop_and_unuse
117
- popped = stack.pop
118
- mixins_in_use.delete(popped[:mixin]) if popped && popped[:mixin]
119
- files_in_use.delete(popped[:filename]) if popped && popped[:filename]
120
- popped
121
- end
122
-
123
98
  def parent_options
124
99
  @parent_options ||= @parent && @parent.options
125
100
  end
@@ -229,10 +229,6 @@ END
229
229
  'Only meaningful for --watch and --update.') do
230
230
  @options[:stop_on_error] = true
231
231
  end
232
- opts.on('-f', '--force', 'Recompile all Sass files, even if the CSS file is newer.',
233
- 'Only meaningful for --update.') do
234
- @options[:force] = true
235
- end
236
232
  opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
237
233
  require 'stringio'
238
234
  @options[:check_syntax] = true
@@ -242,10 +238,6 @@ END
242
238
  'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
243
239
  @options[:for_engine][:style] = name.to_sym
244
240
  end
245
- opts.on('--precision NUMBER_OF_DIGITS', Integer,
246
- 'How many digits of precision to use when outputting decimal numbers. Defaults to 3.') do |precision|
247
- ::Sass::Script::Number.precision = precision
248
- end
249
241
  opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
250
242
  @options[:for_engine][:quiet] = true
251
243
  end
@@ -358,11 +350,6 @@ END
358
350
  ::Sass::Plugin.options.merge! @options[:for_engine]
359
351
  ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
360
352
 
361
- if @options[:force]
362
- raise "The --force flag may only be used with --update." unless @options[:update]
363
- ::Sass::Plugin.options[:always_update] = true
364
- end
365
-
366
353
  raise <<MSG if @args.empty?
367
354
  What files should I watch? Did you mean something like:
368
355
  #{@default_syntax} --watch input.#{@default_syntax}:output.css
@@ -385,11 +372,11 @@ MSG
385
372
 
386
373
  dirs, files = @args.map {|name| split_colon_path(name)}.
387
374
  partition {|i, _| File.directory? i}
388
- files.map! {|from, to| [from, to || from.gsub(/\.[^.]*?$/, '.css')]}
375
+ files.map! {|from, to| [from, to || from.gsub(/\..*?$/, '.css')]}
389
376
  dirs.map! {|from, to| [from, to || from]}
390
377
  ::Sass::Plugin.options[:template_location] = dirs
391
378
 
392
- ::Sass::Plugin.on_updated_stylesheet do |_, css|
379
+ ::Sass::Plugin.on_updating_stylesheet do |_, css|
393
380
  if File.exists? css
394
381
  puts_action :overwrite, :yellow, css
395
382
  else
@@ -404,7 +391,6 @@ MSG
404
391
  raise error unless error.is_a?(::Sass::SyntaxError) && !@options[:stop_on_error]
405
392
  had_error = true
406
393
  puts_action :error, :red, "#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
407
- STDOUT.flush
408
394
  end
409
395
 
410
396
  if @options[:update]
@@ -415,18 +401,9 @@ MSG
415
401
 
416
402
  puts ">>> Sass is watching for changes. Press Ctrl-C to stop."
417
403
 
418
- ::Sass::Plugin.on_template_modified do |template|
419
- puts ">>> Change detected to: #{template}"
420
- STDOUT.flush
421
- end
422
- ::Sass::Plugin.on_template_created do |template|
423
- puts ">>> New template detected: #{template}"
424
- STDOUT.flush
425
- end
426
- ::Sass::Plugin.on_template_deleted do |template|
427
- puts ">>> Deleted template detected: #{template}"
428
- STDOUT.flush
429
- end
404
+ ::Sass::Plugin.on_template_modified {|template| puts ">>> Change detected to: #{template}"}
405
+ ::Sass::Plugin.on_template_created {|template| puts ">>> New template detected: #{template}"}
406
+ ::Sass::Plugin.on_template_deleted {|template| puts ">>> Deleted template detected: #{template}"}
430
407
 
431
408
  ::Sass::Plugin.watch(files)
432
409
  end
@@ -452,7 +429,7 @@ MSG
452
429
  def probably_dest_dir?(path)
453
430
  return false unless path
454
431
  return false if colon_path?(path)
455
- return ::Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
432
+ return Dir.glob(File.join(path, "*.s[ca]ss")).empty?
456
433
  end
457
434
  end
458
435
 
@@ -584,7 +561,7 @@ END
584
561
  end
585
562
 
586
563
  ext = @options[:from]
587
- ::Sass::Util.glob("#{@options[:input]}/**/*.#{ext}") do |f|
564
+ Dir.glob("#{@options[:input]}/**/*.#{ext}") do |f|
588
565
  output =
589
566
  if @options[:in_place]
590
567
  f
@@ -72,8 +72,7 @@ module Sass
72
72
  # If no such files exist, it should return nil.
73
73
  #
74
74
  # The {Sass::Engine} to be returned should be passed `options`,
75
- # with a few modifications. `:syntax` should be set appropriately,
76
- # `:filename` should be set to `uri`,
75
+ # with a few modifications. `:filename` and `:syntax` should be set appropriately,
77
76
  # and `:importer` should be set to this importer.
78
77
  #
79
78
  # @param uri [String] The URI to import.
@@ -13,7 +13,7 @@ module Sass
13
13
  # @param root [String] The root path.
14
14
  # This importer will import files relative to this path.
15
15
  def initialize(root)
16
- @root = File.expand_path(root)
16
+ @root = root
17
17
  end
18
18
 
19
19
  # @see Base#find_relative
@@ -45,21 +45,14 @@ module Sass
45
45
  @root
46
46
  end
47
47
 
48
- def hash
49
- @root.hash
50
- end
51
-
52
- def eql?(other)
53
- root.eql?(other.root)
54
- end
55
-
56
48
  protected
57
49
 
58
50
  # If a full uri is passed, this removes the root from it
59
51
  # otherwise returns the name unchanged
60
52
  def remove_root(name)
61
- if name.index(@root + "/") == 0
62
- name[(@root.length + 1)..-1]
53
+ root = @root.end_with?('/') ? @root : @root + '/'
54
+ if name.index(root) == 0
55
+ name[root.length..-1]
63
56
  else
64
57
  name
65
58
  end
@@ -84,7 +77,6 @@ module Sass
84
77
  # The first element of each pair is a filename to look for;
85
78
  # the second element is the syntax that file would be in (`:sass` or `:scss`).
86
79
  def possible_files(name)
87
- name = escape_glob_characters(name)
88
80
  dirname, basename, extname = split(name)
89
81
  sorted_exts = extensions.sort
90
82
  syntax = extensions[extname]
@@ -93,11 +85,6 @@ module Sass
93
85
  sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
94
86
  end
95
87
 
96
- def escape_glob_characters(name)
97
- name.gsub(/[\*\[\]\{\}\?]/) do |char|
98
- "\\#{char}"
99
- end
100
- end
101
88
 
102
89
  REDUNDANT_DIRECTORY = %r{#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}}
103
90
  # Given a base directory and an `@import`ed name,
@@ -108,7 +95,7 @@ module Sass
108
95
  # @return [(String, Symbol)] A filename-syntax pair.
109
96
  def find_real_file(dir, name)
110
97
  for (f,s) in possible_files(remove_root(name))
111
- path = (dir == "." || Pathname.new(f).absolute?) ? f : "#{dir}/#{f}"
98
+ path = (dir == ".") ? f : "#{dir}/#{f}"
112
99
  if full_path = Dir[path].first
113
100
  full_path.gsub!(REDUNDANT_DIRECTORY,File::SEPARATOR)
114
101
  return full_path, s
@@ -129,6 +116,14 @@ module Sass
129
116
  [dirname, basename, extension]
130
117
  end
131
118
 
119
+ def hash
120
+ @root.hash
121
+ end
122
+
123
+ def eql?(other)
124
+ root.eql?(other.root)
125
+ end
126
+
132
127
  private
133
128
 
134
129
  def _find(dir, name, options)
@@ -31,7 +31,7 @@ module Less
31
31
  WARNING: Sass doesn't support mixing in selector sequences.
32
32
  Replacing "#{sel}" with "@extend #{base}"
33
33
  WARNING
34
- env << Node::SassNode.new(Sass::Tree::CommentNode.new(["// #{sel};"], true, false))
34
+ env << Node::SassNode.new(Sass::Tree::CommentNode.new("// #{sel};", true))
35
35
  env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
36
36
  end
37
37
  end
@@ -92,10 +92,14 @@ module Sass
92
92
  # the second is the location of the CSS file that it should be compiled to.
93
93
  # @see #update_stylesheets
94
94
  def force_update_stylesheets(individual_files = [])
95
- Compiler.new(options.dup.merge(
96
- :never_update => false,
97
- :always_update => true,
98
- :cache => false)).update_stylesheets(individual_files)
95
+ old_options = options
96
+ self.options = options.dup
97
+ options[:never_update] = false
98
+ options[:always_update] = true
99
+ options[:cache] = false
100
+ update_stylesheets(individual_files)
101
+ ensure
102
+ self.options = old_options
99
103
  end
100
104
 
101
105
  # All other method invocations are proxied to the \{#compiler}.
@@ -38,7 +38,7 @@ module Sass::Plugin
38
38
  self.options.merge!(options)
39
39
  end
40
40
 
41
- # Register a callback to be run after stylesheets are mass-updated.
41
+ # Register a callback to be run before stylesheets are mass-updated.
42
42
  # This is run whenever \{#update\_stylesheets} is called,
43
43
  # unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
44
44
  # is enabled.
@@ -51,22 +51,6 @@ module Sass::Plugin
51
51
  # the second is the target CSS file.
52
52
  define_callback :updating_stylesheets
53
53
 
54
- # Register a callback to be run after a single stylesheet is updated.
55
- # The callback is only run if the stylesheet is really updated;
56
- # if the CSS file is fresh, this won't be run.
57
- #
58
- # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
59
- # is enabled, this callback won't be run
60
- # when an exception CSS file is being written.
61
- # To run an action for those files, use \{#on\_compilation\_error}.
62
- #
63
- # @yield [template, css]
64
- # @yieldparam template [String]
65
- # The location of the Sass/SCSS file being updated.
66
- # @yieldparam css [String]
67
- # The location of the CSS file being generated.
68
- define_callback :updated_stylesheet
69
-
70
54
  # Register a callback to be run before a single stylesheet is updated.
71
55
  # The callback is only run if the stylesheet is guaranteed to be updated;
72
56
  # if the CSS file is fresh, this won't be run.
@@ -83,13 +67,6 @@ module Sass::Plugin
83
67
  # The location of the CSS file being generated.
84
68
  define_callback :updating_stylesheet
85
69
 
86
- def on_updating_stylesheet_with_deprecation_warning(&block)
87
- Sass::Util.sass_warn("Sass::Compiler#on_updating_stylesheet callback is deprecated and will be removed in a future release. Use Sass::Compiler#on_updated_stylesheet instead, which is run after stylesheet compilation.")
88
- on_updating_stylesheet_without_deprecation_warning(&block)
89
- end
90
- alias_method :on_updating_stylesheet_without_deprecation_warning, :on_updating_stylesheet
91
- alias_method :on_updating_stylesheet, :on_updating_stylesheet_with_deprecation_warning
92
-
93
70
  # Register a callback to be run when Sass decides not to update a stylesheet.
94
71
  # In particular, the callback is run when Sass finds that
95
72
  # the template file and none of its dependencies
@@ -183,25 +160,28 @@ module Sass::Plugin
183
160
  # The first string in each pair is the location of the Sass/SCSS file,
184
161
  # the second is the location of the CSS file that it should be compiled to.
185
162
  def update_stylesheets(individual_files = [])
163
+ run_updating_stylesheets individual_files
186
164
  Sass::Plugin.checked_for_updates = true
187
165
  staleness_checker = StalenessChecker.new(engine_options)
188
166
 
167
+ individual_files.each do |t, c|
168
+ if options[:always_update] || staleness_checker.stylesheet_needs_update?(c, t)
169
+ update_stylesheet(t, c)
170
+ end
171
+ end
172
+
189
173
  template_location_array.each do |template_location, css_location|
190
- Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
174
+
175
+ Dir.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
191
176
  # Get the relative path to the file
192
177
  name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
193
178
  css = css_filename(name, css_location)
194
- individual_files << [file, css]
195
- end
196
- end
197
-
198
- run_updating_stylesheets individual_files
199
179
 
200
- individual_files.each do |file, css|
201
- if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
202
- update_stylesheet(file, css)
203
- else
204
- run_not_updating_stylesheet(file, css)
180
+ if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
181
+ update_stylesheet file, css
182
+ else
183
+ run_not_updating_stylesheet file, css
184
+ end
205
185
  end
206
186
  end
207
187
  end
@@ -218,10 +198,10 @@ module Sass::Plugin
218
198
  #
219
199
  # Before the watching starts in earnest, `watch` calls \{#update\_stylesheets}.
220
200
  #
221
- # Note that `watch` uses the [Listen](http://github.com/guard/listen) library
201
+ # Note that `watch` uses the [FSSM](http://github.com/ttilley/fssm) library
222
202
  # to monitor the filesystem for changes.
223
- # Listen isn't loaded until `watch` is run.
224
- # The version of Listen distributed with Sass is loaded by default,
203
+ # FSSM isn't loaded until `watch` is run.
204
+ # The version of FSSM distributed with Sass is loaded by default,
225
205
  # but if another version has already been loaded that will be used instead.
226
206
  #
227
207
  # @param individual_files [Array<(String, String)>]
@@ -234,15 +214,15 @@ module Sass::Plugin
234
214
  update_stylesheets(individual_files)
235
215
 
236
216
  begin
237
- require 'listen'
217
+ require 'fssm'
238
218
  rescue LoadError => e
239
- dir = Sass::Util.scope("vendor/listen/lib")
219
+ dir = Sass::Util.scope("vendor/fssm/lib")
240
220
  if $LOAD_PATH.include?(dir)
241
221
  e.message << "\n" <<
242
222
  if File.exists?(scope(".git"))
243
223
  'Run "git submodule update --init" to get the recommended version.'
244
224
  else
245
- 'Run "gem install listen" to get it.'
225
+ 'Run "gem install fssm" to get it.'
246
226
  end
247
227
  raise e
248
228
  else
@@ -251,61 +231,60 @@ module Sass::Plugin
251
231
  end
252
232
  end
253
233
 
254
- template_paths = template_locations # cache the locations
255
- individual_files_hash = individual_files.inject({}) do |h, files|
256
- parent = File.dirname(files.first)
257
- (h[parent] ||= []) << files unless template_paths.include?(parent)
258
- h
234
+ unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents"
235
+ # As of FSSM 0.1.4, it doesn't support FSevents on individual files,
236
+ # but it also isn't smart enough to switch to polling itself.
237
+ require 'fssm/backends/polling'
238
+ Sass::Util.silence_warnings do
239
+ FSSM::Backends.const_set(:Default, FSSM::Backends::Polling)
240
+ end
259
241
  end
260
- directories = template_paths + individual_files_hash.keys +
261
- [{:relative_paths => true}]
262
242
 
263
243
  # TODO: Keep better track of what depends on what
264
244
  # so we don't have to run a global update every time anything changes.
265
- listener = Listen::MultiListener.new(*directories) do |modified, added, removed|
266
- modified.each do |f|
267
- parent = File.dirname(f)
268
- if files = individual_files_hash[parent]
269
- next unless files.first == f
270
- else
271
- next unless f =~ /\.s[ac]ss$/
272
- end
273
- run_template_modified(f)
274
- end
245
+ FSSM.monitor do |mon|
246
+ template_location_array.each do |template_location, css_location|
247
+ mon.path template_location do |path|
248
+ path.glob '**/*.s[ac]ss'
249
+
250
+ path.update do |base, relative|
251
+ run_template_modified File.join(base, relative)
252
+ update_stylesheets(individual_files)
253
+ end
275
254
 
276
- added.each do |f|
277
- parent = File.dirname(f)
278
- if files = individual_files_hash[parent]
279
- next unless files.first == f
280
- else
281
- next unless f =~ /\.s[ac]ss$/
282
- end
283
- run_template_created(f)
284
- end
255
+ path.create do |base, relative|
256
+ run_template_created File.join(base, relative)
257
+ update_stylesheets(individual_files)
258
+ end
285
259
 
286
- removed.each do |f|
287
- parent = File.dirname(f)
288
- if files = individual_files_hash[parent]
289
- next unless files.first == f
290
- try_delete_css files[1]
291
- else
292
- next unless f =~ /\.s[ac]ss$/
293
- try_delete_css f.gsub(/\.s[ac]ss$/, '.css')
260
+ path.delete do |base, relative|
261
+ run_template_deleted File.join(base, relative)
262
+ css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
263
+ try_delete_css css
264
+ update_stylesheets(individual_files)
265
+ end
294
266
  end
295
- run_template_deleted(f)
296
267
  end
297
268
 
298
- update_stylesheets(individual_files)
299
- end
269
+ individual_files.each do |template, css|
270
+ mon.file template do |path|
271
+ path.update do
272
+ run_template_modified template
273
+ update_stylesheets(individual_files)
274
+ end
300
275
 
301
- # The native windows listener is much slower than the polling
302
- # option, according to https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e#commitcomment-1295118
303
- listener.force_polling(true) if Sass::Util.windows?
276
+ path.create do
277
+ run_template_created template
278
+ update_stylesheets(individual_files)
279
+ end
304
280
 
305
- begin
306
- listener.start
307
- rescue Exception => e
308
- raise e unless e.is_a?(Interrupt)
281
+ path.delete do
282
+ run_template_deleted template
283
+ try_delete_css css
284
+ update_stylesheets(individual_files)
285
+ end
286
+ end
287
+ end
309
288
  end
310
289
  end
311
290
 
@@ -339,23 +318,18 @@ module Sass::Plugin
339
318
  engine_opts = engine_options(:css_filename => css, :filename => filename)
340
319
  result = Sass::Engine.for_file(filename, engine_opts).render
341
320
  rescue Exception => e
342
- compilation_error_occured = true
343
321
  run_compilation_error e, filename, css
344
322
  result = Sass::SyntaxError.exception_to_css(e, options)
345
323
  else
346
324
  run_updating_stylesheet filename, css
347
325
  end
348
326
 
349
- write_file(css, result)
350
- run_updated_stylesheet(filename, css) unless compilation_error_occured
351
- end
352
-
353
- def write_file(css, content)
327
+ # Finally, write the file
354
328
  flag = 'w'
355
329
  flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
356
330
  File.open(css, flag) do |file|
357
- file.set_encoding(content.encoding) unless Sass::Util.ruby1_8?
358
- file.print(content)
331
+ file.set_encoding(result.encoding) unless Sass::Util.ruby1_8?
332
+ file.print(result)
359
333
  end
360
334
  end
361
335