haml-edge 2.3.198 → 2.3.199

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.
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