nanoc 2.0.4 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/ChangeLog +31 -1
  2. data/LICENSE +1 -1
  3. data/README +63 -3
  4. data/Rakefile +59 -12
  5. data/bin/nanoc +7 -199
  6. data/lib/nanoc.rb +83 -12
  7. data/lib/nanoc/base/asset.rb +113 -0
  8. data/lib/nanoc/base/asset_defaults.rb +21 -0
  9. data/lib/nanoc/base/asset_rep.rb +277 -0
  10. data/lib/nanoc/base/binary_filter.rb +44 -0
  11. data/lib/nanoc/base/code.rb +41 -0
  12. data/lib/nanoc/base/compiler.rb +46 -34
  13. data/lib/nanoc/base/core_ext/hash.rb +51 -7
  14. data/lib/nanoc/base/core_ext/string.rb +8 -0
  15. data/lib/nanoc/base/data_source.rb +253 -20
  16. data/lib/nanoc/base/defaults.rb +30 -0
  17. data/lib/nanoc/base/enhancements.rb +9 -84
  18. data/lib/nanoc/base/filter.rb +109 -6
  19. data/lib/nanoc/base/layout.rb +91 -0
  20. data/lib/nanoc/base/notification_center.rb +66 -0
  21. data/lib/nanoc/base/page.rb +94 -126
  22. data/lib/nanoc/base/page_defaults.rb +20 -0
  23. data/lib/nanoc/base/page_rep.rb +318 -0
  24. data/lib/nanoc/base/plugin.rb +57 -9
  25. data/lib/nanoc/base/proxies/asset_proxy.rb +29 -0
  26. data/lib/nanoc/base/proxies/asset_rep_proxy.rb +26 -0
  27. data/lib/nanoc/base/proxies/layout_proxy.rb +25 -0
  28. data/lib/nanoc/base/proxies/page_proxy.rb +35 -0
  29. data/lib/nanoc/base/proxies/page_rep_proxy.rb +28 -0
  30. data/lib/nanoc/base/proxy.rb +37 -0
  31. data/lib/nanoc/base/router.rb +72 -0
  32. data/lib/nanoc/base/site.rb +219 -88
  33. data/lib/nanoc/base/template.rb +64 -0
  34. data/lib/nanoc/binary_filters/image_science_thumbnail.rb +28 -0
  35. data/lib/nanoc/cli.rb +1 -0
  36. data/lib/nanoc/cli/base.rb +219 -0
  37. data/lib/nanoc/cli/cli.rb +16 -0
  38. data/lib/nanoc/cli/command.rb +105 -0
  39. data/lib/nanoc/cli/commands/autocompile.rb +80 -0
  40. data/lib/nanoc/cli/commands/compile.rb +273 -0
  41. data/lib/nanoc/cli/commands/create_layout.rb +85 -0
  42. data/lib/nanoc/cli/commands/create_page.rb +85 -0
  43. data/lib/nanoc/cli/commands/create_site.rb +327 -0
  44. data/lib/nanoc/cli/commands/create_template.rb +76 -0
  45. data/lib/nanoc/cli/commands/help.rb +69 -0
  46. data/lib/nanoc/cli/commands/info.rb +114 -0
  47. data/lib/nanoc/cli/commands/switch.rb +141 -0
  48. data/lib/nanoc/cli/commands/update.rb +91 -0
  49. data/lib/nanoc/cli/ext.rb +37 -0
  50. data/lib/nanoc/cli/logger.rb +66 -0
  51. data/lib/nanoc/cli/option_parser.rb +168 -0
  52. data/lib/nanoc/data_sources/filesystem.rb +645 -224
  53. data/lib/nanoc/data_sources/filesystem_combined.rb +495 -0
  54. data/lib/nanoc/extra/auto_compiler.rb +265 -0
  55. data/lib/nanoc/extra/context.rb +22 -0
  56. data/lib/nanoc/extra/core_ext/hash.rb +54 -0
  57. data/lib/nanoc/extra/core_ext/time.rb +13 -0
  58. data/lib/nanoc/extra/file_proxy.rb +29 -0
  59. data/lib/nanoc/extra/vcs.rb +48 -0
  60. data/lib/nanoc/extra/vcses/bazaar.rb +21 -0
  61. data/lib/nanoc/extra/vcses/dummy.rb +20 -0
  62. data/lib/nanoc/extra/vcses/git.rb +21 -0
  63. data/lib/nanoc/extra/vcses/mercurial.rb +21 -0
  64. data/lib/nanoc/extra/vcses/subversion.rb +21 -0
  65. data/lib/nanoc/filters/bluecloth.rb +13 -0
  66. data/lib/nanoc/filters/erb.rb +6 -22
  67. data/lib/nanoc/filters/erubis.rb +14 -0
  68. data/lib/nanoc/filters/haml.rb +7 -23
  69. data/lib/nanoc/filters/markaby.rb +5 -5
  70. data/lib/nanoc/filters/maruku.rb +14 -0
  71. data/lib/nanoc/filters/old.rb +19 -0
  72. data/lib/nanoc/filters/rdiscount.rb +13 -0
  73. data/lib/nanoc/filters/rdoc.rb +5 -4
  74. data/lib/nanoc/filters/redcloth.rb +14 -0
  75. data/lib/nanoc/filters/rubypants.rb +14 -0
  76. data/lib/nanoc/filters/sass.rb +13 -0
  77. data/lib/nanoc/helpers/blogging.rb +170 -0
  78. data/lib/nanoc/helpers/capturing.rb +59 -0
  79. data/lib/nanoc/helpers/html_escape.rb +23 -0
  80. data/lib/nanoc/helpers/link_to.rb +69 -0
  81. data/lib/nanoc/helpers/render.rb +47 -0
  82. data/lib/nanoc/helpers/tagging.rb +52 -0
  83. data/lib/nanoc/helpers/xml_sitemap.rb +58 -0
  84. data/lib/nanoc/routers/default.rb +54 -0
  85. data/lib/nanoc/routers/no_dirs.rb +66 -0
  86. data/lib/nanoc/routers/versioned.rb +79 -0
  87. metadata +112 -22
  88. data/lib/nanoc/base/auto_compiler.rb +0 -132
  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 -38
  99. data/lib/nanoc/layout_processors/markaby.rb +0 -16
@@ -0,0 +1,20 @@
1
+ module Nanoc::Extra::VCSes
2
+
3
+ class Dummy < Nanoc::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 Nanoc::Extra::VCSes
2
+
3
+ class Git < Nanoc::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 Nanoc::Extra::VCSes
2
+
3
+ class Mercurial < Nanoc::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 Nanoc::Extra::VCSes
2
+
3
+ class Subversion < Nanoc::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,13 @@
1
+ module Nanoc::Filters
2
+ class BlueCloth < Nanoc::Filter
3
+
4
+ identifiers :bluecloth
5
+
6
+ def run(content)
7
+ require 'bluecloth'
8
+
9
+ ::BlueCloth.new(content).to_html
10
+ end
11
+
12
+ end
13
+ end
@@ -1,34 +1,18 @@
1
- module Nanoc::Filter::ERB
1
+ module Nanoc::Filters
2
+ class ERB < Nanoc::Filter
2
3
 
3
- class Context
4
-
5
- def initialize(hash)
6
- hash.each_pair do |key, value|
7
- instance_variable_set('@' + key.to_s, value)
8
- end
9
- end
10
-
11
- def get_binding
12
- binding
13
- end
14
-
15
- end
16
-
17
- class ERBFilter < Nanoc::Filter
18
-
19
- identifiers :erb, :eruby
4
+ identifiers :erb
5
+ extensions '.erb', '.rhtml'
20
6
 
21
7
  def run(content)
22
- nanoc_require 'erb'
8
+ require 'erb'
23
9
 
24
10
  # Create context
25
- assigns = { :page => @page, :pages => @pages, :config => @config, :site => @site }
26
- context = Context.new(assigns)
11
+ context = ::Nanoc::Extra::Context.new(assigns)
27
12
 
28
13
  # Get result
29
14
  ::ERB.new(content).result(context.get_binding)
30
15
  end
31
16
 
32
17
  end
33
-
34
18
  end
@@ -0,0 +1,14 @@
1
+ module Nanoc::Filters
2
+ class Erubis < Nanoc::Filter
3
+
4
+ identifiers :erubis
5
+
6
+ def run(content)
7
+ require 'erubis'
8
+
9
+ # Get result
10
+ ::Erubis::Eruby.new(content).evaluate(assigns)
11
+ end
12
+
13
+ end
14
+ end
@@ -1,37 +1,21 @@
1
- module Nanoc::Filter::Haml
2
-
3
- class Context
4
-
5
- def initialize(hash)
6
- hash.each_pair do |key, value|
7
- instance_variable_set('@' + key.to_s, value)
8
- end
9
- end
10
-
11
- def get_binding
12
- binding
13
- end
14
-
15
- end
16
-
17
- class HamlFilter < Nanoc::Filter
1
+ module Nanoc::Filters
2
+ class Haml < Nanoc::Filter
18
3
 
19
4
  identifiers :haml
5
+ extensions '.haml'
20
6
 
21
7
  def run(content)
22
- nanoc_require 'haml'
8
+ require 'haml'
23
9
 
24
10
  # Get options
25
- options = @page.haml_options || {}
11
+ options = @page.attribute_named(:haml_options) || {}
26
12
 
27
- # Get assigns/locals
28
- assigns = { :page => @page, :pages => @pages, :config => @config, :site => @site }
29
- context = Context.new(assigns)
13
+ # Create context
14
+ context = ::Nanoc::Extra::Context.new(assigns)
30
15
 
31
16
  # Get result
32
17
  ::Haml::Engine.new(content, options).render(context, assigns)
33
18
  end
34
19
 
35
20
  end
36
-
37
21
  end
@@ -1,13 +1,13 @@
1
- module Nanoc::Filter::Markaby
2
- class MarkabyFilter < Nanoc::Filter
1
+ module Nanoc::Filters
2
+ class Markaby < Nanoc::Filter
3
3
 
4
4
  identifiers :markaby
5
+ extensions '.mab'
5
6
 
6
7
  def run(content)
7
- nanoc_require 'markaby'
8
-
9
- assigns = { :page => @page, :pages => @pages, :config => @config, :site => @site }
8
+ require 'markaby'
10
9
 
10
+ # Get result
11
11
  ::Markaby::Builder.new(assigns).instance_eval(content).to_s
12
12
  end
13
13
 
@@ -0,0 +1,14 @@
1
+ module Nanoc::Filters
2
+ class Maruku < Nanoc::Filter
3
+
4
+ identifiers :maruku
5
+
6
+ def run(content)
7
+ require 'maruku'
8
+
9
+ # Get result
10
+ ::Maruku.new(content).to_html
11
+ end
12
+
13
+ end
14
+ end
@@ -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