nanoc2 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +3 -0
- data/LICENSE +19 -0
- data/README +75 -0
- data/Rakefile +76 -0
- data/bin/nanoc2 +26 -0
- data/lib/nanoc2.rb +73 -0
- data/lib/nanoc2/base.rb +26 -0
- data/lib/nanoc2/base/asset.rb +117 -0
- data/lib/nanoc2/base/asset_defaults.rb +21 -0
- data/lib/nanoc2/base/asset_rep.rb +282 -0
- data/lib/nanoc2/base/binary_filter.rb +44 -0
- data/lib/nanoc2/base/code.rb +41 -0
- data/lib/nanoc2/base/compiler.rb +67 -0
- data/lib/nanoc2/base/core_ext.rb +2 -0
- data/lib/nanoc2/base/core_ext/hash.rb +78 -0
- data/lib/nanoc2/base/core_ext/string.rb +8 -0
- data/lib/nanoc2/base/data_source.rb +286 -0
- data/lib/nanoc2/base/defaults.rb +30 -0
- data/lib/nanoc2/base/filter.rb +93 -0
- data/lib/nanoc2/base/layout.rb +91 -0
- data/lib/nanoc2/base/notification_center.rb +66 -0
- data/lib/nanoc2/base/page.rb +132 -0
- data/lib/nanoc2/base/page_defaults.rb +20 -0
- data/lib/nanoc2/base/page_rep.rb +324 -0
- data/lib/nanoc2/base/plugin.rb +71 -0
- data/lib/nanoc2/base/proxies.rb +5 -0
- data/lib/nanoc2/base/proxies/asset_proxy.rb +29 -0
- data/lib/nanoc2/base/proxies/asset_rep_proxy.rb +26 -0
- data/lib/nanoc2/base/proxies/layout_proxy.rb +25 -0
- data/lib/nanoc2/base/proxies/page_proxy.rb +35 -0
- data/lib/nanoc2/base/proxies/page_rep_proxy.rb +28 -0
- data/lib/nanoc2/base/proxy.rb +37 -0
- data/lib/nanoc2/base/router.rb +72 -0
- data/lib/nanoc2/base/site.rb +274 -0
- data/lib/nanoc2/base/template.rb +64 -0
- data/lib/nanoc2/binary_filters.rb +1 -0
- data/lib/nanoc2/binary_filters/image_science_thumbnail.rb +28 -0
- data/lib/nanoc2/cli.rb +9 -0
- data/lib/nanoc2/cli/base.rb +132 -0
- data/lib/nanoc2/cli/commands.rb +10 -0
- data/lib/nanoc2/cli/commands/autocompile.rb +80 -0
- data/lib/nanoc2/cli/commands/compile.rb +312 -0
- data/lib/nanoc2/cli/commands/create_layout.rb +85 -0
- data/lib/nanoc2/cli/commands/create_page.rb +85 -0
- data/lib/nanoc2/cli/commands/create_site.rb +323 -0
- data/lib/nanoc2/cli/commands/create_template.rb +76 -0
- data/lib/nanoc2/cli/commands/help.rb +69 -0
- data/lib/nanoc2/cli/commands/info.rb +125 -0
- data/lib/nanoc2/cli/commands/switch.rb +141 -0
- data/lib/nanoc2/cli/commands/update.rb +91 -0
- data/lib/nanoc2/cli/logger.rb +72 -0
- data/lib/nanoc2/data_sources.rb +2 -0
- data/lib/nanoc2/data_sources/filesystem.rb +707 -0
- data/lib/nanoc2/data_sources/filesystem_combined.rb +495 -0
- data/lib/nanoc2/extra.rb +6 -0
- data/lib/nanoc2/extra/auto_compiler.rb +285 -0
- data/lib/nanoc2/extra/context.rb +22 -0
- data/lib/nanoc2/extra/core_ext.rb +2 -0
- data/lib/nanoc2/extra/core_ext/hash.rb +54 -0
- data/lib/nanoc2/extra/core_ext/time.rb +13 -0
- data/lib/nanoc2/extra/file_proxy.rb +29 -0
- data/lib/nanoc2/extra/vcs.rb +48 -0
- data/lib/nanoc2/extra/vcses.rb +5 -0
- data/lib/nanoc2/extra/vcses/bazaar.rb +21 -0
- data/lib/nanoc2/extra/vcses/dummy.rb +20 -0
- data/lib/nanoc2/extra/vcses/git.rb +21 -0
- data/lib/nanoc2/extra/vcses/mercurial.rb +21 -0
- data/lib/nanoc2/extra/vcses/subversion.rb +21 -0
- data/lib/nanoc2/filters.rb +16 -0
- data/lib/nanoc2/filters/bluecloth.rb +13 -0
- data/lib/nanoc2/filters/erb.rb +19 -0
- data/lib/nanoc2/filters/erubis.rb +14 -0
- data/lib/nanoc2/filters/haml.rb +21 -0
- data/lib/nanoc2/filters/markaby.rb +14 -0
- data/lib/nanoc2/filters/maruku.rb +14 -0
- data/lib/nanoc2/filters/old.rb +19 -0
- data/lib/nanoc2/filters/rainpress.rb +13 -0
- data/lib/nanoc2/filters/rdiscount.rb +13 -0
- data/lib/nanoc2/filters/rdoc.rb +23 -0
- data/lib/nanoc2/filters/redcloth.rb +14 -0
- data/lib/nanoc2/filters/relativize_paths.rb +16 -0
- data/lib/nanoc2/filters/relativize_paths_in_css.rb +16 -0
- data/lib/nanoc2/filters/relativize_paths_in_html.rb +16 -0
- data/lib/nanoc2/filters/rubypants.rb +14 -0
- data/lib/nanoc2/filters/sass.rb +18 -0
- data/lib/nanoc2/helpers.rb +9 -0
- data/lib/nanoc2/helpers/blogging.rb +217 -0
- data/lib/nanoc2/helpers/capturing.rb +63 -0
- data/lib/nanoc2/helpers/filtering.rb +54 -0
- data/lib/nanoc2/helpers/html_escape.rb +25 -0
- data/lib/nanoc2/helpers/link_to.rb +113 -0
- data/lib/nanoc2/helpers/render.rb +49 -0
- data/lib/nanoc2/helpers/tagging.rb +56 -0
- data/lib/nanoc2/helpers/text.rb +38 -0
- data/lib/nanoc2/helpers/xml_sitemap.rb +63 -0
- data/lib/nanoc2/routers.rb +3 -0
- data/lib/nanoc2/routers/default.rb +54 -0
- data/lib/nanoc2/routers/no_dirs.rb +66 -0
- data/lib/nanoc2/routers/versioned.rb +79 -0
- metadata +185 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nanoc2::Extra::VCSes
|
2
|
+
|
3
|
+
class Bazaar < Nanoc2::Extra::VCS
|
4
|
+
|
5
|
+
identifiers :bazaar, :bzr
|
6
|
+
|
7
|
+
def add(filename)
|
8
|
+
system('bzr', 'add', filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove(filename)
|
12
|
+
system('bzr', 'rm', filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def move(src, dst)
|
16
|
+
system('bzr', 'mv', src, dst)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Nanoc2::Extra::VCSes
|
2
|
+
|
3
|
+
class Dummy < Nanoc2::Extra::VCS
|
4
|
+
|
5
|
+
identifiers :dummy
|
6
|
+
|
7
|
+
def add(filename)
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove(filename)
|
11
|
+
FileUtils.rm_rf(filename)
|
12
|
+
end
|
13
|
+
|
14
|
+
def move(src, dst)
|
15
|
+
FileUtils.move(src, dst)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nanoc2::Extra::VCSes
|
2
|
+
|
3
|
+
class Git < Nanoc2::Extra::VCS
|
4
|
+
|
5
|
+
identifiers :git
|
6
|
+
|
7
|
+
def add(filename)
|
8
|
+
system('git', 'add', filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove(filename)
|
12
|
+
system('git', 'rm', filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def move(src, dst)
|
16
|
+
system('git', 'mv', src, dst)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nanoc2::Extra::VCSes
|
2
|
+
|
3
|
+
class Mercurial < Nanoc2::Extra::VCS
|
4
|
+
|
5
|
+
identifiers :mercurial, :hg
|
6
|
+
|
7
|
+
def add(filename)
|
8
|
+
system('hg', 'add', filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove(filename)
|
12
|
+
system('hg', 'rm', filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def move(src, dst)
|
16
|
+
system('hg', 'mv', src, dst)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nanoc2::Extra::VCSes
|
2
|
+
|
3
|
+
class Subversion < Nanoc2::Extra::VCS
|
4
|
+
|
5
|
+
identifiers :subversion, :svn
|
6
|
+
|
7
|
+
def add(filename)
|
8
|
+
system('svn', 'add', filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove(filename)
|
12
|
+
system('svn', 'rm', filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def move(src, dst)
|
16
|
+
system('svn', 'mv', src, dst)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'nanoc2/filters/bluecloth'
|
2
|
+
require 'nanoc2/filters/erb'
|
3
|
+
require 'nanoc2/filters/erubis'
|
4
|
+
require 'nanoc2/filters/haml'
|
5
|
+
require 'nanoc2/filters/markaby'
|
6
|
+
require 'nanoc2/filters/maruku'
|
7
|
+
require 'nanoc2/filters/old'
|
8
|
+
require 'nanoc2/filters/rainpress'
|
9
|
+
require 'nanoc2/filters/rdiscount'
|
10
|
+
require 'nanoc2/filters/rdoc'
|
11
|
+
require 'nanoc2/filters/redcloth'
|
12
|
+
require 'nanoc2/filters/relativize_paths'
|
13
|
+
require 'nanoc2/filters/relativize_paths_in_css'
|
14
|
+
require 'nanoc2/filters/relativize_paths_in_html'
|
15
|
+
require 'nanoc2/filters/rubypants'
|
16
|
+
require 'nanoc2/filters/sass'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class ERB < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifiers :erb
|
5
|
+
|
6
|
+
def run(content)
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
# Create context
|
10
|
+
context = ::Nanoc2::Extra::Context.new(assigns)
|
11
|
+
|
12
|
+
# Get result
|
13
|
+
erb = ::ERB.new(content)
|
14
|
+
erb.filename = filename
|
15
|
+
erb.result(context.get_binding)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class Haml < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifiers :haml
|
5
|
+
|
6
|
+
def run(content)
|
7
|
+
require 'haml'
|
8
|
+
|
9
|
+
# Get options
|
10
|
+
options = @obj_rep.attribute_named(:haml_options) || {}
|
11
|
+
options[:filename] = filename
|
12
|
+
|
13
|
+
# Create context
|
14
|
+
context = ::Nanoc2::Extra::Context.new(assigns)
|
15
|
+
|
16
|
+
# Get result
|
17
|
+
::Haml::Engine.new(content, options).render(context, assigns)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class Old < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifiers :eruby, :markdown, :smartypants, :textile
|
5
|
+
|
6
|
+
def run(content)
|
7
|
+
raise Nanoc2::Error.new(
|
8
|
+
"The 'eruby', markdown', 'smartypants' and 'textile' filters no " +
|
9
|
+
"longer exist. Instead, use the following filters:\n" +
|
10
|
+
"\n" +
|
11
|
+
"* for Markdown: bluecloth, rdiscount, redcloth\n" +
|
12
|
+
"* for Textile: redcloth\n" +
|
13
|
+
"* for embedded Ruby: erb, erubis\n" +
|
14
|
+
"* for Smartypants: rubypants"
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class RDoc < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifiers :rdoc
|
5
|
+
|
6
|
+
def run(content)
|
7
|
+
begin
|
8
|
+
# new RDoc
|
9
|
+
require 'rdoc/markup'
|
10
|
+
require 'rdoc/markup/to_html'
|
11
|
+
|
12
|
+
::RDoc::Markup.new.convert(content, ::RDoc::Markup::ToHtml.new)
|
13
|
+
rescue LoadError
|
14
|
+
# old RDoc
|
15
|
+
require 'rdoc/markup/simple_markup'
|
16
|
+
require 'rdoc/markup/simple_markup/to_html'
|
17
|
+
|
18
|
+
::SM::SimpleMarkup.new.convert(content, ::SM::ToHtml.new)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class RelativizePaths < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifier :relativize_paths
|
5
|
+
|
6
|
+
def run(content)
|
7
|
+
raise RuntimeError.new(
|
8
|
+
"The relativize_paths filter itself does not exist anymore. " +
|
9
|
+
"If you want to relativize paths in HTML, use the " +
|
10
|
+
"relativize_paths_in_html filter; if you want to relativize paths " +
|
11
|
+
"in CSS, use the relativize_paths_in_css filter."
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class RelativizePathsInCSS < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifier :relativize_paths_in_css
|
5
|
+
|
6
|
+
require 'nanoc2/helpers/link_to'
|
7
|
+
include Nanoc2::Helpers::LinkTo
|
8
|
+
|
9
|
+
def run(content)
|
10
|
+
content.gsub(/url\((['"]?)(\/.+?)\1\)/) do
|
11
|
+
'url(' + $1 + relative_path_to($2) + $1 + ')'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class RelativizePathsInHTML < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifier :relativize_paths_in_html
|
5
|
+
|
6
|
+
require 'nanoc2/helpers/link_to'
|
7
|
+
include Nanoc2::Helpers::LinkTo
|
8
|
+
|
9
|
+
def run(content)
|
10
|
+
content.gsub(/(src|href)=(['"]?)(\/.+?)\2([ >])/) do
|
11
|
+
$1 + '=' + $2 + relative_path_to($3) + $2 + $4
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Nanoc2::Filters
|
2
|
+
class Sass < Nanoc2::Filter
|
3
|
+
|
4
|
+
identifiers :sass
|
5
|
+
|
6
|
+
def run(content)
|
7
|
+
require 'sass'
|
8
|
+
|
9
|
+
# Get options
|
10
|
+
options = @obj_rep.attribute_named(:sass_options) || {}
|
11
|
+
options[:filename] = filename
|
12
|
+
|
13
|
+
# Get result
|
14
|
+
::Sass::Engine.new(content, options).render
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'nanoc2/helpers/blogging'
|
2
|
+
require 'nanoc2/helpers/capturing'
|
3
|
+
require 'nanoc2/helpers/filtering'
|
4
|
+
require 'nanoc2/helpers/html_escape'
|
5
|
+
require 'nanoc2/helpers/link_to'
|
6
|
+
require 'nanoc2/helpers/render'
|
7
|
+
require 'nanoc2/helpers/tagging'
|
8
|
+
require 'nanoc2/helpers/text'
|
9
|
+
require 'nanoc2/helpers/xml_sitemap'
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module Nanoc2::Helpers
|
2
|
+
|
3
|
+
# Nanoc2::Helpers::Blogging provides some functionality for building blogs,
|
4
|
+
# such as finding articles and constructing feeds.
|
5
|
+
#
|
6
|
+
# This helper has a few requirements. First, all blog articles should have
|
7
|
+
# the following attributes:
|
8
|
+
#
|
9
|
+
# * 'kind', set to 'article'.
|
10
|
+
#
|
11
|
+
# * 'created_at', set to the creation timestamp.
|
12
|
+
#
|
13
|
+
# Some functions in this blogging helper, such as the +atom_feed+ function,
|
14
|
+
# require additional attributes to be set; these attributes are described in
|
15
|
+
# the documentation for these functions.
|
16
|
+
#
|
17
|
+
# The two main functions are sorted_articles and atom_feed.
|
18
|
+
#
|
19
|
+
# To activate this helper, +include+ it, like this:
|
20
|
+
#
|
21
|
+
# include Nanoc2::Helpers::Blogging
|
22
|
+
module Blogging
|
23
|
+
|
24
|
+
# Returns an unsorted list of articles.
|
25
|
+
def articles
|
26
|
+
@pages.select { |page| page.kind == 'article' }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a list of articles, sorted by descending creation date (so newer
|
30
|
+
# articles appear first).
|
31
|
+
def sorted_articles
|
32
|
+
articles.sort_by { |a| a.created_at }.reverse
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a string representing the atom feed containing recent articles,
|
36
|
+
# sorted by descending creation date. +params+ is a hash where the
|
37
|
+
# following keys can be set:
|
38
|
+
#
|
39
|
+
# +limit+:: The maximum number of articles to show. Defaults to 5.
|
40
|
+
#
|
41
|
+
# +articles+:: A list of articles to include in the feed. Defaults to the
|
42
|
+
# list of articles returned by the articles function.
|
43
|
+
#
|
44
|
+
# +content_proc+:: A proc that returns the content of the given article,
|
45
|
+
# passed as a parameter. By default, given the argument
|
46
|
+
# +article+, this proc will return +article.content+.
|
47
|
+
# This function may not return nil.
|
48
|
+
#
|
49
|
+
# +excerpt_proc+:: A proc that returns the excerpt of the given article,
|
50
|
+
# passed as a parameter. By default, given the argument
|
51
|
+
# +article+, this proc will return +article.excerpt+.
|
52
|
+
# This function may return nil.
|
53
|
+
#
|
54
|
+
# The following attributes must be set on blog articles:
|
55
|
+
#
|
56
|
+
# * 'title', containing the title of the blog post.
|
57
|
+
#
|
58
|
+
# * all other attributes mentioned above.
|
59
|
+
#
|
60
|
+
# The following attributes can optionally be set on blog articles to
|
61
|
+
# change the behaviour of the Atom feed:
|
62
|
+
#
|
63
|
+
# * 'excerpt', containing an excerpt of the article, usually only a few
|
64
|
+
# lines long.
|
65
|
+
#
|
66
|
+
# * 'custom_path_in_feed', containing the path that will be used instead
|
67
|
+
# of the normal path in the feed. This can be useful when including
|
68
|
+
# non-outputted pages in a feed; such pages could have their custom feed
|
69
|
+
# path set to the blog path instead, for example.
|
70
|
+
#
|
71
|
+
# The feed will also include dates on which the articles were updated.
|
72
|
+
# These are generated automatically; the way this happens depends on the
|
73
|
+
# used data source (the filesystem data source checks the file mtimes, for
|
74
|
+
# instance).
|
75
|
+
#
|
76
|
+
# The feed page will need to have the following attributes:
|
77
|
+
#
|
78
|
+
# * 'base_url', containing the URL to the site, without trailing slash.
|
79
|
+
# For example, if the site is at "http://example.com/", the base_url
|
80
|
+
# would be "http://example.com". It is probably a good idea to define
|
81
|
+
# this in the page defaults, i.e. the 'meta.yaml' file (at least if the
|
82
|
+
# filesystem data source is being used, which is probably the case).
|
83
|
+
#
|
84
|
+
# * 'title', containing the title of the feed, which is usually also the
|
85
|
+
# title of the blog.
|
86
|
+
#
|
87
|
+
# * 'author_name', containing the name of the page's author. This will
|
88
|
+
# likely be a global attribute, unless the site is managed by several
|
89
|
+
# people/
|
90
|
+
#
|
91
|
+
# * 'author_uri', containing the URI for the page's author, such as the
|
92
|
+
# author's web site URL. This will also likely be a global attribute.
|
93
|
+
#
|
94
|
+
# The feed page can have the following optional attributes:
|
95
|
+
#
|
96
|
+
# * 'feed_url', containing the custom URL of the feed. This can be useful
|
97
|
+
# when the private feed URL shouldn't be exposed; for example, when
|
98
|
+
# using FeedBurner this would be set to the public FeedBurner URL.
|
99
|
+
#
|
100
|
+
# To construct a feed, create a blank page with no layout, only the 'erb'
|
101
|
+
# (or 'erubis') filter, and an 'xml' extension. It may also be useful to
|
102
|
+
# set 'is_hidden' to true, so that helpers such as the sitemap helper will
|
103
|
+
# ignore the page. The content of the feed page should be:
|
104
|
+
#
|
105
|
+
# <%= atom_feed %>
|
106
|
+
def atom_feed(params={})
|
107
|
+
require 'builder'
|
108
|
+
|
109
|
+
# Extract parameters
|
110
|
+
limit = params[:limit] || 5
|
111
|
+
relevant_articles = params[:articles] || articles || []
|
112
|
+
content_proc = params[:content_proc] || lambda { |a| a.content }
|
113
|
+
excerpt_proc = params[:excerpt_proc] || lambda { |a| a.excerpt }
|
114
|
+
|
115
|
+
# Check feed page attributes
|
116
|
+
if @page.base_url.nil?
|
117
|
+
raise RuntimeError.new('Cannot build Atom feed: feed page has no base_url')
|
118
|
+
end
|
119
|
+
if @page.title.nil?
|
120
|
+
raise RuntimeError.new('Cannot build Atom feed: feed page has no title')
|
121
|
+
end
|
122
|
+
if @page.author_name.nil?
|
123
|
+
raise RuntimeError.new('Cannot build Atom feed: feed page has no author_name')
|
124
|
+
end
|
125
|
+
if @page.author_uri.nil?
|
126
|
+
raise RuntimeError.new('Cannot build Atom feed: feed page has no author_uri')
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check article attributes
|
130
|
+
if relevant_articles.empty?
|
131
|
+
raise RuntimeError.new('Cannot build Atom feed: no articles')
|
132
|
+
end
|
133
|
+
if relevant_articles.any? { |a| a.created_at.nil? }
|
134
|
+
raise RuntimeError.new('Cannot build Atom feed: one or more articles lack created_at')
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get sorted relevant articles
|
138
|
+
sorted_relevant_articles = relevant_articles.sort_by { |a| a.created_at }.reverse.first(limit)
|
139
|
+
|
140
|
+
# Get most recent article
|
141
|
+
last_article = sorted_relevant_articles.first
|
142
|
+
|
143
|
+
# Create builder
|
144
|
+
buffer = ''
|
145
|
+
xml = Builder::XmlMarkup.new(:target => buffer, :indent => 2)
|
146
|
+
|
147
|
+
# Build feed
|
148
|
+
xml.instruct!
|
149
|
+
xml.feed(:xmlns => 'http://www.w3.org/2005/Atom') do
|
150
|
+
# Add primary attributes
|
151
|
+
xml.id @page.base_url + '/'
|
152
|
+
xml.title @page.title
|
153
|
+
|
154
|
+
# Add date
|
155
|
+
xml.updated last_article.created_at.to_iso8601_time
|
156
|
+
|
157
|
+
# Add links
|
158
|
+
xml.link(:rel => 'alternate', :href => @page.base_url)
|
159
|
+
xml.link(:rel => 'self', :href => feed_url)
|
160
|
+
|
161
|
+
# Add author information
|
162
|
+
xml.author do
|
163
|
+
xml.name @page.author_name
|
164
|
+
xml.uri @page.author_uri
|
165
|
+
end
|
166
|
+
|
167
|
+
# Add articles
|
168
|
+
sorted_relevant_articles.each do |a|
|
169
|
+
xml.entry do
|
170
|
+
# Add primary attributes
|
171
|
+
xml.id atom_tag_for(a)
|
172
|
+
xml.title a.title, :type => 'html'
|
173
|
+
|
174
|
+
# Add dates
|
175
|
+
xml.published a.created_at.to_iso8601_time
|
176
|
+
xml.updated a.mtime.to_iso8601_time
|
177
|
+
|
178
|
+
# Add link
|
179
|
+
xml.link(:rel => 'alternate', :href => url_for(a))
|
180
|
+
|
181
|
+
# Add content
|
182
|
+
summary = excerpt_proc.call(a)
|
183
|
+
xml.content content_proc.call(a), :type => 'html'
|
184
|
+
xml.summary summary, :type => 'html' unless summary.nil?
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
buffer
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns the URL for the given page. It will return the URL containing
|
193
|
+
# the custom path in the feed if possible, otherwise the normal path.
|
194
|
+
def url_for(page)
|
195
|
+
@page.base_url + (page.custom_path_in_feed || page.path)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Returns the URL of the feed. It will return the custom feed URL if set,
|
199
|
+
# or otherwise the normal feed URL.
|
200
|
+
def feed_url
|
201
|
+
@page[:feed_url] || @page.base_url + @page.path
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns an URI containing an unique ID for the given page. This will be
|
205
|
+
# used in the Atom feed to uniquely identify articles. These IDs are
|
206
|
+
# created using a procedure suggested by Mark Pilgrim in this blog post:
|
207
|
+
# http://diveintomark.org/archives/2004/05/28/howto-atom-id.
|
208
|
+
def atom_tag_for(page)
|
209
|
+
hostname = @page.base_url.sub(/.*:\/\/(.+?)\/?$/, '\1')
|
210
|
+
formatted_date = page.created_at.to_iso8601_date
|
211
|
+
|
212
|
+
'tag:' + hostname + ',' + formatted_date + ':' + page.path
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|