nanoc2 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
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