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.
Files changed (100) hide show
  1. data/ChangeLog +3 -0
  2. data/LICENSE +19 -0
  3. data/README +75 -0
  4. data/Rakefile +76 -0
  5. data/bin/nanoc2 +26 -0
  6. data/lib/nanoc2.rb +73 -0
  7. data/lib/nanoc2/base.rb +26 -0
  8. data/lib/nanoc2/base/asset.rb +117 -0
  9. data/lib/nanoc2/base/asset_defaults.rb +21 -0
  10. data/lib/nanoc2/base/asset_rep.rb +282 -0
  11. data/lib/nanoc2/base/binary_filter.rb +44 -0
  12. data/lib/nanoc2/base/code.rb +41 -0
  13. data/lib/nanoc2/base/compiler.rb +67 -0
  14. data/lib/nanoc2/base/core_ext.rb +2 -0
  15. data/lib/nanoc2/base/core_ext/hash.rb +78 -0
  16. data/lib/nanoc2/base/core_ext/string.rb +8 -0
  17. data/lib/nanoc2/base/data_source.rb +286 -0
  18. data/lib/nanoc2/base/defaults.rb +30 -0
  19. data/lib/nanoc2/base/filter.rb +93 -0
  20. data/lib/nanoc2/base/layout.rb +91 -0
  21. data/lib/nanoc2/base/notification_center.rb +66 -0
  22. data/lib/nanoc2/base/page.rb +132 -0
  23. data/lib/nanoc2/base/page_defaults.rb +20 -0
  24. data/lib/nanoc2/base/page_rep.rb +324 -0
  25. data/lib/nanoc2/base/plugin.rb +71 -0
  26. data/lib/nanoc2/base/proxies.rb +5 -0
  27. data/lib/nanoc2/base/proxies/asset_proxy.rb +29 -0
  28. data/lib/nanoc2/base/proxies/asset_rep_proxy.rb +26 -0
  29. data/lib/nanoc2/base/proxies/layout_proxy.rb +25 -0
  30. data/lib/nanoc2/base/proxies/page_proxy.rb +35 -0
  31. data/lib/nanoc2/base/proxies/page_rep_proxy.rb +28 -0
  32. data/lib/nanoc2/base/proxy.rb +37 -0
  33. data/lib/nanoc2/base/router.rb +72 -0
  34. data/lib/nanoc2/base/site.rb +274 -0
  35. data/lib/nanoc2/base/template.rb +64 -0
  36. data/lib/nanoc2/binary_filters.rb +1 -0
  37. data/lib/nanoc2/binary_filters/image_science_thumbnail.rb +28 -0
  38. data/lib/nanoc2/cli.rb +9 -0
  39. data/lib/nanoc2/cli/base.rb +132 -0
  40. data/lib/nanoc2/cli/commands.rb +10 -0
  41. data/lib/nanoc2/cli/commands/autocompile.rb +80 -0
  42. data/lib/nanoc2/cli/commands/compile.rb +312 -0
  43. data/lib/nanoc2/cli/commands/create_layout.rb +85 -0
  44. data/lib/nanoc2/cli/commands/create_page.rb +85 -0
  45. data/lib/nanoc2/cli/commands/create_site.rb +323 -0
  46. data/lib/nanoc2/cli/commands/create_template.rb +76 -0
  47. data/lib/nanoc2/cli/commands/help.rb +69 -0
  48. data/lib/nanoc2/cli/commands/info.rb +125 -0
  49. data/lib/nanoc2/cli/commands/switch.rb +141 -0
  50. data/lib/nanoc2/cli/commands/update.rb +91 -0
  51. data/lib/nanoc2/cli/logger.rb +72 -0
  52. data/lib/nanoc2/data_sources.rb +2 -0
  53. data/lib/nanoc2/data_sources/filesystem.rb +707 -0
  54. data/lib/nanoc2/data_sources/filesystem_combined.rb +495 -0
  55. data/lib/nanoc2/extra.rb +6 -0
  56. data/lib/nanoc2/extra/auto_compiler.rb +285 -0
  57. data/lib/nanoc2/extra/context.rb +22 -0
  58. data/lib/nanoc2/extra/core_ext.rb +2 -0
  59. data/lib/nanoc2/extra/core_ext/hash.rb +54 -0
  60. data/lib/nanoc2/extra/core_ext/time.rb +13 -0
  61. data/lib/nanoc2/extra/file_proxy.rb +29 -0
  62. data/lib/nanoc2/extra/vcs.rb +48 -0
  63. data/lib/nanoc2/extra/vcses.rb +5 -0
  64. data/lib/nanoc2/extra/vcses/bazaar.rb +21 -0
  65. data/lib/nanoc2/extra/vcses/dummy.rb +20 -0
  66. data/lib/nanoc2/extra/vcses/git.rb +21 -0
  67. data/lib/nanoc2/extra/vcses/mercurial.rb +21 -0
  68. data/lib/nanoc2/extra/vcses/subversion.rb +21 -0
  69. data/lib/nanoc2/filters.rb +16 -0
  70. data/lib/nanoc2/filters/bluecloth.rb +13 -0
  71. data/lib/nanoc2/filters/erb.rb +19 -0
  72. data/lib/nanoc2/filters/erubis.rb +14 -0
  73. data/lib/nanoc2/filters/haml.rb +21 -0
  74. data/lib/nanoc2/filters/markaby.rb +14 -0
  75. data/lib/nanoc2/filters/maruku.rb +14 -0
  76. data/lib/nanoc2/filters/old.rb +19 -0
  77. data/lib/nanoc2/filters/rainpress.rb +13 -0
  78. data/lib/nanoc2/filters/rdiscount.rb +13 -0
  79. data/lib/nanoc2/filters/rdoc.rb +23 -0
  80. data/lib/nanoc2/filters/redcloth.rb +14 -0
  81. data/lib/nanoc2/filters/relativize_paths.rb +16 -0
  82. data/lib/nanoc2/filters/relativize_paths_in_css.rb +16 -0
  83. data/lib/nanoc2/filters/relativize_paths_in_html.rb +16 -0
  84. data/lib/nanoc2/filters/rubypants.rb +14 -0
  85. data/lib/nanoc2/filters/sass.rb +18 -0
  86. data/lib/nanoc2/helpers.rb +9 -0
  87. data/lib/nanoc2/helpers/blogging.rb +217 -0
  88. data/lib/nanoc2/helpers/capturing.rb +63 -0
  89. data/lib/nanoc2/helpers/filtering.rb +54 -0
  90. data/lib/nanoc2/helpers/html_escape.rb +25 -0
  91. data/lib/nanoc2/helpers/link_to.rb +113 -0
  92. data/lib/nanoc2/helpers/render.rb +49 -0
  93. data/lib/nanoc2/helpers/tagging.rb +56 -0
  94. data/lib/nanoc2/helpers/text.rb +38 -0
  95. data/lib/nanoc2/helpers/xml_sitemap.rb +63 -0
  96. data/lib/nanoc2/routers.rb +3 -0
  97. data/lib/nanoc2/routers/default.rb +54 -0
  98. data/lib/nanoc2/routers/no_dirs.rb +66 -0
  99. data/lib/nanoc2/routers/versioned.rb +79 -0
  100. metadata +185 -0
@@ -0,0 +1,63 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::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
+ #
34
+ # To activate this helper, +include+ it, like this:
35
+ #
36
+ # include Nanoc2::Helpers::Capturing
37
+ module Capturing
38
+
39
+ # Captures the content inside the block into a page attribute named
40
+ # "content_for_" followed by the given name. The content of the block
41
+ # itself will not be outputted.
42
+ def content_for(name, &block)
43
+ eval("@page[:content_for_#{name.to_s}] = capture(&block)")
44
+ end
45
+
46
+ private
47
+
48
+ def capture(*args, &block)
49
+ buffer = eval('_erbout', block.binding)
50
+
51
+ pos = buffer.length
52
+ block.call(*args)
53
+
54
+ data = buffer[pos..-1]
55
+
56
+ buffer[pos..-1] = ''
57
+
58
+ data
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,54 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::Helpers::Filtering provides a filter method, which allows parts of
4
+ # a page to be filtered.
5
+ #
6
+ # For example, the following piece of code only runs the "rubypants" filter
7
+ # on the second paragraph:
8
+ #
9
+ # <p>Lorem ipsum dolor sit amet...</p>
10
+ # <% filter :rubypants do %>
11
+ # <p>Consectetur adipisicing elit...</p>
12
+ # <% end %>
13
+ #
14
+ # This helper likely only works with ERB (and perhaps Erubis).
15
+ #
16
+ # To activate this helper, +include+ it, like this:
17
+ #
18
+ # include Nanoc2::Helpers::Filtering
19
+ module Filtering
20
+
21
+ # Filters the content in the given block and outputs it.
22
+ def filter(filter_name, &block)
23
+ # Capture block
24
+ data = capture(&block)
25
+
26
+ # Find filter
27
+ filter = Nanoc2::Filter.named(filter_name).new(@_obj_rep)
28
+
29
+ # Filter captured data
30
+ filtered_data = filter.run(data)
31
+
32
+ # Append filtered data to buffer
33
+ buffer = eval('_erbout', block.binding)
34
+ buffer << filtered_data
35
+ end
36
+
37
+ private
38
+
39
+ def capture(*args, &block)
40
+ buffer = eval('_erbout', block.binding)
41
+
42
+ pos = buffer.length
43
+ block.call(*args)
44
+
45
+ data = buffer[pos..-1]
46
+
47
+ buffer[pos..-1] = ''
48
+
49
+ data
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,25 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::Helpers::HTMLEscape contains functionality for HTML-escaping
4
+ # strings.
5
+ #
6
+ # This helper is activated automatically.
7
+ module HTMLEscape
8
+
9
+ # Returns the HTML-escaped representation of the given string. Only &, <,
10
+ # > and " are escaped.
11
+ def html_escape(string)
12
+ string.gsub('&', '&amp;').
13
+ gsub('<', '&lt;').
14
+ gsub('>', '&gt;').
15
+ gsub('"', '&quot;')
16
+ end
17
+
18
+ alias h html_escape
19
+
20
+ end
21
+
22
+ end
23
+
24
+ # Include by default
25
+ include Nanoc2::Helpers::HTMLEscape
@@ -0,0 +1,113 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::Helpers::LinkTo contains functions for linking to pages.
4
+ #
5
+ # To activate this helper, +include+ it, like this:
6
+ #
7
+ # include Nanoc2::Helpers::LinkTo
8
+ module LinkTo
9
+
10
+ require 'nanoc2/helpers/html_escape'
11
+ include Nanoc2::Helpers::HTMLEscape
12
+
13
+ # Creates a HTML link to the given path or page/asset representation, and
14
+ # with the given text.
15
+ #
16
+ # +path_or_rep+:: the URL or path (a String) that should be linked to, or
17
+ # the page or asset representation that should be linked
18
+ # to.
19
+ #
20
+ # +text+:: the visible link text.
21
+ #
22
+ # +attributes+:: a hash containing HTML attributes that will be added to
23
+ # the link.
24
+ #
25
+ # Examples:
26
+ #
27
+ # link_to('Blog', '/blog/')
28
+ # # => '<a href="/blog/">Blog</a>'
29
+ #
30
+ # page_rep = @pages.find { |p| p.page_id == 'special' }.reps(:default)
31
+ # link_to('Special Page', page_rep)
32
+ # # => '<a href="/special_page/">Special Page</a>'
33
+ #
34
+ # link_to('Blog', '/blog/', :title => 'My super cool blog')
35
+ # # => '<a href="/blog/" title="My super cool blog">Blog</a>
36
+ def link_to(text, path_or_rep, attributes={})
37
+ # Find path
38
+ path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
39
+
40
+ # Join attributes
41
+ attributes = attributes.inject('') do |memo, (key, value)|
42
+ memo + key.to_s + '="' + h(value) + '" '
43
+ end
44
+
45
+ # Create link
46
+ "<a #{attributes}href=\"#{path}\">#{text}</a>"
47
+ end
48
+
49
+ # Creates a HTML link using link_to, except when the linked page is the
50
+ # current one. In this case, a span element with class "active" and with
51
+ # the given text will be returned.
52
+ #
53
+ # Examples:
54
+ #
55
+ # link_to_unless_current('Blog', '/blog/')
56
+ # # => '<a href="/blog/">Blog</a>'
57
+ #
58
+ # link_to_unless_current('This Page', @page_rep)
59
+ # # => '<span class="active">This Page</span>'
60
+ def link_to_unless_current(text, path_or_rep, attributes={})
61
+ # Find path
62
+ path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
63
+
64
+ if @page_rep and @page_rep.path == path
65
+ # Create message
66
+ "<span class=\"active\" title=\"You're here.\">#{text}</span>"
67
+ else
68
+ link_to(text, path_or_rep, attributes)
69
+ end
70
+ end
71
+
72
+ # Returns the relative path from the current page to the given path or
73
+ # page/asset representation.
74
+ #
75
+ # +path_or_rep+:: the URL or path (a String) to where the relative should
76
+ # point, or the page or asset representation to which the
77
+ # relative should point.
78
+ #
79
+ # Example:
80
+ #
81
+ # # if the current item's path is /foo/bar/
82
+ # relative_path('/foo/qux/')
83
+ # # => '../qux/'
84
+ def relative_path_to(path_or_rep)
85
+ require 'pathname'
86
+
87
+ # Find path
88
+ path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
89
+
90
+ # Get source and destination paths
91
+ dst_path = Pathname.new(path)
92
+ src_path = Pathname.new((defined?(@page) ? @page : @asset).path)
93
+
94
+ # Calculate elative path (method depends on whether destination is a
95
+ # directory or not).
96
+ if src_path.to_s[-1,1] != '/'
97
+ relative_path = dst_path.relative_path_from(src_path.dirname).to_s
98
+ else
99
+ relative_path = dst_path.relative_path_from(src_path).to_s
100
+ end
101
+
102
+ # Add trailing slash if necessary
103
+ if dst_path.to_s[-1,1] == '/'
104
+ relative_path += '/'
105
+ end
106
+
107
+ # Done
108
+ relative_path
109
+ end
110
+
111
+ end
112
+
113
+ end
@@ -0,0 +1,49 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::Helpers::Render provides functionality for rendering layouts as
4
+ # partials.
5
+ #
6
+ # This helper is activated automatically.
7
+ module Render
8
+
9
+ # Returns a string containing the rendered given layout.
10
+ #
11
+ # +name_or_path+:: the name or the path of the layout that should be
12
+ # rendered.
13
+ #
14
+ # +other_assigns+:: a hash containing assigns that will be made available
15
+ # as instance variables.
16
+ #
17
+ # Example 1: a layout 'head' with content "HEAD" and a layout 'foot' with
18
+ # content "FOOT":
19
+ #
20
+ # <%= render 'head' %> - MIDDLE - <%= render 'foot' %>
21
+ # # => "HEAD - MIDDLE - FOOT"
22
+ #
23
+ # Example 2: a layout named 'head' with content "<h1><%= @title %></h1>":
24
+ #
25
+ # <%= render 'head', :title => 'Foo' %>
26
+ # # => "<h1>Foo</h1>"
27
+ def render(name_or_path, other_assigns={})
28
+ # Find layout
29
+ layout = @_obj.site.layouts.find { |l| l.path == name_or_path.cleaned_path }
30
+ raise Nanoc2::Errors::UnknownLayoutError.new(name_or_path.cleaned_path) if layout.nil?
31
+
32
+ # Find filter
33
+ klass = layout.filter_class
34
+ raise Nanoc2::Errors::CannotDetermineFilterError.new(layout.path) if klass.nil?
35
+ filter = klass.new(@_obj_rep, other_assigns)
36
+
37
+ # Layout
38
+ @_obj.site.compiler.stack.push(layout)
39
+ result = filter.run(layout.content)
40
+ @_obj.site.compiler.stack.pop
41
+ result
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ # Include by default
49
+ include Nanoc2::Helpers::Render
@@ -0,0 +1,56 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::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
+ #
9
+ # To activate this helper, +include+ it, like this:
10
+ #
11
+ # include Nanoc2::Helpers::Tagging
12
+ module Tagging
13
+
14
+ # Returns a formatted list of tags for the given page as a string. Several
15
+ # parameters allow customization:
16
+ #
17
+ # :base_url:: The URL to which the tag will be appended to construct the
18
+ # link URL. This URL must have a trailing slash. Defaults to
19
+ # "http://technorati.com/tag/".
20
+ #
21
+ # :none_text:: The text to display when the page has no tags. Defaults to
22
+ # "(none)".
23
+ #
24
+ # :separator:: The separator to put between tags. Defaults to ", ".
25
+ def tags_for(page, params={})
26
+ base_url = params[:base_url] || 'http://technorati.com/tag/'
27
+ none_text = params[:none_text] || '(none)'
28
+ separator = params[:separator] || ', '
29
+
30
+ if page.tags.nil? or page.tags.empty?
31
+ none_text
32
+ else
33
+ page.tags.collect { |tag| link_for_tag(tag, base_url) }.join(separator)
34
+ end
35
+ end
36
+
37
+ # Returns all pages with the given tag.
38
+ def pages_with_tag(tag)
39
+ @pages.select { |p| (p.tags || []).include?(tag) }
40
+ end
41
+
42
+ # Returns a link to to the specified tag. The link is marked up using the
43
+ # rel-tag microformat.
44
+ #
45
+ # +tag+:: The name of the tag, which should consist of letters and numbers
46
+ # (no spaces, slashes, or other special characters).
47
+ #
48
+ # +base_url+:: The URL to which the tag will be appended to construct the
49
+ # link URL. This URL must have a trailing slash.
50
+ def link_for_tag(tag, base_url)
51
+ %[<a href="#{base_url}#{tag}" rel="tag">#{tag}</a>]
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,38 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::Helpers::Text contains several useful text-related helper functions.
4
+ module Text
5
+
6
+ # Returns an excerpt for the given string. HTML tags are ignored, so if
7
+ # you don't want them to turn up, they should be stripped from the string
8
+ # before passing it to the excerpt function.
9
+ #
10
+ # +params+ is a hash where the following keys can be set:
11
+ #
12
+ # +length+:: The maximum number of characters this excerpt can contain,
13
+ # including the omission. Defaults to 25.
14
+ #
15
+ # +omission+:: The string to append to the excerpt when the excerpt is
16
+ # shorter than the original string. Defaults to '...' (but in
17
+ # HTML, you may want to use something more fancy, like
18
+ # '&hellip;').
19
+ def excerptize(string, params={})
20
+ # Initialize params
21
+ params[:length] ||= 25
22
+ params[:omission] ||= '...'
23
+
24
+ # Get excerpt
25
+ length = params[:length] - params[:omission].length
26
+ length = 0 if length < 0
27
+ (string.length > params[:length] ? string[0...length] + params[:omission] : string)
28
+ end
29
+
30
+ # Strips all HTML tags out of the given string.
31
+ def strip_html(string)
32
+ # FIXME will need something more sophisticated than this, because it sucks
33
+ string.gsub(/<[^>]*(>+|\s*\z)/m, '').strip
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,63 @@
1
+ module Nanoc2::Helpers
2
+
3
+ # Nanoc2::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
+ #
7
+ # To activate this helper, +include+ it, like this:
8
+ #
9
+ # include Nanoc2::Helpers::XMLSitemap
10
+ module XMLSitemap
11
+
12
+ # Returns the XML sitemap as a string.
13
+ #
14
+ # The following attributes can optionally be set on pages to change the
15
+ # behaviour of the sitemap:
16
+ #
17
+ # * 'changefreq', containing the estimated change frequency as defined by
18
+ # the Sitemaps protocol.
19
+ #
20
+ # * 'priority', containing the page's priority, ranging from 0.0 to 1.0,
21
+ # as defined by the Sitemaps protocol.
22
+ #
23
+ # The sitemap will also include dates on which the pages were updated.
24
+ # These are generated automatically; the way this happens depends on the
25
+ # used data source (the filesystem data source checks the file mtimes, for
26
+ # instance).
27
+ #
28
+ # The sitemap page will need to have the following attributes:
29
+ #
30
+ # * 'base_url', containing the URL to the site, without trailing slash.
31
+ # For example, if the site is at "http://example.com/", the base_url
32
+ # would be "http://example.com". It is probably a good idea to define
33
+ # this in the page defaults, i.e. the 'meta.yaml' file (at least if the
34
+ # filesystem data source is being used, which is probably the case).
35
+ def xml_sitemap
36
+ require 'builder'
37
+
38
+ # Create builder
39
+ buffer = ''
40
+ xml = Builder::XmlMarkup.new(:target => buffer, :indent => 2)
41
+
42
+ # Build sitemap
43
+ xml.instruct!
44
+ xml.urlset(:xmlns => 'http://www.google.com/schemas/sitemap/0.84') do
45
+ # Add page
46
+ @pages.reject { |p| p.is_hidden || p.skip_output }.each do |page|
47
+ xml.url do
48
+ loc = (@site.config[:base_url] || @page.base_url) + page.path
49
+ xml.loc loc
50
+ xml.lastmod page.mtime.to_iso8601_date unless page.mtime.nil?
51
+ xml.changefreq page.changefreq unless page.changefreq.nil?
52
+ xml.priority page.priority unless page.priority.nil?
53
+ end
54
+ end
55
+ end
56
+
57
+ # Return sitemap
58
+ buffer
59
+ end
60
+
61
+ end
62
+
63
+ end