class Middleman::CoreExtensions::FrontMatter

Constants

YAML_ERRORS

Public Class Methods

new(app, options_hash={}, &block) click to toggle source
Calls superclass method Middleman::Extension::new
# File lib/middleman-core/core_extensions/front_matter.rb, line 20
def initialize(app, options_hash={}, &block)
  super

  @cache = {}
end

Public Instance Methods

after_configuration() click to toggle source
# File lib/middleman-core/core_extensions/front_matter.rb, line 32
def after_configuration
  app.extensions[:frontmatter] = self
  app.ignore %r{\.frontmatter$}

  ::Middleman::Sitemap::Resource.send :include, ResourceInstanceMethods

  app.sitemap.provides_metadata do |path|
    fmdata = data(path).first

    data = {}
    [:layout, :layout_engine].each do |opt|
      data[opt] = fmdata[opt] unless fmdata[opt].nil?
    end

    { options: data, page: ::Middleman::Util.recursively_enhance(fmdata).freeze }
  end
end
before_configuration() click to toggle source
# File lib/middleman-core/core_extensions/front_matter.rb, line 26
def before_configuration
  ext = self
  app.files.changed { |file| ext.clear_data(file) }
  app.files.deleted { |file| ext.clear_data(file) }
end
clear_data(file) click to toggle source
# File lib/middleman-core/core_extensions/front_matter.rb, line 105
def clear_data(file)
  # Copied from Sitemap::Store#file_to_path, but without
  # removing the file extension
  file = File.join(app.root, file)
  prefix = app.source_dir.sub(/\/$/, '') + '/'
  return unless file.include?(prefix)
  path = file.sub(prefix, '').sub(/\.frontmatter$/, '')

  @cache.delete(path)
end
data(path) click to toggle source
# File lib/middleman-core/core_extensions/front_matter.rb, line 91
def data(path)
  p = normalize_path(path)
  @cache[p] ||= begin
    data, content = frontmatter_and_content(p)

    if app.files.exists?("#{path}.frontmatter")
      external_data, _ = frontmatter_and_content("#{p}.frontmatter")
      data = external_data.deep_merge(data)
    end

    [data, content]
  end
end
template_data_for_file(path) click to toggle source

Get the template data from a path @param [String] path @return [String]

# File lib/middleman-core/core_extensions/front_matter.rb, line 86
def template_data_for_file(path)
  extensions[:frontmatter].data(path).last
end

Private Instance Methods

frontmatter_and_content(path) click to toggle source

Get the frontmatter and plain content from a file @param [String] path @return [Array<Thor::CoreExt::HashWithIndifferentAccess, String>]

# File lib/middleman-core/core_extensions/front_matter.rb, line 168
def frontmatter_and_content(path)
  full_path = if Pathname(path).relative?
    File.join(app.source_dir, path)
  else
    path
  end

  data = {}

  return [data, nil] if !app.files.exists?(full_path) || ::Middleman::Util.binary?(full_path)

  content = File.read(full_path)

  begin
    if content =~ /\A.*coding:/
      lines = content.split(/\n/)
      lines.shift
      content = lines.join("\n")
    end

    result = parse_yaml_front_matter(content, full_path) || parse_json_front_matter(content, full_path)
    return result if result
  rescue
    # Probably a binary file, move on
  end

  [data, content]
end
normalize_path(path) click to toggle source
# File lib/middleman-core/core_extensions/front_matter.rb, line 197
def normalize_path(path)
  path.sub(%r{^#{Regexp.escape(app.source_dir)}\/}, '')
end
parse_json_front_matter(content, full_path) click to toggle source
# File lib/middleman-core/core_extensions/front_matter.rb, line 142
def parse_json_front_matter(content, full_path)
  json_regex = /\A(;;;\s*\n.*?\n?)^(;;;\s*$\n?)/m

  if content =~ json_regex
    content = content.sub(json_regex, '')

    begin
      json = ($1 + $2).sub(';;;', '{').sub(';;;', '}')
      data = ActiveSupport::JSON.decode(json).symbolize_keys
    rescue => e
      app.logger.error "JSON Exception parsing #{full_path}: #{e.message}"
      return false
    end

  else
    return false
  end

  [data, content]
rescue
  [{}, content]
end
parse_yaml_front_matter(content, full_path) click to toggle source

Parse YAML frontmatter out of a string @param [String] content @return [Array<Hash, String>]

# File lib/middleman-core/core_extensions/front_matter.rb, line 121
def parse_yaml_front_matter(content, full_path)
  yaml_regex = /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
  if content =~ yaml_regex
    content = content.sub(yaml_regex, '')

    begin
      data = YAML.load($1) || {}
      data = data.symbolize_keys
    rescue *YAML_ERRORS => e
      app.logger.error "YAML Exception parsing #{full_path}: #{e.message}"
      return false
    end
  else
    return false
  end

  [data, content]
rescue
  [{}, content]
end