module Middleman::Util

def all_files_under(path, &ignore)

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

def asset_path(app, kind, source, options={})

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

def asset_url(app, path, prefix='', options={})

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

def binary?(filename)

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

def collect_extensions(path)

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

def current_directory

Returns:
  • (Array) -

Parameters:
  • path (String) -- The glob path.
def current_directory
  result = ::Dir.pwd
  return result unless RUBY_PLATFORM =~ /darwin/
  result.encode('UTF-8', 'UTF-8-MAC')
end

def extract_response_text(response)

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

def file_contents_include_binary_bytes?(filename)

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

def find_related_files(app, files)

def find_related_files(app, files)
  return [] if files.empty?
  file_set = ::Set.new(files)
  all_extensions = files.flat_map { |f| collect_extensions(f.to_s) }
  sass_type_aliasing = ['.scss', '.sass']
  erb_type_aliasing = ['.erb', '.haml', '.slim']
  all_extensions |= sass_type_aliasing unless (all_extensions & sass_type_aliasing).empty?
  all_extensions |= erb_type_aliasing unless (all_extensions & erb_type_aliasing).empty?
  all_extensions.uniq!
  app.sitemap.resources.select { |r|
    if r.file_descriptor
      local_extensions = collect_extensions(r.file_descriptor[:full_path].to_s)
      local_extensions |= sass_type_aliasing unless (local_extensions & sass_type_aliasing).empty?
      local_extensions |= erb_type_aliasing unless (local_extensions & erb_type_aliasing).empty?
      local_extensions.uniq!
      !(all_extensions & local_extensions).empty? && !file_set.include?(r.file_descriptor[:full_path])
    else
      false
    end
  }.map(&:file_descriptor)
end

def full_path(path, app)

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

def glob_directory(path)

Returns:
  • (Array) -

Parameters:
  • path (String) -- The glob path.
def glob_directory(path)
  results = ::Dir[path]
  return results unless RUBY_PLATFORM =~ /darwin/
  results.map { |r| r.encode('UTF-8', 'UTF-8-MAC') }
end

def instrument(name, payload={}, &block)

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

def nonbinary_mime?(mime)

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

def normalize_path(path)

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

def parse_uri(uri)

def parse_uri(uri)
  ::Addressable::URI.parse(uri)
end

def path_match(matcher, path)

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

def recursively_enhance(obj)

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

def relative_path_from_resource(curr_resource, resource_url, relative)

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

def remove_templating_extensions(path)

def remove_templating_extensions(path)
  step_through_extensions(path)
end

def rewrite_paths(body, path, exts, app, &_block)

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

def should_ignore?(validator, value)

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

def step_through_extensions(path)

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

def strip_leading_slash(path)

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

def tilt_class(path)

def tilt_class(path)
  ::Tilt[path]
end

def url_for(app, path_or_resource, options={})

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