nanoc3 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +3 -0
- data/LICENSE +19 -0
- data/NEWS.rdoc +262 -0
- data/README.rdoc +80 -0
- data/Rakefile +11 -0
- data/bin/nanoc3 +16 -0
- data/lib/nanoc3/base/code_snippet.rb +42 -0
- data/lib/nanoc3/base/compiler.rb +225 -0
- data/lib/nanoc3/base/compiler_dsl.rb +110 -0
- data/lib/nanoc3/base/core_ext/array.rb +21 -0
- data/lib/nanoc3/base/core_ext/hash.rb +23 -0
- data/lib/nanoc3/base/core_ext/string.rb +14 -0
- data/lib/nanoc3/base/core_ext.rb +5 -0
- data/lib/nanoc3/base/data_source.rb +197 -0
- data/lib/nanoc3/base/dependency_tracker.rb +291 -0
- data/lib/nanoc3/base/errors.rb +95 -0
- data/lib/nanoc3/base/filter.rb +60 -0
- data/lib/nanoc3/base/item.rb +87 -0
- data/lib/nanoc3/base/item_rep.rb +236 -0
- data/lib/nanoc3/base/layout.rb +53 -0
- data/lib/nanoc3/base/notification_center.rb +68 -0
- data/lib/nanoc3/base/plugin.rb +88 -0
- data/lib/nanoc3/base/preprocessor_context.rb +37 -0
- data/lib/nanoc3/base/rule.rb +37 -0
- data/lib/nanoc3/base/rule_context.rb +68 -0
- data/lib/nanoc3/base/site.rb +334 -0
- data/lib/nanoc3/base.rb +25 -0
- data/lib/nanoc3/cli/base.rb +151 -0
- data/lib/nanoc3/cli/commands/autocompile.rb +89 -0
- data/lib/nanoc3/cli/commands/compile.rb +279 -0
- data/lib/nanoc3/cli/commands/create_item.rb +79 -0
- data/lib/nanoc3/cli/commands/create_layout.rb +94 -0
- data/lib/nanoc3/cli/commands/create_site.rb +320 -0
- data/lib/nanoc3/cli/commands/help.rb +71 -0
- data/lib/nanoc3/cli/commands/info.rb +114 -0
- data/lib/nanoc3/cli/commands/update.rb +96 -0
- data/lib/nanoc3/cli/commands.rb +13 -0
- data/lib/nanoc3/cli/logger.rb +73 -0
- data/lib/nanoc3/cli.rb +16 -0
- data/lib/nanoc3/data_sources/delicious.rb +66 -0
- data/lib/nanoc3/data_sources/filesystem.rb +231 -0
- data/lib/nanoc3/data_sources/filesystem_combined.rb +202 -0
- data/lib/nanoc3/data_sources/filesystem_common.rb +22 -0
- data/lib/nanoc3/data_sources/filesystem_compact.rb +232 -0
- data/lib/nanoc3/data_sources/last_fm.rb +103 -0
- data/lib/nanoc3/data_sources/twitter.rb +53 -0
- data/lib/nanoc3/data_sources.rb +20 -0
- data/lib/nanoc3/extra/auto_compiler.rb +97 -0
- data/lib/nanoc3/extra/chick.rb +119 -0
- data/lib/nanoc3/extra/context.rb +24 -0
- data/lib/nanoc3/extra/core_ext/time.rb +19 -0
- data/lib/nanoc3/extra/core_ext.rb +3 -0
- data/lib/nanoc3/extra/deployers/rsync.rb +64 -0
- data/lib/nanoc3/extra/deployers.rb +12 -0
- data/lib/nanoc3/extra/file_proxy.rb +31 -0
- data/lib/nanoc3/extra/validators/links.rb +0 -0
- data/lib/nanoc3/extra/validators/w3c.rb +71 -0
- data/lib/nanoc3/extra/validators.rb +12 -0
- data/lib/nanoc3/extra/vcs.rb +65 -0
- data/lib/nanoc3/extra/vcses/bazaar.rb +21 -0
- data/lib/nanoc3/extra/vcses/dummy.rb +20 -0
- data/lib/nanoc3/extra/vcses/git.rb +21 -0
- data/lib/nanoc3/extra/vcses/mercurial.rb +21 -0
- data/lib/nanoc3/extra/vcses/subversion.rb +21 -0
- data/lib/nanoc3/extra/vcses.rb +17 -0
- data/lib/nanoc3/extra.rb +16 -0
- data/lib/nanoc3/filters/bluecloth.rb +13 -0
- data/lib/nanoc3/filters/coderay.rb +17 -0
- data/lib/nanoc3/filters/erb.rb +19 -0
- data/lib/nanoc3/filters/erubis.rb +17 -0
- data/lib/nanoc3/filters/haml.rb +20 -0
- data/lib/nanoc3/filters/less.rb +13 -0
- data/lib/nanoc3/filters/markaby.rb +14 -0
- data/lib/nanoc3/filters/maruku.rb +14 -0
- data/lib/nanoc3/filters/rainpress.rb +13 -0
- data/lib/nanoc3/filters/rdiscount.rb +13 -0
- data/lib/nanoc3/filters/rdoc.rb +23 -0
- data/lib/nanoc3/filters/redcloth.rb +14 -0
- data/lib/nanoc3/filters/relativize_paths.rb +32 -0
- data/lib/nanoc3/filters/rubypants.rb +14 -0
- data/lib/nanoc3/filters/sass.rb +17 -0
- data/lib/nanoc3/filters.rb +37 -0
- data/lib/nanoc3/helpers/blogging.rb +226 -0
- data/lib/nanoc3/helpers/breadcrumbs.rb +25 -0
- data/lib/nanoc3/helpers/capturing.rb +71 -0
- data/lib/nanoc3/helpers/filtering.rb +46 -0
- data/lib/nanoc3/helpers/html_escape.rb +22 -0
- data/lib/nanoc3/helpers/link_to.rb +120 -0
- data/lib/nanoc3/helpers/rendering.rb +76 -0
- data/lib/nanoc3/helpers/tagging.rb +58 -0
- data/lib/nanoc3/helpers/text.rb +40 -0
- data/lib/nanoc3/helpers/xml_sitemap.rb +69 -0
- data/lib/nanoc3/helpers.rb +16 -0
- data/lib/nanoc3/package.rb +106 -0
- data/lib/nanoc3/tasks/clean.rake +16 -0
- data/lib/nanoc3/tasks/clean.rb +33 -0
- data/lib/nanoc3/tasks/deploy/rsync.rake +11 -0
- data/lib/nanoc3/tasks/validate.rake +35 -0
- data/lib/nanoc3/tasks.rb +9 -0
- data/lib/nanoc3.rb +19 -0
- data/vendor/cri/ChangeLog +0 -0
- data/vendor/cri/LICENSE +19 -0
- data/vendor/cri/NEWS +0 -0
- data/vendor/cri/README +4 -0
- data/vendor/cri/Rakefile +25 -0
- data/vendor/cri/lib/cri/base.rb +153 -0
- data/vendor/cri/lib/cri/command.rb +105 -0
- data/vendor/cri/lib/cri/core_ext/string.rb +41 -0
- data/vendor/cri/lib/cri/core_ext.rb +8 -0
- data/vendor/cri/lib/cri/option_parser.rb +186 -0
- data/vendor/cri/lib/cri.rb +12 -0
- data/vendor/cri/test/test_base.rb +6 -0
- data/vendor/cri/test/test_command.rb +6 -0
- data/vendor/cri/test/test_core_ext.rb +21 -0
- data/vendor/cri/test/test_option_parser.rb +279 -0
- metadata +225 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Filters
|
4
|
+
|
5
|
+
autoload 'BlueCloth', 'nanoc3/filters/bluecloth'
|
6
|
+
autoload 'CodeRay', 'nanoc3/filters/coderay'
|
7
|
+
autoload 'ERB', 'nanoc3/filters/erb'
|
8
|
+
autoload 'Erubis', 'nanoc3/filters/erubis'
|
9
|
+
autoload 'Haml', 'nanoc3/filters/haml'
|
10
|
+
autoload 'Less', 'nanoc3/filters/less'
|
11
|
+
autoload 'Markaby', 'nanoc3/filters/markaby'
|
12
|
+
autoload 'Maruku', 'nanoc3/filters/maruku'
|
13
|
+
autoload 'Rainpress', 'nanoc3/filters/rainpress'
|
14
|
+
autoload 'RDiscount', 'nanoc3/filters/rdiscount'
|
15
|
+
autoload 'RDoc', 'nanoc3/filters/rdoc'
|
16
|
+
autoload 'RedCloth', 'nanoc3/filters/redcloth'
|
17
|
+
autoload 'RelativizePaths', 'nanoc3/filters/relativize_paths'
|
18
|
+
autoload 'RubyPants', 'nanoc3/filters/rubypants'
|
19
|
+
autoload 'Sass', 'nanoc3/filters/sass'
|
20
|
+
|
21
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::BlueCloth', :bluecloth
|
22
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::CodeRay', :coderay
|
23
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::ERB', :erb
|
24
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Erubis', :erubis
|
25
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Haml', :haml
|
26
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Less', :less
|
27
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Markaby', :markaby
|
28
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Maruku', :maruku
|
29
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Rainpress', :rainpress
|
30
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::RDiscount', :rdiscount
|
31
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::RDoc', :rdoc
|
32
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::RedCloth', :redcloth
|
33
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::RelativizePaths', :relativize_paths
|
34
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::RubyPants', :rubypants
|
35
|
+
Nanoc3::Filter.register '::Nanoc3::Filters::Sass', :sass
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::Blogging provides some functionality for building blogs,
|
6
|
+
# such as finding articles and constructing feeds.
|
7
|
+
#
|
8
|
+
# This helper has a few requirements. First, all blog articles should have
|
9
|
+
# the following attributes:
|
10
|
+
#
|
11
|
+
# * 'kind', set to 'article'.
|
12
|
+
#
|
13
|
+
# * 'created_at', set to the creation timestamp.
|
14
|
+
#
|
15
|
+
# Some functions in this blogging helper, such as the +atom_feed+ function,
|
16
|
+
# require additional attributes to be set; these attributes are described in
|
17
|
+
# the documentation for these functions.
|
18
|
+
#
|
19
|
+
# The two main functions are sorted_articles and atom_feed.
|
20
|
+
#
|
21
|
+
# To activate this helper, +include+ it, like this:
|
22
|
+
#
|
23
|
+
# include Nanoc3::Helpers::Blogging
|
24
|
+
module Blogging
|
25
|
+
|
26
|
+
# Returns an unsorted list of articles.
|
27
|
+
def articles
|
28
|
+
@items.select { |item| item[:kind] == 'article' }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a list of articles, sorted by descending creation date (so newer
|
32
|
+
# articles appear first).
|
33
|
+
def sorted_articles
|
34
|
+
require 'time'
|
35
|
+
articles.sort_by { |a| Time.parse(a[:created_at]) }.reverse
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a string representing the atom feed containing recent articles,
|
39
|
+
# sorted by descending creation date. +params+ is a hash where the
|
40
|
+
# following keys can be set:
|
41
|
+
#
|
42
|
+
# +limit+:: The maximum number of articles to show. Defaults to 5.
|
43
|
+
#
|
44
|
+
# +articles+:: A list of articles to include in the feed. Defaults to the
|
45
|
+
# list of articles returned by the articles function.
|
46
|
+
#
|
47
|
+
# +content_proc+:: A proc that returns the content of the given article,
|
48
|
+
# passed as a parameter. By default, given the argument
|
49
|
+
# +article+, this proc will return
|
50
|
+
# +article.reps[0].content+. This function may not return
|
51
|
+
# nil.
|
52
|
+
#
|
53
|
+
# +excerpt_proc+:: A proc that returns the excerpt of the given article,
|
54
|
+
# passed as a parameter. By default, given the argument
|
55
|
+
# +article+, this proc will return +article.excerpt+.
|
56
|
+
# This function may return nil.
|
57
|
+
#
|
58
|
+
# The following attributes must be set on blog articles:
|
59
|
+
#
|
60
|
+
# * 'title', containing the title of the blog post.
|
61
|
+
#
|
62
|
+
# * all other attributes mentioned above.
|
63
|
+
#
|
64
|
+
# The following attributes can optionally be set on blog articles to
|
65
|
+
# change the behaviour of the Atom feed:
|
66
|
+
#
|
67
|
+
# * 'excerpt', containing an excerpt of the article, usually only a few
|
68
|
+
# lines long.
|
69
|
+
#
|
70
|
+
# * 'custom_path_in_feed', containing the path that will be used instead
|
71
|
+
# of the normal path in the feed. This can be useful when including
|
72
|
+
# non-outputted items in a feed; such items could have their custom feed
|
73
|
+
# path set to the blog path instead, for example.
|
74
|
+
#
|
75
|
+
# The feed will also include dates on which the articles were updated.
|
76
|
+
# These are generated automatically; the way this happens depends on the
|
77
|
+
# used data source (the filesystem data source checks the file mtimes, for
|
78
|
+
# instance).
|
79
|
+
#
|
80
|
+
# The site configuration will need to have the following attributes:
|
81
|
+
#
|
82
|
+
# * 'base_url', containing the URL to the site, without trailing slash.
|
83
|
+
# For example, if the site is at "http://example.com/", the base_url
|
84
|
+
# would be "http://example.com".
|
85
|
+
#
|
86
|
+
# The feed item will need to have the following attributes:
|
87
|
+
#
|
88
|
+
# * 'title', containing the title of the feed, which is usually also the
|
89
|
+
# title of the blog.
|
90
|
+
#
|
91
|
+
# * 'author_name', containing the name of the item's author. This will
|
92
|
+
# likely be a global attribute, unless the site is managed by several
|
93
|
+
# people/
|
94
|
+
#
|
95
|
+
# * 'author_uri', containing the URI for the item's author, such as the
|
96
|
+
# author's web site URL. This will also likely be a global attribute.
|
97
|
+
#
|
98
|
+
# The feed item can have the following optional attributes:
|
99
|
+
#
|
100
|
+
# * 'feed_url', containing the custom URL of the feed. This can be useful
|
101
|
+
# when the private feed URL shouldn't be exposed; for example, when
|
102
|
+
# using FeedBurner this would be set to the public FeedBurner URL.
|
103
|
+
#
|
104
|
+
# To construct a feed, create a blank item with no layout, only the 'erb'
|
105
|
+
# (or 'erubis') filter, and an 'xml' extension. It may also be useful to
|
106
|
+
# set 'is_hidden' to true, so that helpers such as the sitemap helper will
|
107
|
+
# ignore the item. The content of the feed item should be:
|
108
|
+
#
|
109
|
+
# <%= atom_feed %>
|
110
|
+
def atom_feed(params={})
|
111
|
+
require 'builder'
|
112
|
+
require 'time'
|
113
|
+
|
114
|
+
# Extract parameters
|
115
|
+
limit = params[:limit] || 5
|
116
|
+
relevant_articles = params[:articles] || articles || []
|
117
|
+
content_proc = params[:content_proc] || lambda { |a| a.reps[0].content_at_snapshot(:pre) }
|
118
|
+
excerpt_proc = params[:excerpt_proc] || lambda { |a| a[:excerpt] }
|
119
|
+
|
120
|
+
# Check config attributes
|
121
|
+
if @site.config[:base_url].nil?
|
122
|
+
raise RuntimeError.new('Cannot build Atom feed: site configuration has no base_url')
|
123
|
+
end
|
124
|
+
|
125
|
+
# Check feed item attributes
|
126
|
+
if @item[:title].nil?
|
127
|
+
raise RuntimeError.new('Cannot build Atom feed: feed item has no title')
|
128
|
+
end
|
129
|
+
if @item[:author_name].nil?
|
130
|
+
raise RuntimeError.new('Cannot build Atom feed: feed item has no author_name')
|
131
|
+
end
|
132
|
+
if @item[:author_uri].nil?
|
133
|
+
raise RuntimeError.new('Cannot build Atom feed: feed item has no author_uri')
|
134
|
+
end
|
135
|
+
|
136
|
+
# Check article attributes
|
137
|
+
if relevant_articles.empty?
|
138
|
+
raise RuntimeError.new('Cannot build Atom feed: no articles')
|
139
|
+
end
|
140
|
+
if relevant_articles.any? { |a| a[:created_at].nil? }
|
141
|
+
raise RuntimeError.new('Cannot build Atom feed: one or more articles lack created_at')
|
142
|
+
end
|
143
|
+
|
144
|
+
# Get sorted relevant articles
|
145
|
+
sorted_relevant_articles = relevant_articles.sort_by { |a| Time.parse(a[:created_at]) }.reverse.first(limit)
|
146
|
+
|
147
|
+
# Get most recent article
|
148
|
+
last_article = sorted_relevant_articles.first
|
149
|
+
|
150
|
+
# Create builder
|
151
|
+
buffer = ''
|
152
|
+
xml = Builder::XmlMarkup.new(:target => buffer, :indent => 2)
|
153
|
+
|
154
|
+
# Build feed
|
155
|
+
xml.instruct!
|
156
|
+
xml.feed(:xmlns => 'http://www.w3.org/2005/Atom') do
|
157
|
+
# Add primary attributes
|
158
|
+
xml.id @site.config[:base_url] + '/'
|
159
|
+
xml.title @item[:title]
|
160
|
+
|
161
|
+
# Add date
|
162
|
+
xml.updated Time.parse(last_article[:created_at]).to_iso8601_time
|
163
|
+
|
164
|
+
# Add links
|
165
|
+
xml.link(:rel => 'alternate', :href => @site.config[:base_url])
|
166
|
+
xml.link(:rel => 'self', :href => feed_url)
|
167
|
+
|
168
|
+
# Add author information
|
169
|
+
xml.author do
|
170
|
+
xml.name @item[:author_name]
|
171
|
+
xml.uri @item[:author_uri]
|
172
|
+
end
|
173
|
+
|
174
|
+
# Add articles
|
175
|
+
sorted_relevant_articles.each do |a|
|
176
|
+
xml.entry do
|
177
|
+
# Add primary attributes
|
178
|
+
xml.id atom_tag_for(a)
|
179
|
+
xml.title a[:title], :type => 'html'
|
180
|
+
|
181
|
+
# Add dates
|
182
|
+
xml.published Time.parse(a[:created_at]).to_iso8601_time
|
183
|
+
xml.updated a.mtime.to_iso8601_time
|
184
|
+
|
185
|
+
# Add link
|
186
|
+
xml.link(:rel => 'alternate', :href => url_for(a))
|
187
|
+
|
188
|
+
# Add content
|
189
|
+
summary = excerpt_proc.call(a)
|
190
|
+
xml.content content_proc.call(a), :type => 'html'
|
191
|
+
xml.summary summary, :type => 'html' unless summary.nil?
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
buffer
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the URL for the given item. It will return the URL containing
|
200
|
+
# the custom path in the feed if possible, otherwise the normal path.
|
201
|
+
def url_for(item)
|
202
|
+
@site.config[:base_url] + (item[:custom_path_in_feed] || item.reps[0].path)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Returns the URL of the feed. It will return the custom feed URL if set,
|
206
|
+
# or otherwise the normal feed URL.
|
207
|
+
def feed_url
|
208
|
+
@item[:feed_url] || @site.config[:base_url] + @item.reps[0].path
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns an URI containing an unique ID for the given item. This will be
|
212
|
+
# used in the Atom feed to uniquely identify articles. These IDs are
|
213
|
+
# created using a procedure suggested by Mark Pilgrim in this blog post:
|
214
|
+
# http://diveintomark.org/archives/2004/05/28/howto-atom-id.
|
215
|
+
def atom_tag_for(item)
|
216
|
+
require 'time'
|
217
|
+
|
218
|
+
hostname = @site.config[:base_url].sub(/.*:\/\/(.+?)\/?$/, '\1')
|
219
|
+
formatted_date = Time.parse(item[:created_at]).to_iso8601_date
|
220
|
+
|
221
|
+
'tag:' + hostname + ',' + formatted_date + ':' + (item.reps[0].path || item.identifier)
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::Breadcrumbs provides support for breadcrumbs, which allow
|
6
|
+
# the user to go up in the page hierarchy.
|
7
|
+
module Breadcrumbs
|
8
|
+
|
9
|
+
# Returns the breadcrumbs trail as an array. Higher items (items that are
|
10
|
+
# closer to the root) come before lower items.
|
11
|
+
def breadcrumbs_trail
|
12
|
+
trail = []
|
13
|
+
item = @item
|
14
|
+
|
15
|
+
begin
|
16
|
+
trail.unshift(item)
|
17
|
+
item = item.parent
|
18
|
+
end until item.nil?
|
19
|
+
|
20
|
+
trail
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::Capturing provides a content_for method, which allows
|
6
|
+
# content to be "captured" on one item and reused elsewhere.
|
7
|
+
#
|
8
|
+
# = Example
|
9
|
+
#
|
10
|
+
# For example, suppose you want the sidebar of your site to contain a short
|
11
|
+
# summary of the item. You could put the summary in the meta file, but
|
12
|
+
# that’s not possible when the summary contains eRuby. You could also put
|
13
|
+
# the sidebar inside the actual item, but that’s not very pretty. Instead,
|
14
|
+
# you write the summary on the item itself, but capture it, and print it in
|
15
|
+
# the sidebar layout.
|
16
|
+
#
|
17
|
+
# Captured content becomes part of the item. For example, a sidebar layout
|
18
|
+
# could look like this:
|
19
|
+
#
|
20
|
+
# <div id="sidebar">
|
21
|
+
# <h3>Summary</h3>
|
22
|
+
# <%= @item[:content_for_summary] || '(no summary)' %>
|
23
|
+
# </div>
|
24
|
+
#
|
25
|
+
# To put something inside that content_for_summary variable, capture it
|
26
|
+
# using the content_for function. In the about item, for example:
|
27
|
+
#
|
28
|
+
# <% content_for :summary do %>
|
29
|
+
# <p>On this item, nanoc is introduced, blah blah.</p>
|
30
|
+
# <% end %>
|
31
|
+
#
|
32
|
+
# When the site is compiled, the sidebar of the about item will say “On
|
33
|
+
# this item, the purpose of nanoc is described, blah blah blah,” as
|
34
|
+
# expected.
|
35
|
+
#
|
36
|
+
# This helper likely only works with ERB (and perhaps Erubis).
|
37
|
+
#
|
38
|
+
# To activate this helper, +include+ it, like this:
|
39
|
+
#
|
40
|
+
# include Nanoc3::Helpers::Capturing
|
41
|
+
module Capturing
|
42
|
+
|
43
|
+
# Captures the content inside the block into a item attribute named
|
44
|
+
# "content_for_" followed by the given name. The content of the block
|
45
|
+
# itself will not be outputted.
|
46
|
+
def content_for(name, &block)
|
47
|
+
eval("@item[:content_for_#{name.to_s}] = capture(&block)")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Evaluates the given block and returns the result. The block is not outputted.
|
51
|
+
def capture(*args, &block)
|
52
|
+
# Get erbout so far
|
53
|
+
erbout = eval('_erbout', block.binding)
|
54
|
+
erbout_length = erbout.length
|
55
|
+
|
56
|
+
# Execute block
|
57
|
+
block.call(*args)
|
58
|
+
|
59
|
+
# Get new piece of erbout
|
60
|
+
erbout_addition = erbout[erbout_length..-1]
|
61
|
+
|
62
|
+
# Remove addition
|
63
|
+
erbout[erbout_length..-1] = ''
|
64
|
+
|
65
|
+
# Done
|
66
|
+
erbout_addition
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::Filtering provides a filter method, which allows parts of
|
6
|
+
# an item to be filtered.
|
7
|
+
#
|
8
|
+
# For example, the following piece of code only runs the "rubypants" filter
|
9
|
+
# on the second paragraph:
|
10
|
+
#
|
11
|
+
# <p>Lorem ipsum dolor sit amet...</p>
|
12
|
+
# <% filter :rubypants do %>
|
13
|
+
# <p>Consectetur adipisicing elit...</p>
|
14
|
+
# <% end %>
|
15
|
+
#
|
16
|
+
# This helper likely only works with ERB (and perhaps Erubis).
|
17
|
+
#
|
18
|
+
# To activate this helper, +include+ it, like this:
|
19
|
+
#
|
20
|
+
# include Nanoc3::Helpers::Filtering
|
21
|
+
module Filtering
|
22
|
+
|
23
|
+
require 'nanoc3/helpers/capturing'
|
24
|
+
include Nanoc3::Helpers::Capturing
|
25
|
+
|
26
|
+
# Filters the content in the given block and outputs it.
|
27
|
+
def filter(filter_name, arguments={}, &block)
|
28
|
+
# Capture block
|
29
|
+
data = capture(&block)
|
30
|
+
|
31
|
+
# Find filter
|
32
|
+
klass = Nanoc3::Filter.named(filter_name)
|
33
|
+
raise Nanoc3::Errors::UnknownFilter.new(filter_name) if klass.nil?
|
34
|
+
filter = klass.new(@item_rep.assigns)
|
35
|
+
|
36
|
+
# Filter captured data
|
37
|
+
filtered_data = filter.run(data, arguments)
|
38
|
+
|
39
|
+
# Append filtered data to buffer
|
40
|
+
buffer = eval('_erbout', block.binding)
|
41
|
+
buffer << filtered_data
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::HTMLEscape contains functionality for HTML-escaping
|
6
|
+
# strings.
|
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('&', '&').
|
13
|
+
gsub('<', '<').
|
14
|
+
gsub('>', '>').
|
15
|
+
gsub('"', '"')
|
16
|
+
end
|
17
|
+
|
18
|
+
alias h html_escape
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::LinkTo contains functions for linking to items.
|
6
|
+
#
|
7
|
+
# To activate this helper, +include+ it, like this:
|
8
|
+
#
|
9
|
+
# include Nanoc3::Helpers::LinkTo
|
10
|
+
module LinkTo
|
11
|
+
|
12
|
+
require 'nanoc3/helpers/html_escape'
|
13
|
+
include Nanoc3::Helpers::HTMLEscape
|
14
|
+
|
15
|
+
# Creates a HTML link to the given path or item representation, and with
|
16
|
+
# the given text.
|
17
|
+
#
|
18
|
+
# +path_or_rep+:: the URL or path (a String) that should be linked to, or
|
19
|
+
# the item representation that should be linked to.
|
20
|
+
#
|
21
|
+
# +text+:: the visible link text.
|
22
|
+
#
|
23
|
+
# +attributes+:: a hash containing HTML attributes that will be added to
|
24
|
+
# the link.
|
25
|
+
#
|
26
|
+
# Examples:
|
27
|
+
#
|
28
|
+
# link_to('Blog', '/blog/')
|
29
|
+
# # => '<a href="/blog/">Blog</a>'
|
30
|
+
#
|
31
|
+
# item_rep = @items.find { |i| i.item_id == 'special' }.reps[0]
|
32
|
+
# link_to('Special Item', item_rep)
|
33
|
+
# # => '<a href="/special_item/">Special Item</a>'
|
34
|
+
#
|
35
|
+
# link_to('Blog', '/blog/', :title => 'My super cool blog')
|
36
|
+
# # => '<a href="/blog/" title="My super cool blog">Blog</a>
|
37
|
+
def link_to(text, path_or_rep, attributes={})
|
38
|
+
# Find path
|
39
|
+
path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
|
40
|
+
|
41
|
+
# Join attributes
|
42
|
+
attributes = attributes.inject('') do |memo, (key, value)|
|
43
|
+
memo + key.to_s + '="' + h(value) + '" '
|
44
|
+
end
|
45
|
+
|
46
|
+
# Create link
|
47
|
+
"<a #{attributes}href=\"#{path}\">#{text}</a>"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates a HTML link using link_to, except when the linked item is the
|
51
|
+
# current one. In this case, a span element with class "active" and with
|
52
|
+
# the given text will be returned.
|
53
|
+
#
|
54
|
+
# Examples:
|
55
|
+
#
|
56
|
+
# link_to_unless_current('Blog', '/blog/')
|
57
|
+
# # => '<a href="/blog/">Blog</a>'
|
58
|
+
#
|
59
|
+
# link_to_unless_current('This Item', @item_rep)
|
60
|
+
# # => '<span class="active">This Item</span>'
|
61
|
+
def link_to_unless_current(text, path_or_rep, attributes={})
|
62
|
+
# Find path
|
63
|
+
path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
|
64
|
+
|
65
|
+
if @item_rep and @item_rep.path == path
|
66
|
+
# Create message
|
67
|
+
"<span class=\"active\" title=\"You're here.\">#{text}</span>"
|
68
|
+
else
|
69
|
+
link_to(text, path_or_rep, attributes)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the relative path from the current item to the given path or
|
74
|
+
# item representation.
|
75
|
+
#
|
76
|
+
# +path_or_rep+:: the URL or path (a String) to where the relative should
|
77
|
+
# point, or the item representation to which the relative
|
78
|
+
# should point.
|
79
|
+
#
|
80
|
+
# Example:
|
81
|
+
#
|
82
|
+
# # if the current item's path is /foo/bar/
|
83
|
+
# relative_path('/foo/qux/')
|
84
|
+
# # => '../qux/'
|
85
|
+
def relative_path_to(target)
|
86
|
+
require 'pathname'
|
87
|
+
|
88
|
+
# Find path
|
89
|
+
if target.is_a?(String)
|
90
|
+
path = target
|
91
|
+
elsif target.respond_to?(:reps)
|
92
|
+
path = target.reps.find { |r| r.name == :default }.path
|
93
|
+
else
|
94
|
+
path = target.path
|
95
|
+
end
|
96
|
+
|
97
|
+
# Get source and destination paths
|
98
|
+
dst_path = Pathname.new(path)
|
99
|
+
src_path = Pathname.new(@item_rep.path)
|
100
|
+
|
101
|
+
# Calculate elative path (method depends on whether destination is a
|
102
|
+
# directory or not).
|
103
|
+
if src_path.to_s[-1,1] != '/'
|
104
|
+
relative_path = dst_path.relative_path_from(src_path.dirname).to_s
|
105
|
+
else
|
106
|
+
relative_path = dst_path.relative_path_from(src_path).to_s
|
107
|
+
end
|
108
|
+
|
109
|
+
# Add trailing slash if necessary
|
110
|
+
if dst_path.to_s[-1,1] == '/'
|
111
|
+
relative_path += '/'
|
112
|
+
end
|
113
|
+
|
114
|
+
# Done
|
115
|
+
relative_path
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::Rendering provides functionality for rendering layouts as
|
6
|
+
# partials.
|
7
|
+
module Rendering
|
8
|
+
|
9
|
+
include Nanoc3::Helpers::Capturing
|
10
|
+
|
11
|
+
# Returns a string containing the rendered given layout.
|
12
|
+
#
|
13
|
+
# +identifier+:: the identifier of the layout that should be rendered.
|
14
|
+
#
|
15
|
+
# +other_assigns+:: a hash containing assigns that will be made available
|
16
|
+
# as instance variables.
|
17
|
+
#
|
18
|
+
# Example 1: a layout 'head' with content "HEAD" and a layout 'foot' with
|
19
|
+
# content "FOOT":
|
20
|
+
#
|
21
|
+
# <%= render 'head' %> - MIDDLE - <%= render 'foot' %>
|
22
|
+
# # => "HEAD - MIDDLE - FOOT"
|
23
|
+
#
|
24
|
+
# Example 2: a layout named 'head' with content "<h1><%= @title %></h1>":
|
25
|
+
#
|
26
|
+
# <%= render 'head', :title => 'Foo' %>
|
27
|
+
# # => "<h1>Foo</h1>"
|
28
|
+
def render(identifier, other_assigns={}, &block)
|
29
|
+
# Find layout
|
30
|
+
layout = @site.layouts.find { |l| l.identifier == identifier.cleaned_identifier }
|
31
|
+
raise Nanoc3::Errors::UnknownLayout.new(identifier.cleaned_identifier) if layout.nil?
|
32
|
+
|
33
|
+
# Capture content, if any
|
34
|
+
captured_content = block_given? ? capture(&block) : nil
|
35
|
+
|
36
|
+
# Get assigns
|
37
|
+
assigns = {
|
38
|
+
:content => captured_content,
|
39
|
+
:item => @item,
|
40
|
+
:item_rep => @item_rep,
|
41
|
+
:items => @items,
|
42
|
+
:layout => layout,
|
43
|
+
:layouts => @layouts,
|
44
|
+
:config => @config,
|
45
|
+
:site => @site
|
46
|
+
}.merge(other_assigns)
|
47
|
+
|
48
|
+
# Get filter name
|
49
|
+
filter_name, filter_args = @site.compiler.filter_for_layout(layout)
|
50
|
+
raise Nanoc3::Errors::CannotDetermineFilter.new(layout.identifier) if filter_name.nil?
|
51
|
+
|
52
|
+
# Get filter class
|
53
|
+
filter_class = Nanoc3::Filter.named(filter_name)
|
54
|
+
raise Nanoc3::Errors::UnknownFilter.new(filter_name) if filter_class.nil?
|
55
|
+
|
56
|
+
# Create filter
|
57
|
+
filter = filter_class.new(assigns)
|
58
|
+
|
59
|
+
# Layout
|
60
|
+
@site.compiler.stack.push(layout)
|
61
|
+
result = filter.run(layout.raw_content, filter_args)
|
62
|
+
@site.compiler.stack.pop
|
63
|
+
|
64
|
+
# Append to erbout if we have a block
|
65
|
+
if block_given?
|
66
|
+
erbout = eval('_erbout', block.binding)
|
67
|
+
erbout << result
|
68
|
+
end
|
69
|
+
|
70
|
+
# Done
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3::Helpers
|
4
|
+
|
5
|
+
# Nanoc3::Helpers::Tagging provides some support for managing tags added to
|
6
|
+
# items. To add tags to items, set the +tags+ attribute to an array of
|
7
|
+
# tags that should be applied to the item. For example:
|
8
|
+
#
|
9
|
+
# tags: [ 'foo', 'bar', 'baz' ]
|
10
|
+
#
|
11
|
+
# To activate this helper, +include+ it, like this:
|
12
|
+
#
|
13
|
+
# include Nanoc3::Helpers::Tagging
|
14
|
+
module Tagging
|
15
|
+
|
16
|
+
# Returns a formatted list of tags for the given item as a string. Several
|
17
|
+
# parameters allow customization:
|
18
|
+
#
|
19
|
+
# :base_url:: The URL to which the tag will be appended to construct the
|
20
|
+
# link URL. This URL must have a trailing slash. Defaults to
|
21
|
+
# "http://technorati.com/tag/".
|
22
|
+
#
|
23
|
+
# :none_text:: The text to display when the item has no tags. Defaults to
|
24
|
+
# "(none)".
|
25
|
+
#
|
26
|
+
# :separator:: The separator to put between tags. Defaults to ", ".
|
27
|
+
def tags_for(item, params={})
|
28
|
+
base_url = params[:base_url] || 'http://technorati.com/tag/'
|
29
|
+
none_text = params[:none_text] || '(none)'
|
30
|
+
separator = params[:separator] || ', '
|
31
|
+
|
32
|
+
if item[:tags].nil? or item[:tags].empty?
|
33
|
+
none_text
|
34
|
+
else
|
35
|
+
item[:tags].map { |tag| link_for_tag(tag, base_url) }.join(separator)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns all items with the given tag.
|
40
|
+
def items_with_tag(tag)
|
41
|
+
@items.select { |i| (i[:tags] || []).include?(tag) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns a link to to the specified tag. The link is marked up using the
|
45
|
+
# rel-tag microformat.
|
46
|
+
#
|
47
|
+
# +tag+:: The name of the tag, which should consist of letters and numbers
|
48
|
+
# (no spaces, slashes, or other special characters).
|
49
|
+
#
|
50
|
+
# +base_url+:: The URL to which the tag will be appended to construct the
|
51
|
+
# link URL. This URL must have a trailing slash.
|
52
|
+
def link_for_tag(tag, base_url)
|
53
|
+
%[<a href="#{base_url}#{tag}" rel="tag">#{tag}</a>]
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|