Class: Mango::ContentPage

Inherits:
Object
  • Object
show all
Defined in:
lib/mango/content_page.rb

Overview

ContentPage is a model class. An instance of ContentPage is the representation of a single content file. The primary responsiblity of ContentPage is to manage the conversion of user-generated data into markup like HTML. It accomplishes this task by utilizing a variety of content engines.

A ContentPage file contains two optional components -- a body and a header.

Example content file

# mango_poem.markdown
---
title: The Sin of Mango
categories:
  - bad
  - poetry
---
Mango is like a drug.
You must have more and more and more of the Mango
until there is no Mango left.
Not even for Mango!

Mangos aside, the above example highlights the key facets of writing a content page.

  1. A content page is stored as a file in the content directory Here, the file name is mango_poem.markdown.
  2. The header, if defined, comes first and is embedded within triple-dashed --- dividers.
  3. The body comes second, nestled comfortably below the header.
  4. The header is composed of key-value attribute pairs in YAML format.
  5. The file's extension signals that the body should be treated as Markdown.

The Header

The header is composed of key-value attribute pairs in YAML format.

Each ContentPage instance is passed into their body and view templates as the page local variable. For example, this is how to access the header attributes of a content page inside an ERB template:

<h1><%= page.title %></h1>

The Body

The body of a content file supports many writer and designer friendly formats. The content file's extension determines the body's format, and therefore, the template engine used to convert the body into markup like HTML. For a list of supported content page template engines, and their formats, see Mango::ContentPage::TEMPLATE_ENGINES.

Each ContentPage instance is passed into their body and view templates as the page local variable. For example, this is how to access the complete data, pre-rendered body, and rendered content of a content page inside an ERB template:

<p><%= page.data %></p>
<p><%= page.body %></p>
<p><%= page.content %></p>

The View Attribute and Template

Each ContentPage instance has a view attribute, even if one is not explicitly declared in the content file. This attribute is essential as it guides the Mango::Application to render the correct view template file. The default view template file name is defined by Mango::ContentPage::DEFAULT_ATTRIBUTES.

When declaring an explicit view template, the relative file name is required. For example, given the following content page:

---
view: blog.haml
---

The Mango::Application will attempt to render the content page within the blog.haml view template if it exists in the Mango::Application.settings.views directory. The supported view template engines are defined by Mango::Application::VIEW_TEMPLATE_ENGINES.

Defined Under Namespace

Classes: InvalidHeaderError

Constant Summary collapse

TEMPLATE_ENGINES =

Supported content page template engines

{
  Tilt::BlueClothTemplate => :markdown,
  Tilt::HamlTemplate      => :haml,
  Tilt::ERBTemplate       => :erb,
  Tilt::LiquidTemplate    => :liquid
}
DEFAULT_ATTRIBUTES =

Default key-value attribute pairs

{
  "engine" => TEMPLATE_ENGINES.key(:markdown),
  "view"   => "page.haml"
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ContentPage

Creates a new instance by extracting the body and attributes from raw data. Any extracted components found are merged with their defaults.

Options Hash (options):

  • :data (String)

    Contains a body and possibly a YAML header

  • :engine (Symbol)

    See TEMPLATE_ENGINES and DEFAULT_ATTRIBUTES["engine"]

Raises:

  • (ArgumentError)

    Raised when registered content engine cannot be found

  • (InvalidHeaderError)

    Raised when YAML header is invalid


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/mango/content_page.rb', line 112

def initialize(options = {})
  data   = options[:data]   || ""
  engine = options[:engine] || DEFAULT_ATTRIBUTES["engine"]

  unless TEMPLATE_ENGINES.include?(engine)
    raise ArgumentError, "Cannot find registered content engine -- #{engine}"
  end

  @attributes = DEFAULT_ATTRIBUTES.dup

  @attributes["body"] = if data =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
    begin
      header = YAML.load($1) || {}
    rescue Exception => e
      raise InvalidHeaderError, e.message
    end

    begin
      @attributes.merge!(header)
    rescue
      raise InvalidHeaderError, "Cannot parse header -- #{header.inspect}"
    end

    $'  # aka $POSTMATCH
  else
    data
  end

  FlavoredMarkdown.shake!(@attributes["body"]) if engine == TEMPLATE_ENGINES.key(:markdown)
  @attributes.merge!("engine" => engine, "data" => data, "content" => nil)

  @attributes["content"] = engine.new { @attributes["body"] }.render(nil, page: self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object (private)

Adds syntactic suger for reading attributes.

Examples:

page.title == page.attributes["title"]

Raises:

  • (NoMethodError)

    Raised when there is no method name key in attributes


159
160
161
162
# File 'lib/mango/content_page.rb', line 159

def method_missing(method_name, *args, &block)
  key = method_name.to_s
  attributes.has_key?(key) ? attributes[key] : super
end

Instance Attribute Details

#attributesHash (readonly) Also known as: to_liquid

Contains the engine, data, body, content, view, and any header key-value pairs


100
101
102
# File 'lib/mango/content_page.rb', line 100

def attributes
  @attributes
end