Module: Nanoc::Helpers::Blogging

Included in:
AtomFeedBuilder
Defined in:
lib/nanoc/helpers/blogging.rb

Overview

Provides functionality for building blogs, such as finding articles and constructing feeds.

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

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.

Defined Under Namespace

Classes: AtomFeedBuilder

Instance Method Summary (collapse)

Instance Method Details

- (Array) articles

Returns an unsorted list of articles, i.e. items where the kind attribute is set to "article".

Returns:

  • (Array)

    An array containing all articles



28
29
30
31
32
33
34
35
# File 'lib/nanoc/helpers/blogging.rb', line 28

def articles
  blk = -> { @items.select { |item| item[:kind] == 'article' } }
  if @items.frozen?
    @article_items ||= blk.call
  else
    blk.call
  end
end

- (String) atom_feed(params = {})

Returns a string representing the atom feed containing recent articles, sorted by descending creation date.

The following attributes must be set on blog articles:

  • title - The title of the blog post

  • created_at (described above)

  • kind (described above) unless you are passing an explicit list of articles using the :articles parameter

The following attributes can optionally be set on blog articles to change the behaviour of the Atom feed:

  • excerpt - An excerpt of the article, which is usually only a few lines long.

  • 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.

  • custom_url_in_feed - The url that will be used instead of the normal url in the feed (generated from the site’s base url + the item rep’s path). This can be useful when building a link-blog where the URL of article is a remote location.

  • 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 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.

  • author_uri - The URI for the item’s author, such as the author’s web site URL.

The feed item can have the following optional attributes:

  • feed_url - The custom URL of the feed. This can be useful when the private feed URL shouldn’t be exposed; for example, when using FeedBurner this would be set to the public FeedBurner URL.

To construct a feed, create a new item and make sure that it is filtered with :erb or :erubis; it should not be laid out. Ensure that it is routed to the proper path, e.g. /blog.xml. It may also be useful to set the is_hidden attribute to true, so that helpers such as the sitemap helper will ignore the item. The content of the feed item should be <%= atom_feed %>.

Examples:

Defining compilation and routing rules for a feed item


compile '/blog/feed/' do
  filter :erb
end

route '/blog/feed/' do
  '/blog.xml'
end

Limiting the number of items in a feed


<%= atom_feed :limit => 5 %>

Parameters:

  • params (Hash) (defaults to: {})

    a customizable set of options

Options Hash (params):

  • :limit (Number) — default: 5

    The maximum number of articles to show

  • :articles (Array) — default: articles

    A list of articles to include in the feed

  • :preserve_order (Boolean) — default: false

    Whether or not the ordering of the list of articles should be preserved. If false, the articles will be sorted by created_at. If true, the list of articles will be used as-is, and should have the most recent articles last.

  • :content_proc (Proc) — default: ->{ |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.

  • :excerpt_proc (proc) — default: ->{ |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.

  • :title (String)

    The feed’s title, if it is not given in the item attributes.

  • :author_name (String)

    The name of the feed’s author, if it is not given in the item attributes.

  • :author_uri (String)

    The URI of the feed’s author, if it is not given in the item attributes.

  • :icon (String)

    The URI of the feed’s icon.

  • :logo (String)

    The URI of the feed’s logo.

Returns:

  • (String)

    The generated feed content



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/nanoc/helpers/blogging.rb', line 307

def atom_feed(params = {})
  require 'builder'

  # Create builder
  builder = AtomFeedBuilder.new(@site, @item)

  # Fill builder
  builder.limit             = params[:limit] || 5
  builder.relevant_articles = params[:articles] || articles || []
  builder.preserve_order    = params.fetch(:preserve_order, false)
  builder.content_proc      = params[:content_proc] || ->(a) { a.compiled_content(snapshot: :pre) }
  builder.excerpt_proc      = params[:excerpt_proc] || ->(a) { a[:excerpt] }
  builder.title             = params[:title] || @item[:title] || @site.config[:title]
  builder.author_name       = params[:author_name] || @item[:author_name] || @site.config[:author_name]
  builder.author_uri        = params[:author_uri] || @item[:author_uri] || @site.config[:author_uri]
  builder.icon              = params[:icon]
  builder.              = params[:logo]

  # Run
  builder.validate
  builder.build
end

- (String) atom_tag_for(item)

Returns an URI containing an unique ID for the given item. This will be used in the Atom feed to uniquely identify articles. These IDs are created using a procedure suggested by Mark Pilgrim and described in his [“How to make a good ID in Atom” blog post] (http://web.archive.org/web/20110915110202/http://diveintomark.org/archives/2004/05/28/howto-atom-id).

Parameters:

  • item (Nanoc::Item)

    The item for which to create an atom tag

Returns:

  • (String)

    The atom tag for the given item



374
375
376
377
378
379
380
# File 'lib/nanoc/helpers/blogging.rb', line 374

def atom_tag_for(item)
  hostname, base_dir = %r{^.+?://([^/]+)(.*)$}.match(@site.config[:base_url])[1..2]

  formatted_date = attribute_to_time(item[:created_at]).to_iso8601_date

  'tag:' + hostname + ',' + formatted_date + ':' + base_dir + (item.path || item.identifier)
end

- (Time) attribute_to_time(time)

Converts the given attribute (which can be a string, a Time or a Date) into a Time.

Parameters:

  • time (String, Time, Date)

    Something that contains time information but is not necessarily a Time instance yet

Returns:

  • (Time)

    The Time instance corresponding to the given input



389
390
391
392
393
# File 'lib/nanoc/helpers/blogging.rb', line 389

def attribute_to_time(time)
  time = Time.local(time.year, time.month, time.day) if time.is_a?(Date)
  time = Time.parse(time) if time.is_a?(String)
  time
end

- (String) feed_url

Returns the URL of the feed. It will return the custom feed URL if set, or otherwise the normal feed URL.

Returns:

  • (String)

    The URL of the feed



356
357
358
359
360
361
362
363
# File 'lib/nanoc/helpers/blogging.rb', line 356

def feed_url
  # Check attributes
  if @site.config[:base_url].nil?
    raise Nanoc::Errors::GenericTrivial.new('Cannot build Atom feed: site configuration has no base_url')
  end

  @item[:feed_url] || @site.config[:base_url] + @item.path
end

- (Array) sorted_articles

Returns a sorted list of articles, i.e. items where the kind attribute is set to "article". Articles are sorted by descending creation date, so newer articles appear before older articles.

Returns:

  • (Array)

    A sorted array containing all articles



42
43
44
45
46
47
48
49
50
# File 'lib/nanoc/helpers/blogging.rb', line 42

def sorted_articles
  blk = -> { articles.sort_by { |a| attribute_to_time(a[:created_at]) }.reverse }

  if @items.frozen?
    @sorted_article_items ||= blk.call
  else
    blk.call
  end
end

- (String) url_for(item)

Returns the URL for the given item. It will return the URL containing the custom path in the feed if possible, otherwise the normal path.

Parameters:

  • item (Nanoc::Item)

    The item for which to fetch the URL.

Returns:

  • (String)

    The URL of the given item



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/nanoc/helpers/blogging.rb', line 336

def url_for(item)
  # Check attributes
  if @site.config[:base_url].nil?
    raise Nanoc::Errors::GenericTrivial.new('Cannot build Atom feed: site configuration has no base_url')
  end

  # Build URL
  if item[:custom_url_in_feed]
    item[:custom_url_in_feed]
  elsif item[:custom_path_in_feed]
    @site.config[:base_url] + item[:custom_path_in_feed]
  elsif item.path
    @site.config[:base_url] + item.path
  end
end