haml-edge 3.1.73 → 3.1.74

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
- 3.1.73
1
+ 3.1.74
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.73
1
+ 3.1.74
data/lib/haml/exec.rb CHANGED
@@ -281,19 +281,19 @@ END
281
281
  output = @options[:output]
282
282
 
283
283
  @options[:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
284
- tree =
284
+ engine =
285
285
  if input.is_a?(File) && !@options[:check_syntax]
286
- ::Sass::Files.tree_for(input.path, @options[:for_engine])
286
+ ::Sass::Files.engine_for(input.path, @options[:for_engine])
287
287
  else
288
288
  # We don't need to do any special handling of @options[:check_syntax] here,
289
289
  # because the Sass syntax checking happens alongside evaluation
290
290
  # and evaluation doesn't actually evaluate any code anyway.
291
- ::Sass::Engine.new(input.read(), @options[:for_engine]).to_tree
291
+ ::Sass::Engine.new(input.read(), @options[:for_engine])
292
292
  end
293
293
 
294
294
  input.close() if input.is_a?(File)
295
295
 
296
- output.write(tree.render)
296
+ output.write(engine.render)
297
297
  output.close() if output.is_a? File
298
298
  rescue ::Sass::SyntaxError => e
299
299
  raise e if @options[:trace]
@@ -769,10 +769,10 @@ END
769
769
  Less::Engine.new(input).to_tree.to_sass_tree.send("to_#{@options[:to]}", @options[:for_tree])
770
770
  else
771
771
  if input.is_a?(File)
772
- ::Sass::Files.tree_for(input.path, @options[:for_engine])
772
+ ::Sass::Files.engine_for(input.path, @options[:for_engine])
773
773
  else
774
- ::Sass::Engine.new(input.read, @options[:for_engine]).to_tree
775
- end.send("to_#{@options[:to]}", @options[:for_tree])
774
+ ::Sass::Engine.new(input.read, @options[:for_engine])
775
+ end.to_tree.send("to_#{@options[:to]}", @options[:for_tree])
776
776
  end
777
777
  end
778
778
 
data/lib/haml/util.rb CHANGED
@@ -263,6 +263,43 @@ module Haml
263
263
  version_gt(v1, v2) || !version_gt(v2, v1)
264
264
  end
265
265
 
266
+ # A wrapper for `Marshal.dump` that calls `#_before_dump` on the object
267
+ # before dumping it, `#_after_dump` afterwards.
268
+ # It also calls `#_around_dump` and passes it a block in which the object is dumped.
269
+ #
270
+ # If any of these methods are undefined, they are not called.
271
+ #
272
+ # @param obj [Object] The object to dump.
273
+ # @return [String] The dumped data.
274
+ def dump(obj)
275
+ obj._before_dump if obj.respond_to?(:_before_dump)
276
+ return Marshal.dump(obj) unless obj.respond_to?(:_around_dump)
277
+ res = nil
278
+ obj._around_dump {res = Marshal.dump(obj)}
279
+ res
280
+ ensure
281
+ obj._after_dump if obj.respond_to?(:_after_dump)
282
+ end
283
+
284
+ # A wrapper for `Marshal.load` that calls `#_after_load` on the object
285
+ # after loading it, if it's defined.
286
+ #
287
+ # @param data [String] The data to load.
288
+ # @return [Object] The loaded object.
289
+ def load(data)
290
+ obj = Marshal.load(data)
291
+ obj._after_load if obj.respond_to?(:_after_load)
292
+ obj
293
+ end
294
+
295
+ # Throws a NotImplementedError for an abstract method.
296
+ #
297
+ # @param obj [Object] `self`
298
+ # @raise [NotImplementedError]
299
+ def abstract(obj)
300
+ raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
301
+ end
302
+
266
303
  # Silence all output to STDERR within a block.
267
304
  #
268
305
  # @yield A block in which no output will be printed to STDERR
@@ -0,0 +1,213 @@
1
+ require 'stringio'
2
+
3
+ module Sass
4
+ # An abstract base class for backends for the Sass cache.
5
+ # Any key-value store can act as such a backend;
6
+ # it just needs to implement the
7
+ # \{#_store} and \{#_retrieve} methods.
8
+ #
9
+ # To use a cache store with Sass,
10
+ # use the {file:SASS_REFERENCE.md#cache_store-option `:cache_store` option}.
11
+ class CacheStore
12
+ # Store cached contents for later retrieval
13
+ # Must be implemented by all CacheStore subclasses
14
+ #
15
+ # Note: cache contents contain binary data.
16
+ #
17
+ # @param key [String] The key to store the contents under
18
+ # @param version [String] The current sass version.
19
+ # Cached contents must not be retrieved across different versions of sass.
20
+ # @param sha [String] The sha of the sass source.
21
+ # Cached contents must not be retrieved if the sha has changed.
22
+ # @param contents [String] The contents to store.
23
+ def _store(key, version, sha, contents)
24
+ raise "#{self.class} must implement #_store."
25
+ end
26
+
27
+ # Retrieved cached contents.
28
+ # Must be implemented by all subclasses.
29
+ #
30
+ # Note: if the key exists but the sha or version have changed,
31
+ # then the key may be deleted by the cache store, if it wants to do so.
32
+ #
33
+ # @param key [String] The key to retrieve
34
+ # @param version [String] The current sass version.
35
+ # Cached contents must not be retrieved across different versions of sass.
36
+ # @param sha [String] The sha of the sass source.
37
+ # Cached contents must not be retrieved if the sha has changed.
38
+ # @return [String] The contents that were previously stored.
39
+ # @return [NilClass] when the cache key is not found or the version or sha have changed.
40
+ def _retrieve(key, version, sha)
41
+ raise "#{self.class} must implement #_retrieve."
42
+ end
43
+
44
+ # Store a {Sass::Tree::RootNode}.
45
+ #
46
+ # @param key [String] The key to store it under.
47
+ # @param sha [String] The checksum for the contents that are being stored.
48
+ # @param root [Sass::Tree::RootNode] The root of the tree to be stored.
49
+ def store(key, sha, root)
50
+ orig_options = root.options
51
+ begin
52
+ _store(key, Sass::VERSION, sha, Haml::Util.dump(root))
53
+ ensure
54
+ root.options = orig_options
55
+ end
56
+ end
57
+
58
+ # Retrieve a {Sass::Tree::RootNode}.
59
+ #
60
+ # @param key [String] The key the root element was stored under.
61
+ # @param sha [String] The checksum of the root element's content.
62
+ # @return [Sass::Tree::RootNode] The root node.
63
+ def retrieve(key, sha)
64
+ contents = _retrieve(key, Sass::VERSION, sha)
65
+ Haml::Util.load(contents) if contents
66
+ rescue EOFError, TypeError, ArgumentError => e
67
+ raise
68
+ Haml::Util.haml_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
69
+ end
70
+
71
+ # Return the key for the sass file.
72
+ #
73
+ # The `(sass_dirname, sass_basename)` pair
74
+ # should uniquely identify the Sass document,
75
+ # but otherwise there are no restrictions on their content.
76
+ #
77
+ # @param sass_dirname [String]
78
+ # The fully-expanded location of the Sass file.
79
+ # This corresponds to the directory name on a filesystem.
80
+ # @param sass_basename [String] The name of the Sass file that is being referenced.
81
+ # This corresponds to the basename on a filesystem.
82
+ def key(sass_dirname, sass_basename)
83
+ dir = Digest::SHA1.hexdigest(sass_dirname)
84
+ filename = "#{sass_basename}c"
85
+ "#{dir}/#{filename}"
86
+ end
87
+ end
88
+
89
+ # A backend for the Sass cache using the filesystem.
90
+ class FileCacheStore < CacheStore
91
+ # The directory where the cached files will be stored.
92
+ #
93
+ # @return [String]
94
+ attr_accessor :cache_location
95
+
96
+ # Create a new FileCacheStore.
97
+ #
98
+ # @param cache_location [String] see \{#cache\_location}
99
+ def initialize(cache_location)
100
+ @cache_location = cache_location
101
+ end
102
+
103
+ # @see {CacheStore#\_retrieve\_}
104
+ def _retrieve(key, version, sha)
105
+ return unless File.readable?(path_to(key))
106
+ contents = nil
107
+ File.open(path_to(key), "rb") do |f|
108
+ if f.readline("\n").strip == version && f.readline("\n").strip == sha
109
+ return f.read
110
+ end
111
+ end
112
+ File.unlink path_to(key)
113
+ nil
114
+ rescue EOFError, TypeError, ArgumentError => e
115
+ Haml::Util.haml_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
116
+ end
117
+
118
+ # @see {CacheStore#\_store\_}
119
+ def _store(key, version, sha, contents)
120
+ return unless File.writable?(File.dirname(@cache_location))
121
+ return if File.exists?(@cache_location) && !File.writable?(@cache_location)
122
+ compiled_filename = path_to(key)
123
+ return if File.exists?(File.dirname(compiled_filename)) && !File.writable?(File.dirname(compiled_filename))
124
+ return if File.exists?(compiled_filename) && !File.writable?(compiled_filename)
125
+ FileUtils.mkdir_p(File.dirname(compiled_filename))
126
+ File.open(compiled_filename, "wb") do |f|
127
+ f.puts(version)
128
+ f.puts(sha)
129
+ f.write(contents)
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ # Returns the path to a file for the given key.
136
+ #
137
+ # @param key [String]
138
+ # @return [String] The path to the cache file.
139
+ def path_to(key)
140
+ File.join(cache_location, key)
141
+ end
142
+ end
143
+
144
+ # A backend for the Sass cache using in-process memory.
145
+ class InMemoryCacheStore < CacheStore
146
+ # Since the {InMemoryCacheStore} is stored in the Sass tree's options hash,
147
+ # when the options get serialized as part of serializing the tree,
148
+ # you get crazy exponential growth in the size of the cached objects
149
+ # unless you don't dump the cache.
150
+ #
151
+ # @private
152
+ def _dump(depth)
153
+ ""
154
+ end
155
+
156
+ # If we deserialize this class, just make a new empty one.
157
+ #
158
+ # @private
159
+ def self._load(repr)
160
+ InMemoryCacheStore.new
161
+ end
162
+
163
+ # Create a new, empty cache store.
164
+ def initialize
165
+ @contents = {}
166
+ end
167
+
168
+ # @see CacheStore#_retrieve
169
+ def _retrieve(key, version, sha)
170
+ if @contents.has_key?(key)
171
+ return unless @contents[key][:version] == version
172
+ return unless @contents[key][:sha] == sha
173
+ return @contents[key][:contents]
174
+ end
175
+ end
176
+
177
+ # @see CacheStore#_store
178
+ def _store(key, version, sha, contents)
179
+ @contents[key] = {
180
+ :version => version,
181
+ :sha => sha,
182
+ :contents => contents
183
+ }
184
+ end
185
+
186
+ # Destructively clear the cache.
187
+ def reset!
188
+ @contents = {}
189
+ end
190
+ end
191
+
192
+ # Doesn't store anything, but records what things it should have stored.
193
+ # This doesn't currently have any use except for testing and debugging.
194
+ #
195
+ # @private
196
+ class NullCacheStore < CacheStore
197
+ def initialize
198
+ @keys = {}
199
+ end
200
+
201
+ def _retrieve(key, version, sha)
202
+ nil
203
+ end
204
+
205
+ def _store(key, version, sha, contents)
206
+ @keys[key] = true
207
+ end
208
+
209
+ def was_set?(key)
210
+ @keys[key]
211
+ end
212
+ end
213
+ end
@@ -23,8 +23,22 @@ module Sass
23
23
  # m.on_string_munged {|str, res| puts "#{str} was munged into #{res}!"}
24
24
  # m.munge "bar" #=> bar was munged into bbaarr!
25
25
  module Callbacks
26
+ # Automatically includes {InstanceMethods}
27
+ # when something extends this module.
28
+ #
29
+ # @param base [Module]
30
+ def self.extended(base)
31
+ base.send(:include, InstanceMethods)
32
+ end
26
33
  protected
27
34
 
35
+ module InstanceMethods
36
+ # Removes all callbacks registered against this object.
37
+ def clear_callbacks!
38
+ @_sass_callbacks = {}
39
+ end
40
+ end
41
+
28
42
  # Define a callback with the given name.
29
43
  # This will define an `on_#{name}` method
30
44
  # that registers a block,
data/lib/sass/engine.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'strscan'
2
2
  require 'digest/sha1'
3
+ require 'sass/cache_store'
3
4
  require 'sass/tree/node'
4
5
  require 'sass/tree/root_node'
5
6
  require 'sass/tree/rule_node'
@@ -21,10 +22,11 @@ require 'sass/environment'
21
22
  require 'sass/script'
22
23
  require 'sass/scss'
23
24
  require 'sass/error'
24
- require 'sass/files'
25
+ require 'sass/importers'
25
26
  require 'haml/shared'
26
27
 
27
28
  module Sass
29
+
28
30
  # A Sass mixin.
29
31
  #
30
32
  # `name`: `String`
@@ -130,30 +132,94 @@ module Sass
130
132
  :cache => true,
131
133
  :cache_location => './.sass-cache',
132
134
  :syntax => :sass,
135
+ :filesystem_importer => Sass::Importers::Filesystem
133
136
  }.freeze
134
137
 
138
+ # Converts a Sass options hash into a standard form, filling in
139
+ # default values and resolving aliases.
140
+ #
141
+ # @param options [{Symbol => Object}] The options hash;
142
+ # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
143
+ # @return [{Symbol => Object}] The normalized options hash.
144
+ # @private
145
+ def self.normalize_options(options)
146
+ options = DEFAULT_OPTIONS.merge(options.reject {|k, v| v.nil?})
147
+
148
+ # If the `:filename` option is passed in without an importer,
149
+ # assume it's using the default filesystem importer.
150
+ options[:importer] ||= options[:filesystem_importer].new(".") if options[:filename]
151
+
152
+ options[:cache_store] ||= Sass::FileCacheStore.new(options[:cache_location])
153
+ # Support both, because the docs said one and the other actually worked
154
+ # for quite a long time.
155
+ options[:line_comments] ||= options[:line_numbers]
156
+
157
+ options[:load_paths] = options[:load_paths].map do |p|
158
+ next p unless p.is_a?(String)
159
+ options[:filesystem_importer].new(p)
160
+ end
161
+
162
+ # Backwards compatibility
163
+ options[:property_syntax] ||= options[:attribute_syntax]
164
+ case options[:property_syntax]
165
+ when :alternate; options[:property_syntax] = :new
166
+ when :normal; options[:property_syntax] = :old
167
+ end
168
+
169
+ options
170
+ end
171
+
172
+ # Returns the {Sass::Engine} for the given file.
173
+ # This is preferable to Sass::Engine.new when reading from a file
174
+ # because it properly sets up the Engine's metadata,
175
+ # enables parse-tree caching,
176
+ # and infers the syntax from the filename.
177
+ #
178
+ # @param filename [String] The path to the Sass or SCSS file
179
+ # @param options [{Symbol => Object}] The options hash;
180
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
181
+ # @return [Sass::Engine] The Engine for the given Sass or SCSS file.
182
+ # @raise [Sass::SyntaxError] if there's an error in the document.
183
+ def self.for_file(filename, options)
184
+ had_syntax = options[:syntax]
185
+
186
+ if had_syntax
187
+ # Use what was explicitly specificed
188
+ elsif filename =~ /\.scss$/
189
+ options.merge!(:syntax => :scss)
190
+ elsif filename =~ /\.sass$/
191
+ options.merge!(:syntax => :sass)
192
+ end
193
+
194
+ Sass::Engine.new(File.read(filename), options.merge(:filename => filename))
195
+ end
196
+
197
+ # The options for the Sass engine.
198
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
199
+ #
200
+ # @return [{Symbol => Object}]
201
+ attr_reader :options
202
+
203
+ # Creates a new Engine. Note that Engine should only be used directly
204
+ # when compiling in-memory Sass code.
205
+ # If you're compiling a single Sass file from the filesystem,
206
+ # use \{Sass::Engine.for\_file}.
207
+ # If you're compiling multiple files from the filesystem,
208
+ # use {Sass::Plugin.
209
+ #
135
210
  # @param template [String] The Sass template.
136
211
  # This template can be encoded using any encoding
137
212
  # that can be converted to Unicode.
138
213
  # If the template contains an `@charset` declaration,
139
214
  # that overrides the Ruby encoding
140
215
  # (see {file:SASS_REFERENCE.md#encodings the encoding documentation})
141
- # @param options [{Symbol => Object}] An options hash;
142
- # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
216
+ # @param options [{Symbol => Object}] An options hash.
217
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
218
+ # @see {Sass::Engine.for_file}
219
+ # @see {Sass::Plugin}
143
220
  def initialize(template, options={})
144
- @options = DEFAULT_OPTIONS.merge(options.reject {|k, v| v.nil?})
221
+ @options = self.class.normalize_options(options)
145
222
  @template = template
146
-
147
- # Support both, because the docs said one and the other actually worked
148
- # for quite a long time.
149
- @options[:line_comments] ||= @options[:line_numbers]
150
-
151
- # Backwards compatibility
152
- @options[:property_syntax] ||= @options[:attribute_syntax]
153
- case @options[:property_syntax]
154
- when :alternate; @options[:property_syntax] = :new
155
- when :normal; @options[:property_syntax] = :old
156
- end
157
223
  end
158
224
 
159
225
  # Render the template to CSS.
@@ -199,6 +265,18 @@ module Sass
199
265
  end
200
266
 
201
267
  def _to_tree
268
+ if (@options[:cache] || @options[:read_cache]) &&
269
+ @options[:filename] && @options[:importer]
270
+ key = sassc_key
271
+ sha = Digest::SHA1.hexdigest(@template)
272
+
273
+ if root = @options[:cache_store].retrieve(key, sha)
274
+ @options = root.options.merge(@options)
275
+ root.options = @options
276
+ return root
277
+ end
278
+ end
279
+
202
280
  check_encoding!
203
281
 
204
282
  if @options[:syntax] == :scss
@@ -209,6 +287,7 @@ module Sass
209
287
  end
210
288
 
211
289
  root.options = @options
290
+ @options[:cache_store].store(key, sha, root) if @options[:cache] && key && sha
212
291
  root
213
292
  rescue SyntaxError => e
214
293
  e.modify_backtrace(:filename => @options[:filename], :line => @line)
@@ -216,6 +295,10 @@ module Sass
216
295
  raise e
217
296
  end
218
297
 
298
+ def sassc_key
299
+ @options[:cache_store].key(*@options[:importer].key(@options[:filename], @options))
300
+ end
301
+
219
302
  def check_encoding!
220
303
  return if @checked_encoding
221
304
  @checked_encoding = true
data/lib/sass/error.rb CHANGED
@@ -125,6 +125,7 @@ module Sass
125
125
  # @return [Array<String>]
126
126
  def backtrace
127
127
  return nil if super.nil?
128
+ return super if sass_backtrace.all? {|h| h.empty?}
128
129
  sass_backtrace.map do |h|
129
130
  "#{h[:filename] || "(sass)"}:#{h[:line]}" +
130
131
  (h[:mixin] ? ":in `#{h[:mixin]}'" : "")
@@ -178,7 +179,9 @@ END
178
179
  private
179
180
 
180
181
  def header_string(e, options)
181
- return "#{e.class}: #{e.message}" unless e.is_a? Sass::SyntaxError
182
+ unless e.is_a?(Sass::SyntaxError) && e.sass_line && e.sass_template
183
+ return "#{e.class}: #{e.message}"
184
+ end
182
185
 
183
186
  line_offset = options[:line] || 1
184
187
  line_num = e.sass_line + 1 - line_offset
@@ -0,0 +1,138 @@
1
+ module Sass
2
+ module Importers
3
+ # The abstract base class for Sass importers.
4
+ # All importers should inherit from this.
5
+ #
6
+ # At the most basic level, an importer is given a string
7
+ # and must return a {Sass::Engine} containing some Sass code.
8
+ # This string can be interpreted however the importer wants;
9
+ # however, subclasses are encouraged to use the URI format
10
+ # for pathnames.
11
+ #
12
+ # Importers that have some notion of "relative imports"
13
+ # should take a single load path in their constructor,
14
+ # and interpret paths as relative to that.
15
+ # They should also implement the \{#find\_relative} method.
16
+ #
17
+ # Importers should be serializable via `Marshal.dump`.
18
+ # In addition to the standard `_dump` and `_load` methods,
19
+ # importers can define `_before_dump`, `_after_dump`, `_around_dump`,
20
+ # and `_after_load` methods as per {Haml::Util#dump} and {Haml::Util#load}.
21
+ #
22
+ # @abstract
23
+ class Base
24
+
25
+ # Find a Sass file relative to another file.
26
+ # Importers without a notion of "relative paths"
27
+ # should just return nil here.
28
+ #
29
+ # If the importer does have a notion of "relative paths",
30
+ # it should ignore its load path during this method.
31
+ #
32
+ # See \{#find} for important information on how this method should behave.
33
+ #
34
+ # The `:filename` option passed to the returned {Sass::Engine}
35
+ # should be of a format that could be passed to \{#find}.
36
+ #
37
+ # @param uri [String] The URI to import. This is not necessarily relative,
38
+ # but this method should only return true if it is.
39
+ # @param base [String] The base filename. If `uri` is relative,
40
+ # it should be interpreted as relative to `base`.
41
+ # `base` is guaranteed to be in a format importable by this importer.
42
+ # @param options [{Symbol => Object}] Options for the Sass file
43
+ # containing the `@import` that's currently being resolved.
44
+ # @return [Sass::Engine, nil] An Engine containing the imported file,
45
+ # or nil if it couldn't be found or was in the wrong format.
46
+ def find_relative(uri, base, options)
47
+ Haml::Util.abstract(self)
48
+ end
49
+
50
+ # Find a Sass file, if it exists.
51
+ #
52
+ # This is the primary entry point of the Importer.
53
+ # It corresponds directly to an `@import` statement in Sass.
54
+ # It should do three basic things:
55
+ #
56
+ # * Determine if the URI is in this importer's format.
57
+ # If not, return nil.
58
+ # * Determine if the file indicated by the URI actually exists and is readable.
59
+ # If not, return nil.
60
+ # * Read the file and place the contents in a {Sass::Engine}.
61
+ # Return that engine.
62
+ #
63
+ # If this importer's format allows for file extensions,
64
+ # it should treat them the same way as the default {Filesystem} importer.
65
+ # If the URI explicitly has a `.sass` or `.scss` filename,
66
+ # the importer should look for that exact file
67
+ # and import it as the syntax indicated.
68
+ # If it doesn't exist, the importer should return nil.
69
+ #
70
+ # If the URI doesn't have either of these extensions,
71
+ # the importer should look for files with the extensions.
72
+ # If no such files exist, it should return nil.
73
+ #
74
+ # The {Sass::Engine} to be returned should be passed `options`,
75
+ # with a few modifications. `:filename` and `:syntax` should be set appropriately,
76
+ # and `:importer` should be set to this importer.
77
+ #
78
+ # @param uri [String] The URI to import.
79
+ # @param options [{Symbol => Object}] Options for the Sass file
80
+ # containing the `@import` that's currently being resolved.
81
+ # This is safe for subclasses to modify destructively.
82
+ # Callers should only pass in a value they don't mind being destructively modified.
83
+ # @return [Sass::Engine, nil] An Engine containing the imported file,
84
+ # or nil if it couldn't be found or was in the wrong format.
85
+ def find(uri, options)
86
+ Haml::Util.abstract(self)
87
+ end
88
+
89
+ # Returns the time the given Sass file was last modified.
90
+ #
91
+ # If the given file has been deleted or the time can't be accessed
92
+ # for some other reason, this should return nil.
93
+ #
94
+ # @param uri [String] The URI of the file to check.
95
+ # Comes from a `:filename` option set on an engine returned by this importer.
96
+ # @param options [{Symbol => Objet}] Options for the Sass file
97
+ # containing the `@import` currently being checked.
98
+ # @return [Time, nil]
99
+ def mtime(uri, options)
100
+ Haml::Util.abstract(self)
101
+ end
102
+
103
+ # Get the cache key pair for the given Sass URI.
104
+ # The URI need not be checked for validity.
105
+ #
106
+ # The only strict requirement is that the returned pair of strings
107
+ # uniquely identify the file at the given URI.
108
+ # However, the first component generally corresponds roughly to the directory,
109
+ # and the second to the basename, of the URI.
110
+ #
111
+ # Note that keys must be unique *across importers*.
112
+ # Thus it's probably a good idea to include the importer name
113
+ # at the beginning of the first component.
114
+ #
115
+ # @param uri [String] A URI known to be valid for this importer.
116
+ # @param options [{Symbol => Object}] Options for the Sass file
117
+ # containing the `@import` currently being checked.
118
+ # @return [(String, String)] The key pair which uniquely identifies
119
+ # the file at the given URI.
120
+ def key(uri, options)
121
+ Haml::Util.abstract(self)
122
+ end
123
+
124
+ # A string representation of the importer.
125
+ # Should be overridden by subclasses.
126
+ #
127
+ # This is used to help debugging,
128
+ # and should usually just show the load path encapsulated by this importer.
129
+ #
130
+ # @return [String]
131
+ def to_s
132
+ Haml::Util.abstract(self)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+