module Shinmun # This class represents a post or page. # Each post has a header, encoded as YAML and a body. # # Example: # --- # category: Ruby # date: 2008-09-05 # # BlueCloth, a Markdown library # ============================= # # This is the summary, which is by definition the first paragraph of the # article. The summary shows up in list views and rss feeds. # class Post # Define accessor methods for head variable. def self.head_accessor(*names) names.each do |name| name = name.to_s define_method(name) { @head[name] } define_method("#{name}=") {|v| @head[name] = v } end end attr_accessor :prefix, :path, :type, :title, :head, :body, :summary, :body_html head_accessor :author, :date, :category, :tags, :languages, :header # Initialize empty post and set specified attributes. def initialize(attributes={}) @head = {} @body = '' for k, v in attributes send "#{k}=", v end end # Shortcut for year of date def year date.year end # Shortcut for month of date def month date.month end def filename "#{prefix}/#{path}.#{type}" end # Strips off extension and prefix. def filename=(file) if match = file.match(/^(.*?)\/(.*)\.(.*)/) @prefix = match[1] @path = match[2] @type = match[3] else raise "incorrect filename: #{file}" end end # Split up the source into header and body. Load the header as # yaml document. Render body and parse the summary from rendered html. def parse(src) # Parse YAML header if present if src =~ /---.*?\n(.*?)\n\n(.*)/m @head = YAML.load($1) @body = $2 else @body = src end @title = head['title'] or parse_title @body_html = transform(body, type) @summary = body_html.split("\n\n")[0] self end # Parse title from different formats def parse_title lines = body.split("\n") case type when 'md' @title = lines.shift.sub(/(^#+|#+$)/,'').strip lines.shift if lines.first.match(/^(=|-)+$/) when 'html' @title = lines.shift.sub(/(