haml-edge 2.3.198 → 2.3.199

Sign up to get free protection for your applications and to get access to all the features.
data/EDGE_GEM_VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.198
1
+ 2.3.199
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.198
1
+ 2.3.199
@@ -0,0 +1,123 @@
1
+ module Sass
2
+ module Plugin
3
+ # The class handles `.s[ca]ss` file staleness checks via their mtime timestamps.
4
+ #
5
+ # To speed things up two level of caches are employed:
6
+ #
7
+ # * A class-level dependency cache which stores @import paths for each file.
8
+ # This is a long-lived cache that is reused by every StalenessChecker instance.
9
+ # * Two short-lived instance-level caches, one for file mtimes
10
+ # and one for whether a file is stale during this particular run.
11
+ # These are only used by a single StalenessChecker instance.
12
+ #
13
+ # Usage:
14
+ #
15
+ # * For a one-off staleness check of a single `.s[ca]ss` file,
16
+ # the class-level {stylesheet_needs_update?} method
17
+ # should be used.
18
+ # * For a series of staleness checks (e.g. checking all files for staleness)
19
+ # a StalenessChecker instance should be created,
20
+ # and the instance-level \{#stylesheet\_needs\_update?} method should be used.
21
+ # the caches should make the whole process significantly faster.
22
+ # *WARNING*: It is important not to retain the instance for too long,
23
+ # as its instance-level caches are never explicitly expired.
24
+ class StalenessChecker
25
+ @dependencies_cache = {}
26
+
27
+ class << self
28
+ # @private
29
+ attr_accessor :dependencies_cache
30
+ end
31
+
32
+ # Creates a new StalenessChecker
33
+ # for checking the staleness of several stylesheets at once.
34
+ def initialize
35
+ @dependencies = self.class.dependencies_cache
36
+
37
+ # Entries in the following instance-level caches are never explicitly expired.
38
+ # Instead they are supposed to automaticaly go out of scope when a series of staleness checks
39
+ # (this instance of StalenessChecker was created for) is finished.
40
+ @mtimes, @dependencies_stale = {}, {}
41
+ end
42
+
43
+ # Returns whether or not a given CSS file is out of date
44
+ # and needs to be regenerated.
45
+ #
46
+ # @param css_file [String] The location of the CSS file to check.
47
+ # @param template_file [String] The location of the Sass or SCSS template
48
+ # that is compiled to `css_file`.
49
+ def stylesheet_needs_update?(css_file, template_file)
50
+ template_file = File.expand_path(template_file)
51
+
52
+ unless File.exists?(css_file) && File.exists?(template_file)
53
+ @dependencies.delete(template_file)
54
+ true
55
+ else
56
+ css_mtime = mtime(css_file)
57
+ mtime(template_file) > css_mtime || dependencies_stale?(template_file, css_mtime)
58
+ end
59
+ end
60
+
61
+ # Returns whether or not a given CSS file is out of date
62
+ # and needs to be regenerated.
63
+ #
64
+ # The distinction between this method and the instance-level \{#stylesheet\_needs\_update?}
65
+ # is that the instance method preserves mtime and stale-dependency caches,
66
+ # so it's better to use when checking multiple stylesheets at once.
67
+ #
68
+ # @param css_file [String] The location of the CSS file to check.
69
+ # @param template_file [String] The location of the Sass or SCSS template
70
+ # that is compiled to `css_file`.
71
+ def self.stylesheet_needs_update?(css_file, template_file)
72
+ new.stylesheet_needs_update?(css_file, template_file)
73
+ end
74
+
75
+ private
76
+
77
+ def dependencies_stale?(template_file, css_mtime)
78
+ timestamps = @dependencies_stale[template_file] ||= {}
79
+ timestamps.each_pair do |checked_css_mtime, is_stale|
80
+ if checked_css_mtime <= css_mtime && !is_stale
81
+ return false
82
+ elsif checked_css_mtime > css_mtime && is_stale
83
+ return true
84
+ end
85
+ end
86
+ timestamps[css_mtime] = dependencies(template_file).any?(&dependency_updated?(css_mtime))
87
+ end
88
+
89
+ def mtime(filename)
90
+ @mtimes[filename] ||= File.mtime(filename)
91
+ end
92
+
93
+ def dependencies(filename)
94
+ stored_mtime, dependencies = @dependencies[filename]
95
+
96
+ if !stored_mtime || stored_mtime < mtime(filename)
97
+ @dependencies[filename] = [mtime(filename), dependencies = compute_dependencies(filename)]
98
+ end
99
+
100
+ dependencies
101
+ end
102
+
103
+ def dependency_updated?(css_mtime)
104
+ lambda do |dep|
105
+ begin
106
+ mtime(dep) > css_mtime || dependencies_stale?(dep, css_mtime)
107
+ rescue Sass::SyntaxError
108
+ # If there's an error finding depenencies, default to recompiling.
109
+ true
110
+ end
111
+ end
112
+ end
113
+
114
+ def compute_dependencies(filename)
115
+ Files.tree_for(filename, Plugin.engine_options).grep(Tree::ImportNode) do |n|
116
+ File.expand_path(n.full_filename) unless n.full_filename =~ /\.css$/
117
+ end.compact
118
+ rescue Sass::SyntaxError => e
119
+ [] # If the file has an error, we assume it has no dependencies
120
+ end
121
+ end
122
+ end
123
+ end
data/lib/sass/plugin.rb CHANGED
@@ -3,6 +3,7 @@ require 'rbconfig'
3
3
 
4
4
  require 'sass'
5
5
  require 'sass/callbacks'
6
+ require 'sass/plugin/staleness_checker'
6
7
 
7
8
  module Sass
8
9
  # This module handles the compilation of Sass/SCSS files.
@@ -211,6 +212,8 @@ module Sass
211
212
  individual_files.each {|t, c| update_stylesheet(t, c)}
212
213
 
213
214
  @checked_for_updates = true
215
+ staleness_checker = StalenessChecker.new
216
+
214
217
  template_locations.zip(css_locations).each do |template_location, css_location|
215
218
 
216
219
  Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).each do |file|
@@ -219,7 +222,7 @@ module Sass
219
222
  css = css_filename(name, css_location)
220
223
 
221
224
  next if forbid_update?(name)
222
- if options[:always_update] || stylesheet_needs_update?(css, file)
225
+ if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
223
226
  update_stylesheet file, css
224
227
  else
225
228
  run_not_updating_stylesheet file, css
@@ -374,33 +377,9 @@ module Sass
374
377
  name.sub(/^.*\//, '')[0] == ?_
375
378
  end
376
379
 
380
+ # Compass expects this to exist
377
381
  def stylesheet_needs_update?(css_file, template_file)
378
- return true unless File.exists?(css_file) && File.exists?(template_file)
379
-
380
- css_mtime = File.mtime(css_file)
381
- File.mtime(template_file) > css_mtime ||
382
- dependencies(template_file).any?(&dependency_updated?(css_mtime))
383
- end
384
-
385
- def dependency_updated?(css_mtime)
386
- lambda do |dep|
387
- begin
388
- File.mtime(dep) > css_mtime ||
389
- dependencies(dep).any?(&dependency_updated?(css_mtime))
390
- rescue Sass::SyntaxError
391
- # If there's an error finding depenencies, default to recompiling.
392
- true
393
- end
394
- end
395
- end
396
-
397
- def dependencies(filename)
398
- Files.tree_for(filename, engine_options).select {|n| n.is_a?(Tree::ImportNode)}.map do |n|
399
- next if n.full_filename =~ /\.css$/
400
- n.full_filename
401
- end.compact
402
- rescue Sass::SyntaxError => e
403
- [] # If the file has an error, we assume it has no dependencies
382
+ StalenessChecker.stylesheet_needs_update?(css_file, template_file)
404
383
  end
405
384
  end
406
385
  end
@@ -347,12 +347,12 @@ CSS
347
347
  end
348
348
 
349
349
  def assert_needs_update(name)
350
- assert(Sass::Plugin.stylesheet_needs_update?(tempfile_loc(name), template_loc(name)),
350
+ assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(name), template_loc(name)),
351
351
  "Expected #{template_loc(name)} to need an update.")
352
352
  end
353
353
 
354
354
  def assert_doesnt_need_update(name)
355
- assert(!Sass::Plugin.stylesheet_needs_update?(tempfile_loc(name), template_loc(name)),
355
+ assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(name), template_loc(name)),
356
356
  "Expected #{template_loc(name)} not to need an update.")
357
357
  end
358
358
 
@@ -361,6 +361,7 @@ CSS
361
361
  end
362
362
 
363
363
  def reset_mtimes
364
+ Sass::Plugin::StalenessChecker.dependencies_cache = {}
364
365
  atime = Time.now
365
366
  mtime = Time.now - 5
366
367
  Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
@@ -407,12 +408,6 @@ CSS
407
408
  end
408
409
  end
409
410
 
410
- module Sass::Plugin
411
- class << self
412
- public :stylesheet_needs_update?
413
- end
414
- end
415
-
416
411
  class Sass::Engine
417
412
  alias_method :old_render, :render
418
413
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.198
4
+ version: 2.3.199
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -85,6 +85,7 @@ files:
85
85
  - lib/sass/plugin/merb.rb
86
86
  - lib/sass/plugin/rack.rb
87
87
  - lib/sass/plugin/rails.rb
88
+ - lib/sass/plugin/staleness_checker.rb
88
89
  - lib/sass/script.rb
89
90
  - lib/sass/scss.rb
90
91
  - lib/sass/script/bool.rb