haml-edge 3.1.73 → 3.1.74

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