lib/nanoc3/helpers/blogging.rb in nanoc3-3.1.0a2 vs lib/nanoc3/helpers/blogging.rb in nanoc3-3.1.0a3
- old
+ new
@@ -8,17 +8,20 @@
# This helper has a few requirements. First, all blog articles should have
# the following attributes:
#
# * `kind` — Set to `"article"`
#
- # * `created_at` — The article’s publication timestamp. This timestamp can
- # be in any format parseable by `Time.parse`.
+ # * `created_at` — The article’s publication timestamp
#
# Some functions in this blogging helper, such as the {#atom_feed} function,
# require additional attributes to be set; these attributes are described in
# the documentation for these functions.
#
+ # All “time” item attributes, site configuration attributes or method
+ # parameters can either be a `Time` instance or a string in any format
+ # parseable by `Time.parse`.
+ #
# The two main functions are {#sorted_articles} and {#atom_feed}.
module Blogging
# Returns an unsorted list of articles, i.e. items where the `kind`
# attribute is set to `"article"`.
@@ -33,11 +36,14 @@
# creation date, so newer articles appear before older articles.
#
# @return [Array] A sorted array containing all articles
def sorted_articles
require 'time'
- articles.sort_by { |a| t = a[:created_at] ; t.is_a?(String) ? Time.parse(t) : t }.reverse
+ articles.sort_by do |a|
+ time = a[:created_at]
+ time.is_a?(String) ? Time.parse(time) : time
+ end.reverse
end
# Returns a string representing the atom feed containing recent articles,
# sorted by descending creation date.
#
@@ -56,22 +62,24 @@
# * `custom_path_in_feed` — The path that will be used instead of the
# normal path in the feed. This can be useful when including
# non-outputted items in a feed; such items could have their custom feed
# path set to the blog path instead, for example.
#
- # The feed will also include dates on which the articles were updated.
- # These are generated automatically; the way this happens depends on the
- # used data source (the filesystem data source checks the file mtimes, for
- # instance).
+ # * `updated_at` — The time when the article was last modified. If this
+ # attribute is not present, the `created_at` attribute will be used as
+ # the time when the article was last modified.
#
# The site configuration will need to have the following attributes:
#
# * `base_url` — The URL to the site, without trailing slash. For
# example, if the site is at “http://example.com/”, the `base_url`
# would be “http://example.com”.
#
- # The feed item will need to have the following attributes:
+ # The feed item will need to know about the feed title, the feed author
+ # name, and the URI corresponding to the author. These can be specified
+ # using parameters, as attributes in the feed item, or in the site
+ # configuration.
#
# * `title` — The title of the feed, which is usually also the title of
# the blog.
#
# * `author_name` — The name of the item’s author.
@@ -105,24 +113,33 @@
# @example Limiting the number of items in a feed
#
# <%= atom_feed :limit => 5 %>
#
# @option params [Number] :limit (5) The maximum number of articles to
- # show
+ # show
#
# @option params [Array] :articles (sorted_articles) A list of articles to
- # include in the feed
+ # include in the feed
#
# @option params [Proc] :content_proc (->{ |article|
- # article.compiled_content(:snapshot => :pre) }) A proc that returns the
- # content of the given article, which is passed as a parameter. This
- # function may not return nil.
+ # article.compiled_content(:snapshot => :pre) }) A proc that returns the
+ # content of the given article, which is passed as a parameter. This
+ # function may not return nil.
#
# @option params [proc] :excerpt_proc (->{ |article| article[:excerpt] })
- # A proc that returns the excerpt of the given article, passed as a
- # parameter. This function should return nil if there is no excerpt.
+ # A proc that returns the excerpt of the given article, passed as a
+ # parameter. This function should return nil if there is no excerpt.
#
+ # @option params [String] :title The feed’s title, if it is not given in
+ # the item attributes.
+ #
+ # @option params [String] :author_name The name of the feed’s author, if
+ # it is not given in the item attributes.
+ #
+ # @option params [String] :author_uri The URI of the feed’s author, if it
+ # is not given in the item attributes.
+ #
# @return [String] The generated feed content
def atom_feed(params={})
require 'builder'
require 'time'
@@ -136,18 +153,21 @@
if @site.config[:base_url].nil?
raise RuntimeError.new('Cannot build Atom feed: site configuration has no base_url')
end
# Check feed item attributes
- if @item[:title].nil?
- raise RuntimeError.new('Cannot build Atom feed: feed item has no title')
+ title = params[:title] || @item[:title] || @site.config[:title]
+ if title.nil?
+ raise RuntimeError.new('Cannot build Atom feed: no title in params, item or site config')
end
- if @item[:author_name].nil?
- raise RuntimeError.new('Cannot build Atom feed: feed item has no author_name')
+ author_name = params[:author_name] || @item[:author_name] || @site.config[:author_name]
+ if author_name.nil?
+ raise RuntimeError.new('Cannot build Atom feed: no author_name in params, item or site config')
end
- if @item[:author_uri].nil?
- raise RuntimeError.new('Cannot build Atom feed: feed item has no author_uri')
+ author_uri = params[:author_uri] || @item[:author_uri] || @site.config[:author_uri]
+ if author_uri.nil?
+ raise RuntimeError.new('Cannot build Atom feed: no author_uri in params, item or site config')
end
# Check article attributes
if relevant_articles.empty?
raise RuntimeError.new('Cannot build Atom feed: no articles')
@@ -155,11 +175,14 @@
if relevant_articles.any? { |a| a[:created_at].nil? }
raise RuntimeError.new('Cannot build Atom feed: one or more articles lack created_at')
end
# Get sorted relevant articles
- sorted_relevant_articles = relevant_articles.sort_by { |a| Time.parse(a[:created_at]) }.reverse.first(limit)
+ sorted_relevant_articles = relevant_articles.sort_by do |a|
+ time = a[:created_at]
+ time.is_a?(String) ? Time.parse(time) : time
+ end.reverse.first(limit)
# Get most recent article
last_article = sorted_relevant_articles.first
# Create builder
@@ -171,23 +194,24 @@
xml.feed(:xmlns => 'http://www.w3.org/2005/Atom') do
root_url = @site.config[:base_url] + '/'
# Add primary attributes
xml.id root_url
- xml.title @item[:title]
+ xml.title title
# Add date
- xml.updated Time.parse(last_article[:created_at]).to_iso8601_time
+ time = last_article[:created_at]
+ xml.updated((time.is_a?(String) ? Time.parse(time) : time).to_iso8601_time)
# Add links
xml.link(:rel => 'alternate', :href => root_url)
xml.link(:rel => 'self', :href => feed_url)
# Add author information
xml.author do
- xml.name @item[:author_name]
- xml.uri @item[:author_uri]
+ xml.name author_name
+ xml.uri author_uri
end
# Add articles
sorted_relevant_articles.each do |a|
# Get URL
@@ -198,12 +222,14 @@
# Add primary attributes
xml.id atom_tag_for(a)
xml.title a[:title], :type => 'html'
# Add dates
- xml.published Time.parse(a[:created_at]).to_iso8601_time
- xml.updated a.mtime.to_iso8601_time
+ create_time = a[:created_at]
+ update_time = a[:updated_at] || a[:created_at]
+ xml.published ((create_time.is_a?(String) ? Time.parse(create_time) : create_time).to_iso8601_time)
+ xml.updated ((update_time.is_a?(String) ? Time.parse(update_time) : update_time).to_iso8601_time)
# Add link
xml.link(:rel => 'alternate', :href => url)
# Add content
@@ -261,10 +287,12 @@
# @return [String] The atom tag for the given item
def atom_tag_for(item)
require 'time'
hostname, base_dir = %r{^.+?://([^/]+)(.*)$}.match(@site.config[:base_url])[1..2]
- formatted_date = Time.parse(item[:created_at]).to_iso8601_date
+
+ time = item[:created_at]
+ formatted_date = (time.is_a?(String) ? Time.parse(time) : time).to_iso8601_date
'tag:' + hostname + ',' + formatted_date + ':' + base_dir + (item.path || item.identifier)
end
end