require 'tilt'
require 'coderay'
module SchnitzelPress
class MarkdownRenderer < Redcarpet::Render::HTML
include Redcarpet::Render::SmartyPants
def block_code(code, language)
CodeRay.highlight(code, language)
end
def autolink(link, type)
if link =~ %r{youtube.com\/watch\?v=(.+)$}
youtube_id = $1
%q() % youtube_id
else
%q(%s) % [link, link]
end
end
end
class Post
include Mongoid::Document
store_in :posts
# basic data
field :title, type: String
field :body, type: String
field :slugs, type: Array, default: []
# optional fields
field :summary, type: String
field :link, type: String
field :read_more, type: String
# times & status
field :published_at, type: DateTime
field :status, type: Symbol, default: :draft
# flags
field :disqus, type: Boolean, default: false
# extra
field :body_html, type: String
validates_presence_of :status, :slug
validates_inclusion_of :status, in: [:draft, :published]
scope :published, where(:status => :published)
scope :drafts, where(:status => :draft)
scope :pages, where(:published_at => nil)
scope :posts, where(:published_at.ne => nil)
scope :article_posts, -> { posts.where(:link => nil) }
scope :link_posts, -> { posts.where(:link.ne => nil) }
scope :for_year, ->(year) { d = Date.new(year) ; where(published_at: (d.beginning_of_year)..(d.end_of_year)) }
scope :for_month, ->(year, month) { d = Date.new(year, month) ; where(published_at: (d.beginning_of_month)..(d.end_of_month)) }
scope :for_day, ->(year, month, day) { d = Date.new(year, month, day) ; where(published_at: (d.beginning_of_day)..(d.end_of_day)) }
scope :latest, -> { published.posts.desc(:published_at) }
before_validation :nil_if_blank
before_validation :set_defaults
validate :validate_slug
before_save :update_body_html
def disqus_identifier
slug
end
def slug
slugs.try(:last)
end
def previous_slugs
slugs[0..-2]
end
def published_at=(v)
v = Chronic.parse(v) if v.is_a?(String)
super(v)
end
def slug=(v)
unless v.blank?
slugs.delete(v)
slugs << v
end
end
def set_defaults
if slug.blank? && title.present?
self.slug = title.parameterize
end
end
def validate_slug
conflicting_posts = Post.where(slugs: slug)
if published_at.present?
conflicting_posts = conflicting_posts.for_day(published_at.year, published_at.month, published_at.day)
end
if conflicting_posts.any? && conflicting_posts.first != self
errors[:slug] = "This slug is already in use by another post."
end
end
def nil_if_blank
attributes.keys.each do |attr|
self[attr].strip! if self[attr].is_a?(String)
self[attr] = nil if self[attr] == ""
end
end
def update_body_html
self.body_html = render
end
def to_html
if body_html.nil?
update_body_html
save
end
body_html
end
def render
@@markdown ||= Redcarpet::Markdown.new(MarkdownRenderer,
autolink: true, space_after_headers: true, fenced_code_blocks: true)
@@markdown.render(body)
end
def post?
published_at.present?
end
def page?
!post?
end
def published?
status == :published
end
def draft?
status == :draft
end
def link_post?
link.present?
end
def article_post?
link.nil?
end
def year
published_at.year
end
def month
published_at.month
end
def day
published_at.day
end
def to_url
published_at.present? ? "/#{year}/#{month}/#{day}/#{slug}/" : "/#{slug}/"
end
def disqus?
disqus && published?
end
end
end