nanoc3 3.0.1 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS.rdoc +7 -0
- data/lib/nanoc3.rb +1 -1
- data/lib/nanoc3/base/compiler.rb.orig +250 -0
- data/lib/nanoc3/base/compiler_dsl.rb +6 -1
- data/lib/nanoc3/base/item.rb +3 -3
- data/lib/nanoc3/cli/commands/create_site.rb +3 -3
- data/lib/nanoc3/package.rb +1 -0
- metadata +4 -2
data/NEWS.rdoc
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= nanoc News
|
2
2
|
|
3
|
+
== 3.0.2
|
4
|
+
|
5
|
+
* Children-only identifier patterns no longer erroneously also match parent
|
6
|
+
(e.g. /foo/*/ no longer matches /foo/)
|
7
|
+
* The create_site command no longer uses those ugly HTML entities
|
8
|
+
* Install message now mentions the IRC channel
|
9
|
+
|
3
10
|
== 3.0.1
|
4
11
|
|
5
12
|
* The proper exception is now raised when no matching compilation rules can
|
data/lib/nanoc3.rb
CHANGED
@@ -0,0 +1,250 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nanoc3
|
4
|
+
|
5
|
+
# Nanoc3::Compiler is responsible for compiling a site's item
|
6
|
+
# representations.
|
7
|
+
class Compiler
|
8
|
+
|
9
|
+
# The compilation stack. When the compiler begins compiling a rep or a
|
10
|
+
# layout, it will be placed on the stack; when it is done compiling the
|
11
|
+
# rep or layout, it will be removed from the stack.
|
12
|
+
attr_reader :stack
|
13
|
+
|
14
|
+
# The list of compilation rules that will be used to compile items. This
|
15
|
+
# array will be filled by Nanoc3::Site#load_data.
|
16
|
+
attr_reader :item_compilation_rules
|
17
|
+
|
18
|
+
# The list of routing rules that will be used to give all items a path.
|
19
|
+
# This array will be filled by Nanoc3::Site#load_data.
|
20
|
+
attr_reader :item_routing_rules
|
21
|
+
|
22
|
+
# The hash containing layout-to-filter mapping rules.
|
23
|
+
attr_reader :layout_filter_mapping
|
24
|
+
|
25
|
+
# Creates a new compiler for the given site.
|
26
|
+
def initialize(site)
|
27
|
+
@site = site
|
28
|
+
|
29
|
+
@stack = []
|
30
|
+
|
31
|
+
@item_compilation_rules = []
|
32
|
+
@item_routing_rules = []
|
33
|
+
@layout_filter_mapping = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Compiles (part of) the site and writes out the compiled item
|
37
|
+
# representations.
|
38
|
+
#
|
39
|
+
# +items+:: The items that should be compiled, along with their
|
40
|
+
# dependencies. Pass +nil+ if the entire site should be
|
41
|
+
# compiled.
|
42
|
+
#
|
43
|
+
# This method also accepts a few optional parameters:
|
44
|
+
#
|
45
|
+
# +:force+:: true if the rep should be compiled even if it is not
|
46
|
+
# outdated, false if not. Defaults to false.
|
47
|
+
def run(item=nil, params={})
|
48
|
+
# Create output directory if necessary
|
49
|
+
FileUtils.mkdir_p(@site.config[:output_dir])
|
50
|
+
|
51
|
+
# Load dependencies
|
52
|
+
dependency_tracker.load_graph
|
53
|
+
print_dependency_graph if $DEBUG
|
54
|
+
|
55
|
+
# Get items and reps to compile
|
56
|
+
if item
|
57
|
+
items = [ item ] + dependency_tracker.all_inverse_dependencies_for(item)
|
58
|
+
items.uniq!
|
59
|
+
else
|
60
|
+
items = @site.items
|
61
|
+
end
|
62
|
+
reps = items.map { |i| i.reps }.flatten
|
63
|
+
|
64
|
+
# Prepare dependencies
|
65
|
+
remember_old_dependencies
|
66
|
+
@old_dep_graph = dependency_tracker.instance_eval { @graph }.dup
|
67
|
+
mark_outdated_items(reps, params.has_key?(:force) && params[:force])
|
68
|
+
forget_dependencies_if_outdated(items)
|
69
|
+
|
70
|
+
# Compile reps
|
71
|
+
dependency_tracker.start
|
72
|
+
compile_reps(reps)
|
73
|
+
dependency_tracker.stop
|
74
|
+
|
75
|
+
# Store dependencies
|
76
|
+
dependency_tracker.store_graph
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the first matching compilation rule for the given rep.
|
80
|
+
def compilation_rule_for(rep)
|
81
|
+
@item_compilation_rules.find do |rule|
|
82
|
+
rule.applicable_to?(rep.item) && rule.rep_name == rep.name
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the first matching routing rule for the given rep.
|
87
|
+
def routing_rule_for(rep)
|
88
|
+
@item_routing_rules.find do |rule|
|
89
|
+
rule.applicable_to?(rep.item) && rule.rep_name == rep.name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a tuple containing the filter name and the filter arguments for
|
94
|
+
# the given layout.
|
95
|
+
def filter_for_layout(layout)
|
96
|
+
@layout_filter_mapping.each_pair do |layout_identifier, filter_name_and_args|
|
97
|
+
return filter_name_and_args if layout.identifier =~ layout_identifier
|
98
|
+
end
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# Compiles all item representations in the site.
|
105
|
+
def compile_reps(reps)
|
106
|
+
active_reps, skipped_reps = reps.partition { |rep| rep.outdated? || rep.item.dependencies_outdated? }
|
107
|
+
inactive_reps = []
|
108
|
+
compiled_reps = []
|
109
|
+
|
110
|
+
# Repeat as long as something is successfully compiled...
|
111
|
+
changed = true
|
112
|
+
until !changed
|
113
|
+
changed = false
|
114
|
+
|
115
|
+
# Sort by increasing number of inverse dependencies to speed up compilation
|
116
|
+
#active_reps = active_reps.sort_by { |r| dependency_tracker.all_dependencies_for(r.item).size }
|
117
|
+
# 10.times { puts '=' * 80 }
|
118
|
+
# active_reps.each do |r|
|
119
|
+
# puts r.item.identifier + ' => ' + dependency_tracker.all_dependencies_for(r.item).size.to_s
|
120
|
+
# end
|
121
|
+
# 10.times { puts '=' * 80 }
|
122
|
+
|
123
|
+
# Attempt to compile all active reps
|
124
|
+
until active_reps.empty?
|
125
|
+
@stack.clear
|
126
|
+
begin
|
127
|
+
rep = active_reps.shift
|
128
|
+
puts "*** Attempting to compile #{rep.inspect}" if $DEBUG
|
129
|
+
|
130
|
+
@stack.push(rep)
|
131
|
+
compile_rep(rep)
|
132
|
+
rescue Nanoc3::Errors::UnmetDependency => e
|
133
|
+
puts "*** Attempt failed due to unmet dependency on #{e.rep.inspect}" if $DEBUG
|
134
|
+
|
135
|
+
# Save rep to compile it later
|
136
|
+
inactive_reps << rep
|
137
|
+
|
138
|
+
# Add dependency to list of items to compile
|
139
|
+
unless active_reps.include?(e.rep) || inactive_reps.include?(e.rep)
|
140
|
+
changed = true
|
141
|
+
skipped_reps.delete(e.rep)
|
142
|
+
inactive_reps.unshift(e.rep)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Assume that this page has more dependencies and add those
|
146
|
+
@old_dependencies[rep.item].each do |i|
|
147
|
+
i.reps.each do |r|
|
148
|
+
next if active_reps.include?(r)
|
149
|
+
next if compiled_reps.include?(r)
|
150
|
+
next if inactive_reps.include?(r)
|
151
|
+
|
152
|
+
inactive_reps.unshift(r)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
else
|
156
|
+
puts "*** Attempt succeeded" if $DEBUG
|
157
|
+
|
158
|
+
changed = true
|
159
|
+
compiled_reps << rep
|
160
|
+
end
|
161
|
+
puts if $DEBUG
|
162
|
+
end
|
163
|
+
|
164
|
+
# Retry
|
165
|
+
puts "*** No active reps left; activating all (#{inactive_reps.size}) inactive reps" if $DEBUG
|
166
|
+
puts if $DEBUG
|
167
|
+
active_reps = inactive_reps
|
168
|
+
inactive_reps = []
|
169
|
+
end
|
170
|
+
|
171
|
+
# Notify skipped reps
|
172
|
+
skipped_reps.each do |rep|
|
173
|
+
Nanoc3::NotificationCenter.post(:compilation_started, rep)
|
174
|
+
Nanoc3::NotificationCenter.post(:compilation_ended, rep)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Raise error if some active but non-compileable reps are left
|
178
|
+
if !active_reps.empty?
|
179
|
+
raise Nanoc3::Errors::RecursiveCompilation.new(active_reps)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Compiles the given item representation.
|
184
|
+
#
|
185
|
+
# This method should not be called directly; please use
|
186
|
+
# Nanoc3::Compiler#run instead, and pass this item representation's item as
|
187
|
+
# its first argument.
|
188
|
+
#
|
189
|
+
# +rep+:: The rep that is to be compiled.
|
190
|
+
def compile_rep(rep)
|
191
|
+
# Start
|
192
|
+
Nanoc3::NotificationCenter.post(:compilation_started, rep)
|
193
|
+
Nanoc3::NotificationCenter.post(:visit_started, rep.item)
|
194
|
+
|
195
|
+
# Apply matching rule
|
196
|
+
compilation_rule_for(rep).apply_to(rep)
|
197
|
+
rep.compiled = true
|
198
|
+
|
199
|
+
# Write if rep is routed
|
200
|
+
rep.write unless rep.raw_path.nil?
|
201
|
+
|
202
|
+
# Stop
|
203
|
+
Nanoc3::NotificationCenter.post(:visit_ended, rep.item)
|
204
|
+
Nanoc3::NotificationCenter.post(:compilation_ended, rep)
|
205
|
+
end
|
206
|
+
|
207
|
+
# Returns the dependency tracker for this site.
|
208
|
+
def dependency_tracker
|
209
|
+
@dependency_tracker ||= Nanoc3::DependencyTracker.new(@site.items)
|
210
|
+
end
|
211
|
+
|
212
|
+
# Marks the necessary items as outdated.
|
213
|
+
def mark_outdated_items(reps, force)
|
214
|
+
if force
|
215
|
+
reps.each { |r| r.force_outdated = true }
|
216
|
+
else
|
217
|
+
dependency_tracker.mark_outdated_items
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Clears the list of dependencies for items that will be recompiled.
|
222
|
+
def forget_dependencies_if_outdated(items)
|
223
|
+
items.each do |i|
|
224
|
+
if i.outdated? || i.dependencies_outdated?
|
225
|
+
dependency_tracker.forget_dependencies_for(i)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def remember_old_dependencies
|
231
|
+
@old_dependencies = dependency_tracker.instance_eval { @graph }.dup
|
232
|
+
end
|
233
|
+
|
234
|
+
# Prints the dependency graph.
|
235
|
+
def print_dependency_graph
|
236
|
+
graph = dependency_tracker.instance_eval { @graph }
|
237
|
+
puts "DEPENDENCY GRAPH:"
|
238
|
+
graph.each_pair do |key, values|
|
239
|
+
puts "#{key.inspect} depends on:"
|
240
|
+
values.each do |value|
|
241
|
+
puts " #{value.inspect}"
|
242
|
+
end
|
243
|
+
puts " (nothing!)" if values.empty?
|
244
|
+
puts
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
@@ -99,7 +99,12 @@ module Nanoc3
|
|
99
99
|
# For example, 'foo/*/bar' is transformed into /^foo\/(.*?)\/bar$/.
|
100
100
|
def identifier_to_regex(identifier)
|
101
101
|
if identifier.is_a? String
|
102
|
-
|
102
|
+
# Add leading/trailing slashes if necessary
|
103
|
+
new_identifier = identifier.dup
|
104
|
+
new_identifier[/^/] = '/' if identifier[0,1] != '/'
|
105
|
+
new_identifier[/$/] = '/' unless [ '*', '/' ].include?(identifier[-1,1])
|
106
|
+
|
107
|
+
/^#{new_identifier.gsub('*', '(.*?)')}$/
|
103
108
|
else
|
104
109
|
identifier
|
105
110
|
end
|
data/lib/nanoc3/base/item.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module Nanoc3
|
4
4
|
|
5
|
-
# Nanoc3::Item
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Nanoc3::Item represents a compileable item in a site. It has content and
|
6
|
+
# attributes, as well as an identifier. It can also store the modification
|
7
|
+
# time to speed up compilation.
|
8
8
|
class Item
|
9
9
|
|
10
10
|
# The Nanoc3::Site this item belongs to.
|
@@ -7,13 +7,13 @@ module Nanoc3::CLI::Commands
|
|
7
7
|
DEFAULT_ITEM = <<EOS
|
8
8
|
<h1>A Brand New nanoc Site</h1>
|
9
9
|
|
10
|
-
<p>You
|
10
|
+
<p>You’ve just created a new nanoc site. The page you are looking at right now is the home page for your site (and it’s probably the only page).</p>
|
11
11
|
|
12
12
|
<p>To get started, consider replacing this default homepage with your own customized homepage. Some pointers on how to do so:</p>
|
13
13
|
|
14
14
|
<ul>
|
15
|
-
<li><p><strong>Change this page
|
16
|
-
<li><p><strong>Change the layout</strong>, which is the
|
15
|
+
<li><p><strong>Change this page’s content</strong> by editing “content.html” file in the “content” directory. This is the actual page content, and therefore doesn’t include the header, sidebar or style information (those are part of the layout).</p></li>
|
16
|
+
<li><p><strong>Change the layout</strong>, which is the “default.txt” file in the “layouts/default” directory, and create something unique (and hopefully less bland).</p></li>
|
17
17
|
</ul>
|
18
18
|
|
19
19
|
<p>If you need any help with customizing your nanoc web site, be sure to check out the documentation (see sidebar), and be sure to subscribe to the discussion group (also see sidebar). Enjoy!</p>
|
data/lib/nanoc3/package.rb
CHANGED
@@ -76,6 +76,7 @@ Thanks for installing nanoc 3.0! Here are some resources to help you get started
|
|
76
76
|
* The tutorial at <http://nanoc.stoneship.org/tutorial/>
|
77
77
|
* The manual at <http://nanoc.stoneship.org/manual/>
|
78
78
|
* The discussion group at <http://groups.google.com/group/nanoc>
|
79
|
+
* The IRC channel #nanoc on Freenode
|
79
80
|
|
80
81
|
Because nanoc 3.0 has a lot of new features, be sure to check out the nanoc blog at <http://nanoc.stoneship.org/blog/> for details about this release.
|
81
82
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nanoc3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Defreyne
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-11-07 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- bin/nanoc3
|
36
36
|
- lib/nanoc3/base/code_snippet.rb
|
37
37
|
- lib/nanoc3/base/compiler.rb
|
38
|
+
- lib/nanoc3/base/compiler.rb.orig
|
38
39
|
- lib/nanoc3/base/compiler_dsl.rb
|
39
40
|
- lib/nanoc3/base/core_ext/array.rb
|
40
41
|
- lib/nanoc3/base/core_ext/hash.rb
|
@@ -153,6 +154,7 @@ post_install_message: |
|
|
153
154
|
* The tutorial at <http://nanoc.stoneship.org/tutorial/>
|
154
155
|
* The manual at <http://nanoc.stoneship.org/manual/>
|
155
156
|
* The discussion group at <http://groups.google.com/group/nanoc>
|
157
|
+
* The IRC channel #nanoc on Freenode
|
156
158
|
|
157
159
|
Because nanoc 3.0 has a lot of new features, be sure to check out the nanoc blog at <http://nanoc.stoneship.org/blog/> for details about this release.
|
158
160
|
|