class BlogGenerator::Post

Constants

REGEXP

Attributes

format[R]
metadata[R]
site[R]

Public Class Methods

new(site, path) click to toggle source
# File lib/blog-generator/post.rb, line 18
def initialize(site, path)
  # TODO: metadata so we can construct url (base_url + relative) AND merge author
  @site, @path = site, File.expand_path(path)

  # TODO: Bring back .md from adapters/markdown.rb
  published_on, slug, format = parse_path(path)

  @metadata = self.load_metadata
  @metadata.merge!(slug: slug)
  @metadata.merge!(excerpt: excerpt)
  @metadata.merge!(path: "/posts/#{slug}") ### TODO: some routing config.
  @metadata.merge!(links: self.links)

  @metadata[:tags].map! do |tag|
    slug = generate_slug(tag)
    {title: tag, slug: slug, path: "/tags/#{slug}"}
  end
end

Public Instance Methods

absolute_url() click to toggle source
# File lib/blog-generator/post.rb, line 65
def absolute_url
  [site.base_url, self.relative_url].join('')
end
as_json() click to toggle source
# File lib/blog-generator/post.rb, line 130
def as_json
  @metadata.merge(body: self.post_processed_body).tap do |metadata|
    metadata[:published_at] && metadata[:published_at] = DateTime.parse(metadata[:published_at])
    metadata[:updated_at]   && metadata[:updated_at]   = DateTime.parse(metadata[:updated_at])
  end
end
author() click to toggle source
# File lib/blog-generator/post.rb, line 49
def author
  self.metadata[:author] || site.author
end
body() click to toggle source
# File lib/blog-generator/post.rb, line 73
def body
  @body ||= begin
    process_body(nokogiri_raw_document.dup)
  end
end
email() click to toggle source
# File lib/blog-generator/post.rb, line 53
def email
  self.metadata[:email] || site.email
end
excerpt() click to toggle source
# File lib/blog-generator/post.rb, line 123
def excerpt
  @excerpt ||= begin
    document = nokogiri_raw_document.dup
    document.css('#excerpt').inner_html.sub(/^\s*(.*)\s*$/, '\1').chomp
  end
end
generate_slug(name) click to toggle source
# File lib/blog-generator/post.rb, line 57
def generate_slug(name) # for tags, should go to utils or something.
  name.downcase.tr(' /', '-').delete('!?')
end
image_binary_data(asset_path) click to toggle source
# File lib/blog-generator/post.rb, line 113
def image_binary_data(asset_path)
  require 'base64'

  extension    = File.extname(asset_path)[1..-1]
  binary_data  = File.read(asset_path)
  encoded_data = Base64.encode64(binary_data)

  "data:image/#{extension};base64,#{encoded_data}"
end
load_metadata() click to toggle source
# File lib/blog-generator/post.rb, line 43
def load_metadata
  self.raw_metadata.reduce(Hash.new) do |buffer, (slug, value)|
    buffer.merge(slug.to_sym => try_to_dup(value))
  end
end
post_process_body(text) click to toggle source

This is a terrible hack to make unescaped code possible.

# File lib/blog-generator/post.rb, line 99
def post_process_body(text)
  regexp = /<code lang="(\w+)"(?: file="([^"]+)")?>\n?(.*?)<\/code>/m
  p original_body_matches = self.raw_body.scan(regexp)

  text.gsub(regexp).with_index do |pre, index|
    language, file, code = original_body_matches[index]
    if file
      "<figure><figcaption class='filepath'>#{file}</figcaption><pre><code class=\"#{language}\">#{CGI.escapeHTML(code)}</code></pre></figure>"
    else
      "<pre><code class=\"#{language}\">#{CGI.escapeHTML(code)}</code></pre>"
    end
  end
end
post_processed_body() click to toggle source
# File lib/blog-generator/post.rb, line 94
def post_processed_body
  @post_processed_body ||= post_process_body(self.body.to_s)
end
process_body(document) click to toggle source
# File lib/blog-generator/post.rb, line 79
def process_body(document)
  document.css('#excerpt').remove
  document.css('img[src^="/assets/"]').each do |img|
    absolute_url = img.attribute('src').value
    asset_path   = "..#{absolute_url}" # This is extremely shakey, it depends on us being in api.botanicus.me.
    if File.exists?(asset_path)
      img['src'] = image_binary_data(asset_path)
    else
      raise "Asset #{asset_path} doesn't exist."
    end
  end

  document.css('body').inner_html.strip
end
raw_body() click to toggle source
# File lib/blog-generator/post.rb, line 69
def raw_body
  File.read(@path).match(/\n---\n(.+)$/m)[1].strip
end
raw_metadata() click to toggle source
# File lib/blog-generator/post.rb, line 37
def raw_metadata
  @raw_metadata ||= begin
    YAML.load_file(@path) || raise("Metadata in #{@path} are not valid YAML.")
  end
end
relative_url() click to toggle source
# File lib/blog-generator/post.rb, line 61
def relative_url
  "/posts/#{slug}"
end
save(extra_metadata = Hash.new) click to toggle source
# File lib/blog-generator/post.rb, line 141
    def save(extra_metadata = Hash.new)
      extra_metadata = extra_metadata.reduce(Hash.new) do |buffer, (key, value)|
        buffer.merge(key.to_s => value)
      end

      excerpt = self.excerpt.empty? ? %Q{<p id="excerpt">\n</p>} : %Q{<p id="excerpt">\n  #{self.excerpt}\n</p>}
      metadata = self.raw_metadata.merge(extra_metadata)
      <<-EOF
#{metadata.map { |key, value| "#{key}: #{value}"}.join("\n")}
---

#{excerpt}

#{self.post_processed_body}
      EOF
    end
to_json(*args) click to toggle source
# File lib/blog-generator/post.rb, line 137
def to_json(*args)
  self.as_json.to_json(*args)
end

Private Instance Methods

nokogiri_raw_document() click to toggle source
# File lib/blog-generator/post.rb, line 165
def nokogiri_raw_document
  @nokogiri_raw_document ||= Nokogiri::HTML(self.raw_body)
end
parse_path(path) click to toggle source
# File lib/blog-generator/post.rb, line 169
def parse_path(path)
  match = File.basename(path).match(REGEXP)
  published_on = match[1] ? Date.parse(match[1]).to_time.utc : nil
  [published_on, match[3], match[4].to_sym]
end
try_to_dup(value) click to toggle source

true and some others cannot be cloned.

# File lib/blog-generator/post.rb, line 176
def try_to_dup(value)
  value.dup
rescue TypeError
  value
end