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