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 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
@@ -3,7 +3,7 @@
3
3
  module Nanoc3
4
4
 
5
5
  # The current nanoc version.
6
- VERSION = '3.0.1'
6
+ VERSION = '3.0.2'
7
7
 
8
8
  end
9
9
 
@@ -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
- /^#{identifier.cleaned_identifier.gsub('*', '(.*?)')}?$/
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
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Nanoc3
4
4
 
5
- # Nanoc3::Item is represents all compileable items in a site. It has content
6
- # and attributes, as well as an identifier. It can also store the
7
- # modification time to speed up compilation.
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&#8217;ve just created a new nanoc site. The page you are looking at right now is the home page for your site (and it&#8217;s probably the only page).</p>
10
+ <p>Youve just created a new nanoc site. The page you are looking at right now is the home page for your site (and its 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&#8217;s content</strong> by editing &#8220;content.html&#8221; file in the &#8220;content&#8221; directory. This is the actual page content, and therefore doesn&#8217;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 &#8220;default.txt&#8221; file in the &#8220;layouts/default&#8221; directory, and create something unique (and hopefully less bland).</p></li>
15
+ <li><p><strong>Change this pages content</strong> by editing content.html file in the content directory. This is the actual page content, and therefore doesnt 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>
@@ -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.1
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-10-05 00:00:00 +02:00
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