Module: Middleman::Util

Defined in:
lib/middleman-core/util.rb

Class Method Summary collapse

Class Method Details

.all_files_under(path, &ignore) ⇒ Array<Pathname>

Get a recusive list of files inside a path. Works with symlinks.

Parameters:

  • path

    Some path string or Pathname

  • ignore

    A proc/block that returns true if a given path should be ignored - if a path is ignored, nothing below it will be searched either.

Returns:

  • (Array<Pathname>)

    An array of Pathnames for each file (no directories)



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/middleman-core/util.rb', line 122

def all_files_under(path, &ignore)
  path = Pathname(path)

  return [] if ignore && ignore.call(path)

  if path.directory?
    path.children.flat_map do |child|
      all_files_under(child, &ignore)
    end.compact
  elsif path.file?
    [path]
  else
    []
  end
end

.binary?(filename) ⇒ Boolean

Whether the source file is binary.

Parameters:

  • filename (String)

    The file to check.

Returns:

  • (Boolean)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/middleman-core/util.rb', line 21

def binary?(filename)
  ext = File.extname(filename)

  # We hardcode detecting of gzipped SVG files
  return true if ext == '.svgz'

  return false if Tilt.registered?(ext.sub('.', ''))

  dot_ext = (ext.to_s[0] == '.') ? ext.dup : ".#{ext}"

  if mime = ::Rack::Mime.mime_type(dot_ext, nil)
    !nonbinary_mime?(mime)
  else
    file_contents_include_binary_bytes?(filename)
  end
end

.extract_response_text(response) ⇒ String

Extract the text of a Rack response as a string. Useful for extensions implemented as Rack middleware.

Parameters:

  • response

    The response from #call

Returns:

  • (String)

    The whole response as a string.



84
85
86
87
88
89
90
91
# File 'lib/middleman-core/util.rb', line 84

def extract_response_text(response)
  # The rack spec states all response bodies must respond to each
  result = ''
  response.each do |part, _|
    result << part
  end
  result
end

.full_path(path, app) ⇒ String

Expand a path to include the index file if it’s a directory

Parameters:

Returns:

  • (String)

    Path with index file if necessary.



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/middleman-core/util.rb', line 209

def full_path(path, app)
  resource = app.sitemap.find_resource_by_destination_path(path)

  unless resource
    # Try it with /index.html at the end
    indexed_path = File.join(path.sub(%r{/$}, ''), app.config[:index_file])
    resource = app.sitemap.find_resource_by_destination_path(indexed_path)
  end

  if resource
    '/' + resource.destination_path
  else
    '/' + normalize_path(path)
  end
end

.instrument(name, payload = {}, &block) ⇒ Object

Facade for ActiveSupport/Notification



39
40
41
42
# File 'lib/middleman-core/util.rb', line 39

def instrument(name, payload={}, &block)
  suffixed_name = (name =~ /\.middleman$/) ? name.dup : "#{name}.middleman"
  ::ActiveSupport::Notifications.instrument(suffixed_name, payload, &block)
end

.normalize_path(path) ⇒ String

Normalize a path to not include a leading slash

Parameters:

  • path (String)

Returns:

  • (String)


69
70
71
72
# File 'lib/middleman-core/util.rb', line 69

def normalize_path(path)
  # The tr call works around a bug in Ruby's Unicode handling
  URI.decode(path).sub(%r{^/}, '').tr('', '')
end

.path_match(matcher, path) ⇒ Boolean

Takes a matcher, which can be a literal string or a string containing glob expressions, or a regexp, or a proc, or anything else that responds to #match or #call, and returns whether or not the given path matches that matcher.

Parameters:

  • matcher

    A matcher string/regexp/proc/etc

  • path

    A path as a string

Returns:

  • (Boolean)

    Whether the path matches the matcher



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/middleman-core/util.rb', line 102

def path_match(matcher, path)
  case
  when matcher.is_a?(String)
    path.match(matcher)
  when matcher.respond_to?(:match)
    matcher.match(path)
  when matcher.respond_to?(:call)
    matcher.call(path)
  else
    File.fnmatch(matcher.to_s, path)
  end
end

.strip_leading_slash(path) ⇒ Object

This is a separate method from normalize_path in case we change how we normalize paths



76
77
78
# File 'lib/middleman-core/util.rb', line 76

def strip_leading_slash(path)
  path.sub(%r{^/}, '')
end

.url_for(app, path_or_resource, options = {}) ⇒ Object

Given a source path (referenced either absolutely or relatively) or a Resource, this will produce the nice URL configured for that path, respecting :relative_links, directory indexes, etc.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/middleman-core/util.rb', line 141

def url_for(app, path_or_resource, options={})
  # Handle Resources and other things which define their own url method
  url = if path_or_resource.respond_to?(:url)
    path_or_resource.url
  else
    path_or_resource.dup
  end

  # Try to parse URL
  begin
    uri = URI(url)
  rescue URI::InvalidURIError
    # Nothing we can do with it, it's not really a URI
    return url
  end

  relative = options[:relative]
  raise "Can't use the relative option with an external URL" if relative && uri.host

  # Allow people to turn on relative paths for all links with
  # set :relative_links, true
  # but still override on a case by case basis with the :relative parameter.
  effective_relative = relative || false
  effective_relative = true if relative.nil? && app.config[:relative_links]

  # Try to find a sitemap resource corresponding to the desired path
  this_resource = options[:current_resource]

  if path_or_resource.is_a?(::Middleman::Sitemap::Resource)
    resource = path_or_resource
    resource_url = url
  elsif this_resource && uri.path
    # Handle relative urls
    url_path = Pathname(uri.path)
    current_source_dir = Pathname('/' + this_resource.path).dirname
    url_path = current_source_dir.join(url_path) if url_path.relative?
    resource = app.sitemap.find_resource_by_path(url_path.to_s)
    resource_url = resource.url if resource
  elsif options[:find_resource] && uri.path
    resource = app.sitemap.find_resource_by_path(uri.path)
    resource_url = resource.url if resource
  end

  if resource
    uri.path = URI.encode(relative_path_from_resource(this_resource, resource_url, effective_relative))
  else
    # If they explicitly asked for relative links but we can't find a resource...
    raise "No resource exists at #{url}" if relative
  end

  # Support a :query option that can be a string or hash
  if query = options[:query]
    uri.query = query.respond_to?(:to_param) ? query.to_param : query.to_s
  end

  # Support a :fragment or :anchor option just like Padrino
  fragment = options[:anchor] || options[:fragment]
  uri.fragment = fragment.to_s if fragment

  # Finally make the URL back into a string
  uri.to_s
end