Class: Sass::Importers::Filesystem

Inherits:
Base
  • Object
show all
Defined in:
lib/sass/importers/filesystem.rb

Overview

The default importer, used for any strings found in the load path. Simply loads Sass files from the filesystem using the default logic.

Constant Summary collapse

REDUNDANT_DIRECTORY =
%r{#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root) ⇒ Filesystem

Creates a new filesystem importer that imports files relative to a given path.

Parameters:

  • root (String)

    The root path. This importer will import files relative to this path.



16
17
18
19
# File 'lib/sass/importers/filesystem.rb', line 16

def initialize(root)
  @root = File.expand_path(root)
  @same_name_warnings = Set.new
end

Instance Attribute Details

#root

Returns the value of attribute root.



10
11
12
# File 'lib/sass/importers/filesystem.rb', line 10

def root
  @root
end

Instance Method Details

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/sass/importers/filesystem.rb', line 54

def eql?(other)
  root.eql?(other.root)
end

#escape_glob_characters(name) (protected)



98
99
100
101
102
# File 'lib/sass/importers/filesystem.rb', line 98

def escape_glob_characters(name)
  name.gsub(/[\*\[\]\{\}\?]/) do |char|
    "\\#{char}"
  end
end

#extensions{String => Symbol} (protected)

A hash from file extensions to the syntaxes for those extensions. The syntaxes must be :sass or :scss.

This can be overridden by subclasses that want normal filesystem importing with unusual extensions.

Returns:

  • ({String => Symbol})


77
78
79
# File 'lib/sass/importers/filesystem.rb', line 77

def extensions
  {'sass' => :sass, 'scss' => :scss}
end

#find(name, options)

See Also:



27
28
29
# File 'lib/sass/importers/filesystem.rb', line 27

def find(name, options)
  _find(@root, name, options)
end

#find_real_file(dir, name, options) ⇒ (String, Symbol) (protected)

Given a base directory and an @imported name, finds an existant file that matches the name.

Parameters:

  • dir (String)

    The directory relative to which to search.

  • name (String)

    The filename to search for.

Returns:

  • ((String, Symbol))

    A filename-syntax pair.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/sass/importers/filesystem.rb', line 111

def find_real_file(dir, name, options)
  found = possible_files(remove_root(name)).map do |f, s|
    path = (dir == "." || Pathname.new(f).absolute?) ? f : "#{dir}/#{f}"
    Dir[path].map do |full_path|
      full_path.gsub!(REDUNDANT_DIRECTORY, File::SEPARATOR)
      [full_path, s]
    end
  end
  found = Sass::Util.flatten(found, 1)
  return if found.empty?
  
  if found.size > 1 && !@same_name_warnings.include?(found.first.first)
    found.each {|(f, _)| @same_name_warnings << f}
    relative_to = Pathname.new(dir)
    if options[:_line]
      # If _line exists, we're here due to an actual import in an
      # import_node and we want to print a warning for a user writing an
      # ambiguous import.
      candidates = found.map {|(f, _)| "    " + Pathname.new(f).relative_path_from(relative_to).to_s}.join("\n")
      Sass::Util.sass_warn <<WARNING
WARNING: On line #{options[:_line]}#{" of #{options[:filename]}" if options[:filename]}:
  It's not clear which file to import for '@import "#{name}"'.
  Candidates:
#{candidates}
  For now I'll choose #{File.basename found.first.first}.
  This will be an error in future versions of Sass.
WARNING
    else
      # Otherwise, we're here via StalenessChecker, and we want to print a
      # warning for a user running `sass --watch` with two ambiguous files.
      candidates = found.map {|(f, _)| "    " + File.basename(f)}.join("\n")
      Sass::Util.sass_warn <<WARNING
WARNING: In #{File.dirname(name)}:
  There are multiple files that match the name "#{File.basename(name)}":
#{candidates}
  This will be an error in future versions of Sass.
WARNING
    end
  end
  found.first
end

#find_relative(name, base, options)

See Also:



22
23
24
# File 'lib/sass/importers/filesystem.rb', line 22

def find_relative(name, base, options)
  _find(File.dirname(base), name, options)
end

#hash



50
51
52
# File 'lib/sass/importers/filesystem.rb', line 50

def hash
  @root.hash
end

#key(name, options)

See Also:



40
41
42
43
# File 'lib/sass/importers/filesystem.rb', line 40

def key(name, options)
  [self.class.name + ":" + File.dirname(File.expand_path(name)),
    File.basename(name)]
end

#mtime(name, options)

See Also:



32
33
34
35
36
37
# File 'lib/sass/importers/filesystem.rb', line 32

def mtime(name, options)
  file, s = Sass::Util.destructure(find_real_file(@root, name, options))
  File.mtime(file) if file
rescue Errno::ENOENT
  nil
end

#possible_files(name) ⇒ Array(String, Symbol) (protected)

Given an @imported path, returns an array of possible on-disk filenames and their corresponding syntaxes for that path.

Parameters:

  • name (String)

    The filename.

Returns:

  • (Array(String, Symbol))

    An array of pairs. The first element of each pair is a filename to look for; the second element is the syntax that file would be in (:sass or :scss).



88
89
90
91
92
93
94
95
96
# File 'lib/sass/importers/filesystem.rb', line 88

def possible_files(name)
  name = escape_glob_characters(name)
  dirname, basename, extname = split(name)
  sorted_exts = extensions.sort
  syntax = extensions[extname]

  return [["#{dirname}/{_,}#{basename}.#{extensions.invert[syntax]}", syntax]] if syntax
  sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
end

#remove_root(name) (protected)

If a full uri is passed, this removes the root from it otherwise returns the name unchanged



62
63
64
65
66
67
68
# File 'lib/sass/importers/filesystem.rb', line 62

def remove_root(name)
  if name.index(@root + "/") == 0
    name[(@root.length + 1)..-1]
  else
    name
  end
end

#split(name) (protected)

Splits a filename into three parts, a directory part, a basename, and an extension Only the known extensions returned from the extensions method will be recognized as such.



155
156
157
158
159
160
161
162
163
# File 'lib/sass/importers/filesystem.rb', line 155

def split(name)
  extension = nil
  dirname, basename = File.dirname(name), File.basename(name)
  if basename =~ /^(.*)\.(#{extensions.keys.map{|e| Regexp.escape(e)}.join('|')})$/
    basename = $1
    extension = $2
  end
  [dirname, basename, extension]
end

#to_s

See Also:



46
47
48
# File 'lib/sass/importers/filesystem.rb', line 46

def to_s
  @root
end