nanoc 2.0 → 2.1

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.
Files changed (99) hide show
  1. data/ChangeLog +54 -0
  2. data/LICENSE +1 -1
  3. data/README +63 -3
  4. data/Rakefile +61 -14
  5. data/bin/nanoc +7 -199
  6. data/lib/nanoc/base/asset.rb +113 -0
  7. data/lib/nanoc/base/asset_defaults.rb +21 -0
  8. data/lib/nanoc/base/asset_rep.rb +277 -0
  9. data/lib/nanoc/base/binary_filter.rb +44 -0
  10. data/lib/nanoc/base/code.rb +41 -0
  11. data/lib/nanoc/base/compiler.rb +46 -34
  12. data/lib/nanoc/base/core_ext/hash.rb +51 -7
  13. data/lib/nanoc/base/core_ext/string.rb +8 -0
  14. data/lib/nanoc/base/data_source.rb +253 -20
  15. data/lib/nanoc/base/defaults.rb +30 -0
  16. data/lib/nanoc/base/enhancements.rb +9 -84
  17. data/lib/nanoc/base/filter.rb +109 -6
  18. data/lib/nanoc/base/layout.rb +91 -0
  19. data/lib/nanoc/base/notification_center.rb +66 -0
  20. data/lib/nanoc/base/page.rb +94 -121
  21. data/lib/nanoc/base/page_defaults.rb +20 -0
  22. data/lib/nanoc/base/page_rep.rb +318 -0
  23. data/lib/nanoc/base/plugin.rb +57 -9
  24. data/lib/nanoc/base/proxies/asset_proxy.rb +29 -0
  25. data/lib/nanoc/base/proxies/asset_rep_proxy.rb +26 -0
  26. data/lib/nanoc/base/proxies/layout_proxy.rb +25 -0
  27. data/lib/nanoc/base/proxies/page_proxy.rb +35 -0
  28. data/lib/nanoc/base/proxies/page_rep_proxy.rb +28 -0
  29. data/lib/nanoc/base/proxy.rb +37 -0
  30. data/lib/nanoc/base/router.rb +72 -0
  31. data/lib/nanoc/base/site.rb +220 -91
  32. data/lib/nanoc/base/template.rb +64 -0
  33. data/lib/nanoc/binary_filters/image_science_thumbnail.rb +28 -0
  34. data/lib/nanoc/cli/base.rb +219 -0
  35. data/lib/nanoc/cli/cli.rb +16 -0
  36. data/lib/nanoc/cli/command.rb +105 -0
  37. data/lib/nanoc/cli/commands/autocompile.rb +80 -0
  38. data/lib/nanoc/cli/commands/compile.rb +273 -0
  39. data/lib/nanoc/cli/commands/create_layout.rb +85 -0
  40. data/lib/nanoc/cli/commands/create_page.rb +85 -0
  41. data/lib/nanoc/cli/commands/create_site.rb +327 -0
  42. data/lib/nanoc/cli/commands/create_template.rb +76 -0
  43. data/lib/nanoc/cli/commands/help.rb +69 -0
  44. data/lib/nanoc/cli/commands/info.rb +114 -0
  45. data/lib/nanoc/cli/commands/switch.rb +141 -0
  46. data/lib/nanoc/cli/commands/update.rb +91 -0
  47. data/lib/nanoc/cli/ext.rb +37 -0
  48. data/lib/nanoc/cli/logger.rb +66 -0
  49. data/lib/nanoc/cli/option_parser.rb +168 -0
  50. data/lib/nanoc/cli.rb +1 -0
  51. data/lib/nanoc/data_sources/filesystem.rb +650 -215
  52. data/lib/nanoc/data_sources/filesystem_combined.rb +495 -0
  53. data/lib/nanoc/extra/auto_compiler.rb +265 -0
  54. data/lib/nanoc/extra/context.rb +22 -0
  55. data/lib/nanoc/extra/core_ext/hash.rb +54 -0
  56. data/lib/nanoc/extra/core_ext/time.rb +13 -0
  57. data/lib/nanoc/extra/file_proxy.rb +29 -0
  58. data/lib/nanoc/extra/vcs.rb +48 -0
  59. data/lib/nanoc/extra/vcses/bazaar.rb +21 -0
  60. data/lib/nanoc/extra/vcses/dummy.rb +20 -0
  61. data/lib/nanoc/extra/vcses/git.rb +21 -0
  62. data/lib/nanoc/extra/vcses/mercurial.rb +21 -0
  63. data/lib/nanoc/extra/vcses/subversion.rb +21 -0
  64. data/lib/nanoc/filters/bluecloth.rb +13 -0
  65. data/lib/nanoc/filters/erb.rb +6 -22
  66. data/lib/nanoc/filters/erubis.rb +14 -0
  67. data/lib/nanoc/filters/haml.rb +11 -6
  68. data/lib/nanoc/filters/markaby.rb +5 -5
  69. data/lib/nanoc/filters/maruku.rb +14 -0
  70. data/lib/nanoc/filters/old.rb +19 -0
  71. data/lib/nanoc/filters/rdiscount.rb +13 -0
  72. data/lib/nanoc/filters/rdoc.rb +5 -4
  73. data/lib/nanoc/filters/redcloth.rb +14 -0
  74. data/lib/nanoc/filters/rubypants.rb +14 -0
  75. data/lib/nanoc/filters/sass.rb +13 -0
  76. data/lib/nanoc/helpers/blogging.rb +170 -0
  77. data/lib/nanoc/helpers/capturing.rb +59 -0
  78. data/lib/nanoc/helpers/html_escape.rb +23 -0
  79. data/lib/nanoc/helpers/link_to.rb +69 -0
  80. data/lib/nanoc/helpers/render.rb +47 -0
  81. data/lib/nanoc/helpers/tagging.rb +52 -0
  82. data/lib/nanoc/helpers/xml_sitemap.rb +58 -0
  83. data/lib/nanoc/routers/default.rb +54 -0
  84. data/lib/nanoc/routers/no_dirs.rb +66 -0
  85. data/lib/nanoc/routers/versioned.rb +79 -0
  86. data/lib/nanoc.rb +83 -12
  87. metadata +144 -47
  88. data/lib/nanoc/base/auto_compiler.rb +0 -124
  89. data/lib/nanoc/base/layout_processor.rb +0 -33
  90. data/lib/nanoc/base/page_proxy.rb +0 -31
  91. data/lib/nanoc/base/plugin_manager.rb +0 -33
  92. data/lib/nanoc/data_sources/database.rb +0 -259
  93. data/lib/nanoc/data_sources/trivial.rb +0 -145
  94. data/lib/nanoc/filters/markdown.rb +0 -13
  95. data/lib/nanoc/filters/smartypants.rb +0 -13
  96. data/lib/nanoc/filters/textile.rb +0 -13
  97. data/lib/nanoc/layout_processors/erb.rb +0 -35
  98. data/lib/nanoc/layout_processors/haml.rb +0 -18
  99. data/lib/nanoc/layout_processors/markaby.rb +0 -16
@@ -0,0 +1,19 @@
1
+ module Nanoc::Filters
2
+ class Old < Nanoc::Filter
3
+
4
+ identifiers :eruby, :markdown, :smartypants, :textile
5
+
6
+ def run(content)
7
+ raise Nanoc::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,13 @@
1
+ module Nanoc::Filters
2
+ class RDiscount < Nanoc::Filter
3
+
4
+ identifiers :rdiscount
5
+
6
+ def run(content)
7
+ require 'rdiscount'
8
+
9
+ ::RDiscount.new(content).to_html
10
+ end
11
+
12
+ end
13
+ end
@@ -1,12 +1,13 @@
1
- module Nanoc::Filter::RDoc
2
- class RDocFilter < Nanoc::Filter
1
+ module Nanoc::Filters
2
+ class RDoc < Nanoc::Filter
3
3
 
4
4
  identifiers :rdoc
5
5
 
6
6
  def run(content)
7
- nanoc_require 'rdoc/markup/simple_markup'
8
- nanoc_require 'rdoc/markup/simple_markup/to_html'
7
+ require 'rdoc/markup/simple_markup'
8
+ require 'rdoc/markup/simple_markup/to_html'
9
9
 
10
+ # Get result
10
11
  ::SM::SimpleMarkup.new.convert(content, SM::ToHtml.new)
11
12
  end
12
13
 
@@ -0,0 +1,14 @@
1
+ module Nanoc::Filters
2
+ class RedCloth < Nanoc::Filter
3
+
4
+ identifiers :redcloth
5
+
6
+ def run(content)
7
+ require 'redcloth'
8
+
9
+ # Get result
10
+ ::RedCloth.new(content).to_html
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Nanoc::Filters
2
+ class SmartyPants < Nanoc::Filter
3
+
4
+ identifiers :rubypants
5
+
6
+ def run(content)
7
+ require 'rubypants'
8
+
9
+ # Get result
10
+ ::RubyPants.new(content).to_html
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Nanoc::Filters
2
+ class Sass < Nanoc::Filter
3
+
4
+ identifiers :sass
5
+
6
+ def run(content)
7
+ require 'sass'
8
+
9
+ ::Sass::Engine.new(content).render
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,170 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::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
+ module Blogging
19
+
20
+ # Returns the list of articles, sorted by descending creation date (so
21
+ # newer articles appear first).
22
+ def sorted_articles
23
+ @pages.select do |page|
24
+ page.kind == 'article'
25
+ end.sort do |x,y|
26
+ y.created_at <=> x.created_at
27
+ end
28
+ end
29
+
30
+ # Returns a string representing the atom feed containing recent articles,
31
+ # sorted by descending creation date. +params+ is a hash where the
32
+ # following keys can be set:
33
+ #
34
+ # +limit+:: The maximum number of articles to show. Defaults to 5.
35
+ #
36
+ # The following attributes must be set on blog articles:
37
+ #
38
+ # * 'title', containing the title of the blog post.
39
+ #
40
+ # * all other attributes mentioned above.
41
+ #
42
+ # The following attributes can optionally be set on blog articles to
43
+ # change the behaviour of the Atom feed:
44
+ #
45
+ # * 'excerpt', containing an excerpt of the article, usually only a few
46
+ # lines long.
47
+ #
48
+ # * 'custom_path_in_feed', containing the path that will be used instead
49
+ # of the normal path in the feed. This can be useful when including
50
+ # non-outputted pages in a feed; such pages could have their custom feed
51
+ # path set to the blog path instead, for example.
52
+ #
53
+ # The feed will also include dates on which the articles were updated.
54
+ # These are generated automatically; the way this happens depends on the
55
+ # used data source (the filesystem data source checks the file mtimes, for
56
+ # instance).
57
+ #
58
+ # The feed page will need to have the following attributes:
59
+ #
60
+ # * 'base_url', containing the URL to the site, without trailing slash.
61
+ # For example, if the site is at "http://example.com/", the base_url
62
+ # would be "http://example.com". It is probably a good idea to define
63
+ # this in the page defaults, i.e. the 'meta.yaml' file (at least if the
64
+ # filesystem data source is being used, which is probably the case).
65
+ #
66
+ # * 'title', containing the title of the feed, which is usually also the
67
+ # title of the blog.
68
+ #
69
+ # * 'author_name', containing the name of the page's author. This will
70
+ # likely be a global attribute, unless the site is managed by several
71
+ # people/
72
+ #
73
+ # * 'author_uri', containing the URI for the page's author, such as the
74
+ # author's web site URL. This will also likely be a global attribute.
75
+ #
76
+ # The feed page can have the following optional attributes:
77
+ #
78
+ # * 'feed_url', containing the custom URL of the feed. This can be useful
79
+ # when the private feed URL shouldn't be exposed; for example, when
80
+ # using FeedBurner this would be set to the public FeedBurner URL.
81
+ #
82
+ # To construct a feed, create a blank page with no layout, only the 'erb'
83
+ # (or 'erubis') filter, and an 'xml' extension. It may also be useful to
84
+ # set 'is_hidden' to true, so that helpers such as the sitemap helper will
85
+ # ignore the page. The content of the feed page should be:
86
+ #
87
+ # <%= atom_feed %>
88
+ def atom_feed(params={})
89
+ require 'builder'
90
+
91
+ # Extract parameters
92
+ limit = params[:limit] || 5
93
+
94
+ # Get most recent article
95
+ last_article = sorted_articles.first
96
+
97
+ # Create builder
98
+ buffer = ''
99
+ xml = Builder::XmlMarkup.new(:target => buffer, :indent => 2)
100
+
101
+ # Build feed
102
+ xml.instruct!
103
+ xml.feed(:xmlns => 'http://www.w3.org/2005/Atom') do
104
+ # Add primary attributes
105
+ xml.id @page.base_url + '/'
106
+ xml.title @page.title
107
+
108
+ # Add date
109
+ xml.updated last_article.created_at.to_iso8601_time
110
+
111
+ # Add links
112
+ xml.link(:rel => 'alternate', :href => @page.base_url)
113
+ xml.link(:rel => 'self', :href => feed_url)
114
+
115
+ # Add author information
116
+ xml.author do
117
+ xml.name @page.author_name
118
+ xml.uri @page.author_uri
119
+ end
120
+
121
+ # Add articles
122
+ sorted_articles.first(limit).each do |a|
123
+ xml.entry do
124
+ # Add primary attributes
125
+ xml.id atom_tag_for(a)
126
+ xml.title a.title, :type => 'html'
127
+
128
+ # Add dates
129
+ xml.published a.created_at.to_iso8601_time
130
+ xml.updated a.mtime.to_iso8601_time
131
+
132
+ # Add link
133
+ xml.link(:rel => 'alternate', :href => url_for(a))
134
+
135
+ # Add content
136
+ xml.content a.content, :type => 'html'
137
+ xml.summary a.excerpt, :type => 'html' unless a.excerpt.nil?
138
+ end
139
+ end
140
+ end
141
+
142
+ buffer
143
+ end
144
+
145
+ # Returns the URL for the given page. It will return the URL containing
146
+ # the custom path in the feed if possible, otherwise the normal path.
147
+ def url_for(page)
148
+ @page.base_url + (page.custom_path_in_feed || page.path)
149
+ end
150
+
151
+ # Returns the URL of the feed. It will return the custom feed URL if set,
152
+ # or otherwise the normal feed URL.
153
+ def feed_url
154
+ @page[:feed_url] || @page.base_url + @page.path
155
+ end
156
+
157
+ # Returns an URI containing an unique ID for the given page. This will be
158
+ # used in the Atom feed to uniquely identify articles. These IDs are
159
+ # created using a procedure suggested by Mark Pilgrim in this blog post:
160
+ # http://diveintomark.org/archives/2004/05/28/howto-atom-id.
161
+ def atom_tag_for(page)
162
+ hostname = @page.base_url.sub(/.*:\/\/(.+?)\/?$/, '\1')
163
+ formatted_date = page.created_at.to_iso8601_date
164
+
165
+ 'tag:' + hostname + ',' + formatted_date + ':' + page.path
166
+ end
167
+
168
+ end
169
+
170
+ end
@@ -0,0 +1,59 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::Capturing provides a content_for method, which allows
4
+ # content to be "captured" on one page and reused elsewhere.
5
+ #
6
+ # = Example
7
+ #
8
+ # For example, suppose you want the sidebar of your site to contain a short
9
+ # summary of the page. You could put the summary in the meta file, but
10
+ # that’s not possible when the summary contains eRuby. You could also put
11
+ # the sidebar inside the actual page, but that’s not very pretty. Instead,
12
+ # you write the summary on the page itself, but capture it, and print it in
13
+ # the sidebar layout.
14
+ #
15
+ # Captured content becomes part of the page. For example, a sidebar layout
16
+ # could look like this:
17
+ #
18
+ # <div id="sidebar">
19
+ # <h3>Summary</h3>
20
+ # <%= @page.content_for_summary || '(no summary)' %>
21
+ # </div>
22
+ #
23
+ # To put something inside that content_for_summary variable, capture it
24
+ # using the content_for function. In the about page, for example:
25
+ #
26
+ # <% content_for :summary do %>
27
+ # <p>On this page, nanoc is introduced, blah blah.</p>
28
+ # <% end %>
29
+ #
30
+ # When the site is compiled, the sidebar of the about page will say “On
31
+ # this page, the purpose of nanoc is described, blah blah blah,” as
32
+ # expected.
33
+ module Capturing
34
+
35
+ # Captures the content inside the block into a page attribute named
36
+ # "content_for_" followed by the given name. The content of the block
37
+ # itself will not be outputted.
38
+ def content_for(name, &block)
39
+ eval("@page[:content_for_#{name.to_s}] = capture(&block)")
40
+ end
41
+
42
+ private
43
+
44
+ def capture(*args, &block)
45
+ buffer = eval('_erbout', block.binding)
46
+
47
+ pos = buffer.length
48
+ block.call(*args)
49
+
50
+ data = buffer[pos..-1]
51
+
52
+ buffer[pos..-1] = ''
53
+
54
+ data
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,23 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::HTMLEscape contains functionality for HTML-escaping
4
+ # strings.
5
+ module HTMLEscape
6
+
7
+ # Returns the HTML-escaped representation of the given string. Only &, <,
8
+ # > and " are escaped.
9
+ def html_escape(string)
10
+ string.gsub('&', '&amp;').
11
+ gsub('<', '&lt;').
12
+ gsub('>', '&gt;').
13
+ gsub('"', '&quot;')
14
+ end
15
+
16
+ alias h html_escape
17
+
18
+ end
19
+
20
+ end
21
+
22
+ # Include by default
23
+ include Nanoc::Helpers::HTMLEscape
@@ -0,0 +1,69 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::LinkTo contains functions for linking to pages.
4
+ module LinkTo
5
+
6
+ include Nanoc::Helpers::HTMLEscape
7
+
8
+ # Creates a HTML link to the given path or page/asset representation, and
9
+ # with the given text.
10
+ #
11
+ # +path_or_rep+:: the URL or path (a String) that should be linked to, or
12
+ # the page or asset representation that should be linked
13
+ # to.
14
+ #
15
+ # +text+:: the visible link text.
16
+ #
17
+ # +attributes+:: a hash containing HTML attributes that will be added to
18
+ # the link.
19
+ #
20
+ # Examples:
21
+ #
22
+ # link_to('Blog', '/blog/')
23
+ # # => '<a href="/blog/">Blog</a>'
24
+ #
25
+ # page_rep = @pages.find { |p| p.page_id == 'special' }.reps(:default)
26
+ # link_to('Special Page', page_rep)
27
+ # # => '<a href="/special_page/">Special Page</a>'
28
+ #
29
+ # link_to('Blog', '/blog/', :title => 'My super cool blog')
30
+ # # => '<a href="/blog/" title="My super cool blog">Blog</a>
31
+ def link_to(text, path_or_rep, attributes={})
32
+ # Find path
33
+ path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
34
+
35
+ # Join attributes
36
+ attributes = attributes.inject('') do |memo, (key, value)|
37
+ memo + key.to_s + '="' + h(value) + '" '
38
+ end
39
+
40
+ # Create link
41
+ "<a #{attributes}href=\"#{path}\">#{text}</a>"
42
+ end
43
+
44
+ # Creates a HTML link using link_to, except when the linked page is the
45
+ # current one. In this case, a span element with class "active" and with
46
+ # the given text will be returned.
47
+ #
48
+ # Examples:
49
+ #
50
+ # link_to('Blog', '/blog/')
51
+ # # => '<a href="/blog/">Blog</a>'
52
+ #
53
+ # link_to('This Page', @page_rep)
54
+ # # => '<span class="active">This Page</span>'
55
+ def link_to_unless_current(text, path_or_rep, attributes={})
56
+ # Find path
57
+ path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
58
+
59
+ if @page_rep and @page_rep.path == path
60
+ # Create message
61
+ "<span class=\"active\" title=\"You're here.\">#{text}</span>"
62
+ else
63
+ link_to(text, path_or_rep, attributes)
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,47 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::Render provides functionality for rendering layouts as
4
+ # partials.
5
+ module Render
6
+
7
+ # Returns a string containing the rendered given layout.
8
+ #
9
+ # +name_or_path+:: the name or the path of the layout that should be
10
+ # rendered.
11
+ #
12
+ # +other_assigns+:: a hash containing assigns that will be made available
13
+ # as instance variables.
14
+ #
15
+ # Example 1: a layout 'head' with content "HEAD" and a layout 'foot' with
16
+ # content "FOOT":
17
+ #
18
+ # <%= render 'head' %> - MIDDLE - <%= render 'foot' %>
19
+ # # => "HEAD - MIDDLE - FOOT"
20
+ #
21
+ # Example 2: a layout named 'head' with content "<h1><%= @title %></h1>":
22
+ #
23
+ # <%= render 'head', :title => 'Foo' %>
24
+ # # => "<h1>Foo</h1>"
25
+ def render(name_or_path, other_assigns={})
26
+ # Find layout
27
+ layout = @_obj.site.layouts.find { |l| l.path == name_or_path.cleaned_path }
28
+ raise Nanoc::Errors::UnknownLayoutError.new(name_or_path.cleaned_path) if layout.nil?
29
+
30
+ # Find filter
31
+ klass = layout.filter_class
32
+ raise Nanoc::Errors::CannotDetermineFilterError.new(layout.path) if klass.nil?
33
+ filter = klass.new(@_obj_rep, other_assigns)
34
+
35
+ # Layout
36
+ @_obj.site.compiler.stack.push(layout)
37
+ result = filter.run(layout.content)
38
+ @_obj.site.compiler.stack.pop
39
+ result
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ # Include by default
47
+ include Nanoc::Helpers::Render
@@ -0,0 +1,52 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::Tagging provides some support for managing tags added to
4
+ # pages. To add tags to pages, set the +tags+ page attribute to an array of
5
+ # tags that should be applied to the page. For example:
6
+ #
7
+ # tags: [ 'foo', 'bar', 'baz' ]
8
+ module Tagging
9
+
10
+ # Returns a formatted list of tags for the given page as a string. Several
11
+ # parameters allow customization:
12
+ #
13
+ # :base_url:: The URL to which the tag will be appended to construct the
14
+ # link URL. This URL must have a trailing slash. Defaults to
15
+ # "http://technorati.com/tag/".
16
+ #
17
+ # :none_text:: The text to display when the page has no tags. Defaults to
18
+ # "(none)".
19
+ #
20
+ # :separator:: The separator to put between tags. Defaults to ", ".
21
+ def tags_for(page, params={})
22
+ base_url = params[:base_url] || 'http://technorati.com/tag/'
23
+ none_text = params[:none_text] || '(none)'
24
+ separator = params[:separator] || ', '
25
+
26
+ if page.tags.nil? or page.tags.empty?
27
+ none_text
28
+ else
29
+ page.tags.collect { |tag| link_for_tag(tag, base_url) }.join(separator)
30
+ end
31
+ end
32
+
33
+ # Returns all pages with the given tag.
34
+ def pages_with_tag(tag)
35
+ @pages.select { |p| (p.tags || []).include?(tag) }
36
+ end
37
+
38
+ # Returns a link to to the specified tag. The link is marked up using the
39
+ # rel-tag microformat.
40
+ #
41
+ # +tag+:: The name of the tag, which should consist of letters and numbers
42
+ # (no spaces, slashes, or other special characters).
43
+ #
44
+ # +base_url+:: The URL to which the tag will be appended to construct the
45
+ # link URL. This URL must have a trailing slash.
46
+ def link_for_tag(tag, base_url)
47
+ %[<a href="#{base_url}#{tag}" rel="tag">#{tag}</a>]
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,58 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::XMLSitemap contains functionality for building XML
4
+ # sitemaps that will be crawled by search engines. See the Sitemaps protocol
5
+ # web site, http://www.sitemaps.org, for details.
6
+ module XMLSitemap
7
+
8
+ # Returns the XML sitemap as a string.
9
+ #
10
+ # The following attributes can optionally be set on pages to change the
11
+ # behaviour of the sitemap:
12
+ #
13
+ # * 'changefreq', containing the estimated change frequency as defined by
14
+ # the Sitemaps protocol.
15
+ #
16
+ # * 'priority', containing the page's priority, ranging from 0.0 to 1.0,
17
+ # as defined by the Sitemaps protocol.
18
+ #
19
+ # The sitemap will also include dates on which the pages were updated.
20
+ # These are generated automatically; the way this happens depends on the
21
+ # used data source (the filesystem data source checks the file mtimes, for
22
+ # instance).
23
+ #
24
+ # The sitemap page will need to have the following attributes:
25
+ #
26
+ # * 'base_url', containing the URL to the site, without trailing slash.
27
+ # For example, if the site is at "http://example.com/", the base_url
28
+ # would be "http://example.com". It is probably a good idea to define
29
+ # this in the page defaults, i.e. the 'meta.yaml' file (at least if the
30
+ # filesystem data source is being used, which is probably the case).
31
+ def xml_sitemap
32
+ require 'builder'
33
+
34
+ # Create builder
35
+ buffer = ''
36
+ xml = Builder::XmlMarkup.new(:target => buffer, :indent => 2)
37
+
38
+ # Build sitemap
39
+ xml.instruct!
40
+ xml.urlset(:xmlns => 'http://www.google.com/schemas/sitemap/0.84') do
41
+ # Add page
42
+ @pages.reject { |p| p.is_hidden }.each do |page|
43
+ xml.url do
44
+ xml.loc @page.base_url + page.path
45
+ xml.lastmod page.mtime.to_iso8601_date unless page.mtime.nil?
46
+ xml.changefreq page.changefreq unless page.changefreq.nil?
47
+ xml.priority page.priority unless page.priority.nil?
48
+ end
49
+ end
50
+ end
51
+
52
+ # Return sitemap
53
+ buffer
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,54 @@
1
+ module Nanoc::Routers
2
+
3
+ # The default router organises pages in the most obvious, but sometimes
4
+ # slightly restrictive, way: the hierarchy of compiled pages and assets is
5
+ # the same as the hierarchy of uncompiled pages and assets.
6
+ class Default < Nanoc::Router
7
+
8
+ identifier :default
9
+
10
+ def path_for_page_rep(page_rep)
11
+ # Get data we need
12
+ filename = page_rep.attribute_named(:filename)
13
+ extension = page_rep.attribute_named(:extension)
14
+
15
+ # Initialize path
16
+ path = page_rep.page.path + filename
17
+
18
+ # Add rep name if necessary
19
+ unless page_rep.name == :default
20
+ path += '-' + page_rep.name.to_s
21
+ end
22
+
23
+ # Add extension
24
+ path += '.' + extension
25
+
26
+ # Done
27
+ path
28
+ end
29
+
30
+ def path_for_asset_rep(asset_rep)
31
+ # Get data we need
32
+ extension = asset_rep.attribute_named(:extension)
33
+ modified_path = asset_rep.asset.path[0..-2]
34
+ version = asset_rep.attribute_named(:version)
35
+
36
+ # Initialize path
37
+ assets_prefix = @site.config[:assets_prefix] || '/assets'
38
+ path = assets_prefix + modified_path
39
+
40
+ # Add rep name if necessary
41
+ unless asset_rep.name == :default
42
+ path += '-' + asset_rep.name.to_s
43
+ end
44
+
45
+ # Add extension
46
+ path += '.' + extension
47
+
48
+ # Done
49
+ path
50
+ end
51
+
52
+ end
53
+
54
+ end