module Middleman::Util

Constants

IGNORE_DESCRIPTOR

Public Instance Methods

all_files_under(path) { |path| ... } click to toggle source
# File lib/middleman-core/util/files.rb, line 17
def all_files_under(path, &ignore)
  path = Pathname(path)

  if ignore && yield(path)
    []
  elsif path.directory?
    path.children.flat_map do |child|
      all_files_under(child, &ignore)
    end.compact
  elsif path.file?
    [path]
  else
    []
  end
end
asset_path(app, kind, source, options={}) click to toggle source
# File lib/middleman-core/util/paths.rb, line 75
def asset_path(app, kind, source, options={})
  return source if source.to_s.include?('//') || source.to_s.start_with?('data:')

  asset_folder = case kind
  when :css
    app.config[:css_dir]
  when :js
    app.config[:js_dir]
  when :images
    app.config[:images_dir]
  when :fonts
    app.config[:fonts_dir]
  else
    kind.to_s
  end

  source = source.to_s.tr(' ', '')
  ignore_extension = (kind == :images || kind == :fonts) # don't append extension
  source << ".#{kind}" unless ignore_extension || source.end_with?(".#{kind}")
  asset_folder = '' if source.start_with?('/') # absolute path

  asset_url(app, source, asset_folder, options)
end
asset_url(app, path, prefix='', options={}) click to toggle source
# File lib/middleman-core/util/paths.rb, line 106
def asset_url(app, path, prefix='', options={})
  # Don't touch assets which already have a full path
  return path if path.include?('//') || path.start_with?('data:')

  if options[:relative] && !options[:current_resource]
    raise ArgumentError, '#asset_url must be run in a context with current_resource if relative: true'
  end

  uri = ::Middleman::Util.parse_uri(path)
  path = uri.path

  # Ensure the url we pass into find_resource_by_destination_path is not a
  # relative path, since it only takes absolute url paths.
  dest_path = url_for(app, path, options.merge(relative: false))

  result = if resource = app.sitemap.find_resource_by_path(dest_path)
    resource.url
  elsif resource = app.sitemap.find_resource_by_destination_path(dest_path)
    resource.url
  else
    path = ::File.join(prefix, path)
    if resource = app.sitemap.find_resource_by_path(path)
      resource.url
    else
      ::File.join(app.config[:http_prefix], path)
    end
  end

  final_result = ::Addressable::URI.encode(
    relative_path_from_resource(
      options[:current_resource],
      result,
      options[:relative]
    )
  )

  result_uri = ::Middleman::Util.parse_uri(final_result)
  result_uri.query = uri.query
  result_uri.fragment = uri.fragment
  result_uri.to_s
end
binary?(filename) click to toggle source
# File lib/middleman-core/util/binary.rb, line 18
def binary?(filename)
  @binary_cache ||= {}

  return @binary_cache[filename] if @binary_cache.key?(filename)

  @binary_cache[filename] = begin
    path = Pathname(filename)
    ext = path.extname

    # We hardcode detecting of gzipped SVG files
    if ext == '.svgz'
      true
    elsif ::Tilt.registered?(ext.sub('.', ''))
      false
    else
      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?(path.to_s)
      end
    end
  end
end
collect_extensions(path) click to toggle source
# File lib/middleman-core/util/files.rb, line 86
def collect_extensions(path)
  @@extensions_cache ||= {}

  base_name = ::File.basename(path)
  @@extensions_cache[base_name] ||= begin
    result = []

    unless base_name.start_with?('.')
      step_through_extensions(base_name) { |e| result << e }
    end

    result
  end
end
current_directory() click to toggle source

Get the PWD and try to keep path encoding consistent.

@param [String] path The glob path. @return [Array<String>]

# File lib/middleman-core/util/files.rb, line 49
def current_directory
  result = ::Dir.pwd

  return result unless RUBY_PLATFORM =~ /darwin/

  result.encode('UTF-8', 'UTF-8-MAC')
end
extract_response_text(response) click to toggle source
# File lib/middleman-core/util/rack.rb, line 14
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
file_contents_include_binary_bytes?(filename) click to toggle source
# File lib/middleman-core/util/binary.rb, line 68
def file_contents_include_binary_bytes?(filename)
  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

  false
end
full_path(path, app) click to toggle source
# File lib/middleman-core/util/paths.rb, line 243
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
glob_directory(path) click to toggle source

Glob a directory and try to keep path encoding consistent.

@param [String] path The glob path. @return [Array<String>]

# File lib/middleman-core/util/files.rb, line 37
def glob_directory(path)
  results = ::Dir[path]

  return results unless RUBY_PLATFORM =~ /darwin/

  results.map { |r| r.encode('UTF-8', 'UTF-8-MAC') }
end
instrument(name, payload={}, &block) click to toggle source

Facade for ActiveSupport/Notification

# File lib/middleman-core/util.rb, line 18
def instrument(name, payload={}, &block)
  suffixed_name = name =~ /\.middleman$/ ? name.dup : "#{name}.middleman"
  ::ActiveSupport::Notifications.instrument(suffixed_name, payload, &block)
end
nonbinary_mime?(mime) click to toggle source
# File lib/middleman-core/util/binary.rb, line 49
def nonbinary_mime?(mime)
  if mime.start_with?('text/')
    true
  elsif mime.include?('xml') && !mime.include?('officedocument')
    true
  elsif mime.include?('json')
    true
  elsif mime.include?('javascript')
    true
  else
    false
  end
end
normalize_path(path) click to toggle source
# File lib/middleman-core/util/paths.rb, line 34
def normalize_path(path)
  # The tr call works around a bug in Ruby's Unicode handling
  Addressable::URI.unencode(path).sub(%r{^/}, '').tr('', '')
end
parse_uri(uri) click to toggle source
# File lib/middleman-core/util/paths.rb, line 19
def parse_uri(uri)
  ::Addressable::URI.parse(uri)
end
path_match(matcher, path) click to toggle source
# File lib/middleman-core/util/paths.rb, line 295
def path_match(matcher, path)
  if matcher.is_a?(String)
    if matcher.include? '*'
      ::File.fnmatch(matcher, path)
    else
      path == matcher
    end
  elsif matcher.respond_to?(:match)
    !!(path =~ matcher)
  elsif matcher.respond_to?(:call)
    matcher.call(path)
  else
    ::File.fnmatch(matcher.to_s, path)
  end
end
recursively_enhance(obj) click to toggle source
# File lib/middleman-core/util/data.rb, line 30
def recursively_enhance(obj)
  if obj.is_a? ::Array
    obj.map { |e| recursively_enhance(e) }
  elsif obj.is_a? ::Hash
    EnhancedHash.new(obj)
  else
    obj
  end
end
relative_path_from_resource(curr_resource, resource_url, relative) click to toggle source
# File lib/middleman-core/util/paths.rb, line 266
def relative_path_from_resource(curr_resource, resource_url, relative)
  # Switch to the relative path between resource and the given resource
  # if we've been asked to.
  if relative
    # Output urls relative to the destination path, not the source path
    current_dir = Pathname('/' + curr_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

    relative_path
  else
    resource_url
  end
end
remove_templating_extensions(path) click to toggle source
# File lib/middleman-core/util/files.rb, line 78
def remove_templating_extensions(path)
  step_through_extensions(path)
end
rewrite_paths(body, path, exts, app) { |asset_path| ... } click to toggle source
# File lib/middleman-core/util/rack.rb, line 24
def rewrite_paths(body, path, exts, app, &_block)
  matcher = /([\'\"\(,]\s*|# sourceMappingURL=)([^\s\'\"\)\(>]+(#{::Regexp.union(exts)}))/

  url_fn_prefix = 'url('

  body.dup.gsub(matcher) do |match|
    opening_character = $1
    asset_path = $2

    if asset_path.start_with?(url_fn_prefix)
      opening_character << url_fn_prefix
      asset_path = asset_path[url_fn_prefix.length..-1]
    end

    current_resource = app.sitemap.find_resource_by_destination_path(path)

    begin
      uri = ::Middleman::Util.parse_uri(asset_path)

      if uri.relative? && uri.host.nil? && !(asset_path =~ /^[^\/].*[a-z]+\.[a-z]+\/.*/)
        dest_path = ::Middleman::Util.url_for(app, asset_path, relative: false, current_resource: current_resource)

        resource = app.sitemap.find_resource_by_destination_path(dest_path)

        if resource && (result = yield(asset_path))
          "#{opening_character}#{result}"
        else
          match
        end
      else
        match
      end
    rescue ::Addressable::URI::InvalidURIError
      match
    end
  end
end
should_ignore?(validator, value) click to toggle source
# File lib/middleman-core/util/paths.rb, line 50
def should_ignore?(validator, value)
  if validator.is_a? Regexp
    # Treat as Regexp
    !!(value =~ validator)
  elsif validator.respond_to? :call
    # Treat as proc
    validator.call(value)
  elsif validator.is_a? String
    # Treat as glob
    File.fnmatch(value, validator)
  else
    # If some unknown thing, don't ignore
    false
  end
end
step_through_extensions(path) { |ext| ... } click to toggle source
# File lib/middleman-core/util/files.rb, line 58
def step_through_extensions(path)
  while ::Middleman::Util.tilt_class(path)
    ext = ::File.extname(path)
    break if ext.empty?

    yield ext if block_given?

    # Strip templating extensions as long as Tilt knows them
    path = path[0..-(ext.length + 1)]
  end

  yield ::File.extname(path) if block_given?

  path
end
strip_leading_slash(path) click to toggle source
# File lib/middleman-core/util/paths.rb, line 43
def strip_leading_slash(path)
  path.sub(%r{^/}, '')
end
tilt_class(path) click to toggle source
# File lib/middleman-core/util/paths.rb, line 25
def tilt_class(path)
  ::Tilt[path]
end
url_for(app, path_or_resource, options={}) click to toggle source
# File lib/middleman-core/util/paths.rb, line 152
def url_for(app, path_or_resource, options={})
  if path_or_resource.is_a?(String) || path_or_resource.is_a?(Symbol)
    r = app.sitemap.find_resource_by_page_id(path_or_resource)

    path_or_resource = r ? r : path_or_resource.to_s
  end

  # 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 = ::Middleman::Util.parse_uri(url)
  rescue ::Addressable::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 && !uri.host
    # 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)
    if resource
      resource_url = resource.url
    else
      # Try to find a resource relative to destination paths
      url_path = Pathname(uri.path)
      current_source_dir = Pathname('/' + this_resource.destination_path).dirname
      url_path = current_source_dir.join(url_path) if url_path.relative?
      resource = app.sitemap.find_resource_by_destination_path(url_path.to_s)
      resource_url = resource.url if resource
    end
  elsif options[:find_resource] && uri.path && !uri.host
    resource = app.sitemap.find_resource_by_path(uri.path)
    resource_url = resource.url if resource
  end

  if resource
    uri.path = if this_resource
      ::Addressable::URI.encode(
        relative_path_from_resource(
          this_resource,
          resource_url,
          effective_relative
        )
      )
    else
      resource_url
    end
  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