Module: Middleman::Util

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

Class Method Summary collapse

Class Method Details

.all_files_under(*paths) ⇒ Array

Get a recusive list of files inside a set of paths. Works with symlinks.

Parameters:

  • paths

    Some paths string or Pathname

Returns:

  • (Array)

    An array of filenames



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/middleman-core/util.rb', line 138

def self.all_files_under(*paths)
  # when we drop 1.8, replace this with flat_map
  paths.map do |p|
    path = Pathname(p)
    if path.directory?
      all_files_under(*path.children)
    elsif path.file?
      path
    end
  end.flatten.compact
end

.binary?(filename) ⇒ Boolean

Whether the source file is binary.

Parameters:

  • filename (String)

    The file to check.

Returns:

  • (Boolean)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/middleman-core/util.rb', line 24

def self.binary?(filename)
  ext = File.extname(filename)
  return true if ext == '.svgz'
  return false if Tilt.registered?(ext.sub('.',''))

  ext = ".#{ext}" unless ext.to_s[0] == ?.
  mime = ::Rack::Mime.mime_type(ext, nil)
  unless mime
    binary_bytes = [0, 1, 2, 3, 4, 5, 6, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31]
    s = File.read(filename, 4096) || ''
    s.each_byte do |c|
      return true if binary_bytes.include?(c)
    end
    return false
  end
  return false if mime.start_with?('text/')
  return false if mime.include?('xml')
  return false if mime.include?('json')
  return false if mime.include?('javascript')
  true
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.



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

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

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

Facade for ActiveSupport/Notification



58
59
60
61
# File 'lib/middleman-core/util.rb', line 58

def self.instrument(name, payload={}, &block)
  name << ".middleman" unless name =~ /\.middleman$/
  ::ActiveSupport::Notifications.instrument(name, payload, &block)
end

.logger(*args) ⇒ Middleman::Logger

The logger

Returns:



49
50
51
52
53
54
55
# File 'lib/middleman-core/util.rb', line 49

def self.logger(*args)
  if !@_logger || args.length > 0
    @_logger = ::Middleman::Logger.new(*args)
  end

  @_logger
end

.normalize_path(path) ⇒ String

Normalize a path to not include a leading slash

Parameters:

Returns:



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

def self.normalize_path(path)
  # The tr call works around a bug in Ruby's Unicode handling
  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



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/middleman-core/util.rb', line 121

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

.recursively_enhance(data) ⇒ Thor::CoreExt::HashWithIndifferentAccess

Recursively convert a normal Hash into a HashWithIndifferentAccess

Parameters:

  • data (Hash)

    Normal hash

Returns:

  • (Thor::CoreExt::HashWithIndifferentAccess)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/middleman-core/util.rb', line 68

def self.recursively_enhance(data)
  if data.is_a? Hash
    data = ::Thor::CoreExt::HashWithIndifferentAccess.new(data)
    data.each do |key, val|
      data[key] = recursively_enhance(val)
    end
    data
  elsif data.is_a? Array
    data.each_with_index do |val, i|
      data[i] = recursively_enhance(val)
    end
    data
  else
    data
  end
end

.strip_leading_slash(path) ⇒ Object

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



95
96
97
# File 'lib/middleman-core/util.rb', line 95

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



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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/middleman-core/util.rb', line 153

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

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

  relative = options.delete(: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 = app.current_resource # store in a local var to save work

  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
    # Switch to the relative path between this_resource and the given resource
    # if we've been asked to.
    if effective_relative
      # Output urls relative to the destination path, not the source path
      current_dir = Pathname('/' + this_resource.destination_path).dirname
      relative_path = Pathname(resource_url).relative_path_from(current_dir).to_s

      # Put back the trailing slash to avoid unnecessary Apache redirects
      if resource_url.end_with?('/') && !relative_path.end_with?('/')
        relative_path << '/'
      end

      uri.path = relative_path
    else
      uri.path = resource_url
    end
  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.delete(: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.delete(:anchor) || options.delete(:fragment)
  uri.fragment = fragment.to_s if fragment

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