webgen 1.0.0.beta1 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/API.rdoc +64 -11
  2. data/ChangeLog +391 -0
  3. data/README.md +2 -2
  4. data/VERSION +1 -1
  5. data/data/webgen/passive_sources/templates/tag.template +1 -1
  6. data/data/webgen/passive_sources/templates/tikz.template +14 -0
  7. data/lib/webgen/bundle/built-in/init.rb +9 -7
  8. data/lib/webgen/bundle_loader.rb +1 -1
  9. data/lib/webgen/cli/show_command.rb +2 -0
  10. data/lib/webgen/cli/show_config_command.rb +0 -1
  11. data/lib/webgen/cli/show_dependencies_command.rb +6 -63
  12. data/lib/webgen/cli/show_tree_command.rb +85 -0
  13. data/lib/webgen/content_processor/erb.rb +1 -1
  14. data/lib/webgen/content_processor/{rdoc.rb → r_doc.rb} +0 -0
  15. data/lib/webgen/content_processor/{redcloth.rb → red_cloth.rb} +0 -0
  16. data/lib/webgen/content_processor/ruby.rb +3 -0
  17. data/lib/webgen/content_processor/sass.rb +10 -6
  18. data/lib/webgen/content_processor/tikz.rb +10 -20
  19. data/lib/webgen/context/html_head.rb +7 -0
  20. data/lib/webgen/item_tracker.rb +42 -15
  21. data/lib/webgen/item_tracker/file.rb +7 -3
  22. data/lib/webgen/item_tracker/missing_node.rb +17 -5
  23. data/lib/webgen/item_tracker/node_content.rb +7 -3
  24. data/lib/webgen/item_tracker/node_meta_info.rb +8 -3
  25. data/lib/webgen/item_tracker/nodes.rb +10 -3
  26. data/lib/webgen/node.rb +4 -29
  27. data/lib/webgen/node_finder.rb +25 -10
  28. data/lib/webgen/path.rb +2 -2
  29. data/lib/webgen/path_handler/base.rb +20 -9
  30. data/lib/webgen/path_handler/feed.rb +29 -22
  31. data/lib/webgen/path_handler/page.rb +1 -3
  32. data/lib/webgen/path_handler/page_utils.rb +114 -33
  33. data/lib/webgen/path_handler/sitemap.rb +13 -6
  34. data/lib/webgen/path_handler/template.rb +0 -70
  35. data/lib/webgen/path_handler/virtual.rb +10 -2
  36. data/lib/webgen/tag.rb +13 -13
  37. data/lib/webgen/tag/tikz.rb +2 -1
  38. data/lib/webgen/test_helper.rb +2 -11
  39. data/lib/webgen/version.rb +1 -1
  40. data/test/webgen/content_processor/test_erb.rb +4 -0
  41. data/test/webgen/content_processor/{test_rdoc.rb → test_r_doc.rb} +1 -1
  42. data/test/webgen/content_processor/{test_redcloth.rb → test_red_cloth.rb} +1 -1
  43. data/test/webgen/content_processor/test_sass.rb +2 -2
  44. data/test/webgen/content_processor/test_tikz.rb +10 -3
  45. data/test/webgen/item_tracker/test_file.rb +5 -5
  46. data/test/webgen/item_tracker/test_missing_node.rb +8 -9
  47. data/test/webgen/item_tracker/test_node_content.rb +5 -6
  48. data/test/webgen/item_tracker/test_node_meta_info.rb +6 -7
  49. data/test/webgen/item_tracker/test_nodes.rb +7 -9
  50. data/test/webgen/path_handler/test_base.rb +4 -5
  51. data/test/webgen/path_handler/test_page.rb +1 -1
  52. data/test/webgen/path_handler/test_page_utils.rb +39 -11
  53. data/test/webgen/path_handler/test_template.rb +5 -45
  54. data/test/webgen/path_handler/test_virtual.rb +21 -0
  55. data/test/webgen/tag/test_link.rb +1 -1
  56. data/test/webgen/tag/test_tikz.rb +2 -2
  57. data/test/webgen/test_context.rb +10 -0
  58. data/test/webgen/test_item_tracker.rb +7 -4
  59. data/test/webgen/test_node.rb +3 -16
  60. data/test/webgen/test_node_finder.rb +10 -6
  61. data/test/webgen/test_tag.rb +4 -4
  62. metadata +218 -216
@@ -32,7 +32,7 @@ module Webgen
32
32
  # [item_data(*item)]
33
33
  # Return the data for the item so that it can be correctly checked later if it has changed.
34
34
  #
35
- # [changed?(item_id, old_data)]
35
+ # [item_changed?(item_id, old_data)]
36
36
  # Return +true+ if the item identified by its unique ID has changed. The parameter +old_data+
37
37
  # contains the last known data of the item.
38
38
  #
@@ -40,6 +40,11 @@ module Webgen
40
40
  # Return +true+ if the node identified by +node_alcn+ is referenced in the old data identified
41
41
  # by the unique ID.
42
42
  #
43
+ # [item_description(item_id, data)]
44
+ # Return a string or an array of strings which describe the item (identified by its unique ID)
45
+ # and the given item data. This is used for display purposes and should therefore include a
46
+ # nice, human readable interpretation of the item.
47
+ #
43
48
  # The parameter +item+ for the methods +item_id+ and +item_data+ contains the information needed
44
49
  # to identify the item and is depdendent on the specific item tracker extension class. Therefore
45
50
  # you need to look at the documentation for an item tracker extension to see what it expects as
@@ -67,7 +72,7 @@ module Webgen
67
72
  # @website.config[config_key]
68
73
  # end
69
74
  #
70
- # def changed?(config_key, old_val)
75
+ # def item_changed?(config_key, old_val)
71
76
  # @website.config[config_key] != old_val
72
77
  # end
73
78
  #
@@ -75,6 +80,10 @@ module Webgen
75
80
  # false
76
81
  # end
77
82
  #
83
+ # def item_description(config_key, old_val)
84
+ # "The website configuration option '#{config_key}'"
85
+ # end
86
+ #
78
87
  # end
79
88
  #
80
89
  # website.ext.item_tracker.register ConfigTracker, name: :config
@@ -134,10 +143,11 @@ module Webgen
134
143
 
135
144
  @website.blackboard.add_listener(:website_generated, self) do
136
145
  @cached[:node_dependencies].reject! {|alcn, data| !@website.tree[alcn]}
146
+
147
+ used_uids = @cached[:node_dependencies].each_with_object(Set.new) {|(_, uids), obj| obj.merge(uids)}
137
148
  @cached[:item_data].merge!(@item_data)
138
- @cached[:item_data].reject! do |uid, _|
139
- !@cached[:node_dependencies].find {|alcn, data| data.include?(uid)}
140
- end
149
+ @cached[:item_data].reject! {|uid, _| !used_uids.include?(uid)}
150
+
141
151
  @website.cache[:item_tracker_data] = @cached
142
152
  end
143
153
  end
@@ -187,17 +197,16 @@ module Webgen
187
197
 
188
198
  # Return +true+ if the given node has been referenced by any item tracker extension.
189
199
  def node_referenced?(node)
190
- node_alcn = node.alcn
191
- checked_uids = Set.new
192
- @cached[:node_dependencies].each do |alcn, uids|
193
- next if alcn == node_alcn
194
- uids.each do |uid|
195
- next if checked_uids.include?(uid)
196
- checked_uids << uid
197
- return true if item_tracker(uid.first).node_referenced?(uid.last, @cached[:item_data][uid], node_alcn)
200
+ if (cached = @website.cache.volatile[:item_tracker_referenced_nodes]).nil?
201
+ cached = @website.cache.volatile[:item_tracker_referenced_nodes] = Set.new
202
+ @cached[:node_dependencies].each do |alcn, uids|
203
+ uids.each do |uid|
204
+ cached.merge(item_tracker(uid.first).referenced_nodes(uid.last, @cached[:item_data][uid]) - [alcn])
205
+ end
198
206
  end
199
207
  end
200
- false
208
+
209
+ cached.include?(node.alcn)
201
210
  end
202
211
 
203
212
  # Return +true+ if the given item that is handled by the item tracker extension +name+ has
@@ -206,6 +215,24 @@ module Webgen
206
215
  item_changed_by_uid?(unique_id(name, item))
207
216
  end
208
217
 
218
+ # Return a hash with mappings from node ALCNs to their used items (items are converted to
219
+ # a human readable representation by using the #item_description method).
220
+ #
221
+ # If the parameter +include_default+ is set to +false+, the default items added to each node so
222
+ # that it is possible to correctly detect changes, are not included.
223
+ #
224
+ # The cached data, not the current data, is used. So this information is only useful after a
225
+ # website has been generated.
226
+ def cached_items(include_default=true)
227
+ @cached[:node_dependencies].each_with_object({}) do |(alcn, uids), h|
228
+ h[alcn] = uids.sort {|a,b| a.first <=> b.first }.map do |uid|
229
+ next if !include_default && ((uid.first == :node_meta_info && uid.last.first == alcn )||
230
+ (uid.first == :node_content && uid.last == alcn))
231
+ item_tracker(uid.first).item_description(uid.last, @cached[:item_data][uid])
232
+ end.compact
233
+ end
234
+ end
235
+
209
236
  #######
210
237
  private
211
238
  #######
@@ -217,7 +244,7 @@ module Webgen
217
244
  @item_changed[uid] = if !@cached[:item_data].has_key?(uid)
218
245
  true
219
246
  else
220
- item_tracker(uid.first).changed?(uid.last, @cached[:item_data][uid])
247
+ item_tracker(uid.first).item_changed?(uid.last, @cached[:item_data][uid])
221
248
  end
222
249
  end
223
250
 
@@ -25,12 +25,16 @@ module Webgen
25
25
  ::File.mtime(filename)
26
26
  end
27
27
 
28
- def changed?(filename, old_mtime) #:nodoc:
28
+ def item_changed?(filename, old_mtime) #:nodoc:
29
29
  ::File.mtime(filename) > old_mtime
30
30
  end
31
31
 
32
- def node_referenced?(filename, mtime, node_alcn) #:nodoc:
33
- false
32
+ def referenced_nodes(filename, mtime) #:nodoc:
33
+ []
34
+ end
35
+
36
+ def item_description(filename, data) #:nodoc:
37
+ "Content from file '#{filename}'"
34
38
  end
35
39
 
36
40
  end
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ require 'set'
3
4
  require 'webgen/item_tracker'
4
5
 
5
6
  module Webgen
@@ -20,9 +21,13 @@ module Webgen
20
21
  @website = website
21
22
  @at_least_one_node_created = true
22
23
  @stop_reporting = false
24
+ @nodes_to_ignore = Set.new
23
25
 
24
- @website.blackboard.add_listener(:after_node_created, self) do
25
- @at_least_one_node_created = true
26
+ @website.blackboard.add_listener(:reused_existing_node, self) do |node, path|
27
+ @nodes_to_ignore << node
28
+ end
29
+ @website.blackboard.add_listener(:after_node_created, self) do |node|
30
+ @at_least_one_node_created = true unless @nodes_to_ignore.include?(node)
26
31
  end
27
32
  @website.blackboard.add_listener(:after_all_nodes_written, self) do
28
33
  if @at_least_one_node_created
@@ -30,10 +35,12 @@ module Webgen
30
35
  else
31
36
  @stop_reporting = true
32
37
  end
38
+ @nodes_to_ignore = Set.new
33
39
  end
34
40
  @website.blackboard.add_listener(:website_generated, self) do
35
41
  @at_least_one_node_created = true
36
42
  @stop_reporting = false
43
+ @nodes_to_ignore = Set.new
37
44
  end
38
45
  end
39
46
 
@@ -45,14 +52,19 @@ module Webgen
45
52
  @website.tree.resolve_node(path, lang).nil?
46
53
  end
47
54
 
48
- def changed?(iid, old_data) #:nodoc:
55
+ def item_changed?(iid, old_data) #:nodoc:
49
56
  return false if @stop_reporting
50
57
  missing = item_data(*iid)
51
58
  missing || missing != old_data
52
59
  end
53
60
 
54
- def node_referenced?(iid, missing, node_alcn) #:nodoc:
55
- iid.first == node_alcn
61
+ def referenced_nodes(iid, missing) #:nodoc:
62
+ [iid.first]
63
+ end
64
+
65
+ def item_description(iid, data) #:nodoc:
66
+ path, lang = *iid.last
67
+ "Missing acn, alcn or dest path <#{path}>" << (lang.nil? ? '' : " in language '#{lang}'")
56
68
  end
57
69
 
58
70
  end
@@ -26,12 +26,16 @@ module Webgen
26
26
  nil
27
27
  end
28
28
 
29
- def changed?(alcn, old_data) #:nodoc:
29
+ def item_changed?(alcn, old_data) #:nodoc:
30
30
  @website.tree[alcn].nil? || @website.ext.item_tracker.node_changed?(@website.tree[alcn])
31
31
  end
32
32
 
33
- def node_referenced?(alcn, nothing, node_alcn) #:nodoc:
34
- alcn == node_alcn
33
+ def referenced_nodes(alcn, nothing) #:nodoc:
34
+ [alcn]
35
+ end
36
+
37
+ def item_description(alcn, data) #:nodoc:
38
+ "Content from node <#{alcn}>"
35
39
  end
36
40
 
37
41
  end
@@ -38,13 +38,18 @@ module Webgen
38
38
  key.nil? ? (mi = mi.dup; mi.delete(CONTENT_MODIFICATION_KEY); mi) : mi[key].dup
39
39
  end
40
40
 
41
- def changed?(iid, old_data) #:nodoc:
41
+ def item_changed?(iid, old_data) #:nodoc:
42
42
  alcn, key = *iid
43
43
  @website.tree[alcn].nil? || item_data(alcn, key) != old_data
44
44
  end
45
45
 
46
- def node_referenced?(iid, mi, node_alcn) #:nodoc:
47
- iid.first == node_alcn
46
+ def referenced_nodes(iid, mi) #:nodoc:
47
+ [iid.first]
48
+ end
49
+
50
+ def item_description(iid, data) #:nodoc:
51
+ alcn, key = *iid
52
+ (key.nil? ? "Any meta info from <#{alcn}>" : "Meta info key '#{key}' from <#{alcn}>")
48
53
  end
49
54
 
50
55
  end
@@ -47,15 +47,22 @@ module Webgen
47
47
  nodes_to_alcn(node_list(method_name, options))
48
48
  end
49
49
 
50
- def changed?(iid, old_data) #:nodoc:
50
+ def item_changed?(iid, old_data) #:nodoc:
51
51
  method_name, options, type = *iid
52
52
  nodes = node_list(method_name, options)
53
53
  old_data != nodes_to_alcn(nodes) ||
54
54
  nodes.flatten.any? {|n| type == :content ? @website.ext.item_tracker.node_changed?(n) : @website.ext.item_tracker.item_changed?(:node_meta_info, n.alcn)}
55
55
  end
56
56
 
57
- def node_referenced?(iid, alcn_list, node_alcn) #:nodoc:
58
- alcn_list.flatten.any? {|alcn| alcn == node_alcn}
57
+ def referenced_nodes(iid, alcn_list) #:nodoc:
58
+ alcn_list.flatten
59
+ end
60
+
61
+ def item_description(iid, data) #:nodoc:
62
+ method, _, type = *iid
63
+ str = (type == :content ? "Content" : "Meta info") << " from these nodes"
64
+ str << " (result of #{[method].flatten.join('.')}):"
65
+ [str] + data.flatten
59
66
  end
60
67
 
61
68
  # Use Webgen::NodeFinder to generate a (nested) list of nodes. The options hash has to contain
data/lib/webgen/node.rb CHANGED
@@ -200,16 +200,14 @@ module Webgen
200
200
  # You can optionally specify additional attributes for the HTML element in the +attr+ Hash.
201
201
  # Also, the meta information +link_attrs+ of the given +node+ is used, if available, to set
202
202
  # attributes. However, the +attr+ parameter takes precedence over the +link_attrs+ meta
203
- # information. Be aware that all key-value pairs with Symbol keys are removed before the
204
- # attributes are written. Therefore you always need to specify general attributes with strings!
203
+ # information.
205
204
  #
206
- # If the special value :link_text is present in the attributes, it will be used as the link
205
+ # If the special value 'link_text' is present in the attributes, it will be used as the link
207
206
  # text; otherwise the title of the +node+ will be used.
208
207
  def link_to(node, lang = @lang, attr = {})
209
- attr = node['link_attrs'].merge(attr) if node['link_attrs'].kind_of?(Hash)
210
208
  rnode = node.proxy_node(lang)
211
- link_text = attr[:link_text] || (rnode != node && rnode['routed_title']) || node['title']
212
- attr.delete_if {|k,v| k.kind_of?(Symbol)}
209
+ attr = (rnode['link_attrs'].kind_of?(Hash) ? rnode['link_attrs'] : {}).merge(attr)
210
+ link_text = attr.delete('link_text') || (rnode != node && rnode['routed_title']) || node['title']
213
211
 
214
212
  attr['href'] = self.route_to(node, lang)
215
213
  attr['hreflang'] = rnode.lang.to_s if rnode.lang
@@ -223,29 +221,6 @@ module Webgen
223
221
  each_with_object({}) {|(k, v), h| h[v['version']] = v}
224
222
  end
225
223
 
226
-
227
- #######
228
- private
229
- #######
230
-
231
- # Delegate missing methods to the associated path handler. The current node is placed into the
232
- # argument array as the first argument before the method +name+ is invoked on the path handler.
233
- def method_missing(name, *args, &block)
234
- if node_info[:path_handler]
235
- node_info[:path_handler].send(name, *([self] + args), &block)
236
- else
237
- super
238
- end
239
- end
240
-
241
- def respond_to_missing?(symbol, include_private) #:nodoc:
242
- if node_info[:path_handler]
243
- node_info[:path_handler].send(:respond_to?, symbol, include_private)
244
- else
245
- super
246
- end
247
- end
248
-
249
224
  end
250
225
 
251
226
  end
@@ -38,6 +38,13 @@ module Webgen
38
38
  # Value: an integer. Specifies how many nodes from the front of the list should *not* be
39
39
  # returned. Implies 'flatten = true'.
40
40
  #
41
+ # [:levels]
42
+ # Value: one integer (is used as start and end level) or an array with two integers (the start
43
+ # and end levels). All nodes whose hierarchy level in the returned node hierarchy is greater
44
+ # than or equal to the start level and lower than or equal to the end level are used.
45
+ #
46
+ # Only used when the node hierarchy is not flattened.
47
+ #
41
48
  # [:flatten]
42
49
  # Value: anything except +nil+ or +false+. A flat list of nodes is returned if this option is
43
50
  # set, otherwise the nodes are returned in their correct hierarchical order using nested lists.
@@ -85,10 +92,10 @@ module Webgen
85
92
  # Value: a finder option set or an array of finder options sets (specifying option set names is
86
93
  # also possible). Only nodes that do not appear in any specified option set are used.
87
94
  #
88
- # [:levels]
95
+ # [:absolute_levels]
89
96
  # Value: one integer (is used as start and end level) or an array with two integers (the start
90
- # and end levels). All nodes whose hierarchy levels are greater than or equal to the start level
91
- # and lower than or equal to the end level are used.
97
+ # and end levels). All nodes whose hierarchy level in the node tree are greater than or equal to
98
+ # the start level and lower than or equal to the end level are used.
92
99
  #
93
100
  # [:ancestors]
94
101
  # Value: +true+ or +false+/+nil+. If this filter option is set to +true+, only nodes that are
@@ -131,7 +138,7 @@ module Webgen
131
138
  def initialize(website)
132
139
  @website = website
133
140
  @mapping = {
134
- :alcn => :filter_alcn, :levels => :filter_levels, :lang => :filter_lang,
141
+ :alcn => :filter_alcn, :absolute_levels => :filter_absolute_levels, :lang => :filter_lang,
135
142
  :and => :filter_and, :or => :filter_or, :not => :filter_not,
136
143
  :ancestors => :filter_ancestors, :descendants => :filter_descendants,
137
144
  :siblings => :filter_siblings,
@@ -170,8 +177,9 @@ module Webgen
170
177
  end
171
178
  opts = prepare_options_hash(opts_or_name)
172
179
 
173
- limit, offset, flatten, sort = remove_non_filter_options(opts)
180
+ limit, offset, flatten, sort, levels = remove_non_filter_options(opts)
174
181
  flatten = true if limit || offset
182
+ levels = [levels || [1, 1_000_000]].flatten.map {|i| i.to_i}
175
183
 
176
184
  nodes = filter_nodes(opts, ref_node)
177
185
 
@@ -189,10 +197,17 @@ module Webgen
189
197
  hierarchy_nodes.inject(result) {|memo, hn| memo[hn] ||= {}}
190
198
  end
191
199
 
192
- reducer = lambda do |h|
193
- h.map {|k,v| v.empty? ? k : [k, reducer.call(v)]}
200
+ reducer = lambda do |h, level|
201
+ if level < levels.first
202
+ temp = h.map {|k,v| v.empty? ? nil : reducer.call(v, level + 1)}.compact
203
+ temp.length == 1 && temp.first.kind_of?(Array) ? temp.first : temp
204
+ elsif level < levels.last
205
+ h.map {|k,v| v.empty? ? k : [k, reducer.call(v, level + 1)]}
206
+ else
207
+ h.map {|k,v| k}
208
+ end
194
209
  end
195
- nodes = reducer.call(result)
210
+ nodes = reducer.call(result, 1)
196
211
  sort_nodes(nodes, sort, false)
197
212
  end
198
213
 
@@ -222,7 +237,7 @@ module Webgen
222
237
  end
223
238
 
224
239
  def remove_non_filter_options(opts)
225
- [opts.delete(:limit), opts.delete(:offset), opts.delete(:flatten), opts.delete(:sort)]
240
+ [opts.delete(:limit), opts.delete(:offset), opts.delete(:flatten), opts.delete(:sort), opts.delete(:levels)]
226
241
  end
227
242
 
228
243
  def filter_nodes(opts, ref_node)
@@ -297,7 +312,7 @@ module Webgen
297
312
  nodes.keep_if {|n| alcn.any? {|a| n =~ a}}
298
313
  end
299
314
 
300
- def filter_levels(nodes, ref_node, range)
315
+ def filter_absolute_levels(nodes, ref_node, range)
301
316
  range = [range].flatten.map {|i| i.to_i}
302
317
  nodes.keep_if {|n| n.level >= range.first && n.level <= range.last}
303
318
  end
data/lib/webgen/path.rb CHANGED
@@ -314,9 +314,9 @@ module Webgen
314
314
  @basename = match_data[1]
315
315
  @ext = match_data[2]
316
316
  else
317
- @meta_info['sort_info'] ||= (match_data[1].nil? ? nil : match_data[1].to_i)
317
+ @meta_info['sort_info'] ||= match_data[1].to_i unless match_data[1].nil?
318
318
  @basename = match_data[2]
319
- @meta_info['lang'] ||= Webgen::LanguageManager.language_for_code(match_data[3])
319
+ @meta_info['lang'] ||= Webgen::LanguageManager.language_for_code(match_data[3]) if match_data[3]
320
320
  @ext = (@meta_info['lang'].nil? && !match_data[3].nil? ? match_data[3].to_s + '.' : '') + match_data[4].to_s
321
321
  end
322
322
  end
@@ -27,17 +27,24 @@ module Webgen
27
27
  #
28
28
  module Base
29
29
 
30
+ # This is the base Node sub class used by the Base#create_node method if a path handler class
31
+ # does not specify another Node class.
32
+ class Node < Webgen::Node
33
+
34
+ # Return the result of the #content method on the associated path handler or +nil+ if the
35
+ # associated path handler does not have a #content method.
36
+ def content
37
+ (@node_info[:path_handler].respond_to?(:content) ? @node_info[:path_handler].content(self) : nil)
38
+ end
39
+
40
+ end
41
+
42
+
30
43
  # Initialize the path handler with the given Website object.
31
44
  def initialize(website)
32
45
  @website = website
33
46
  end
34
47
 
35
- # Return +nil+ as content of the given +node+.
36
- #
37
- # Should probably be over-written by path handler classes using this module!
38
- def content(node)
39
- end
40
-
41
48
  # Update +path.meta_info+ with meta information found in the content of the path.
42
49
  #
43
50
  # This default +parse_meta_info!+ method does nothing and should be overridden in path
@@ -50,9 +57,12 @@ module Webgen
50
57
  []
51
58
  end
52
59
 
53
- # Create a node from +path+, if possible, yield the full initialized node if a block is given
60
+ # Create a node from +path+, if possible, yield the fully initialized node if a block is given
54
61
  # and return it.
55
62
  #
63
+ # The node class to be used for the created node can be specified via the +node_klass+
64
+ # parameter.
65
+ #
56
66
  # If no node can be created (e.g. when 'path.meta_info['draft']' is set), +nil+ is returned.
57
67
  #
58
68
  # The parent node under which the new node should be created can optionally be specified via
@@ -61,7 +71,7 @@ module Webgen
61
71
  #
62
72
  # On the created node, the node information +:path+ is set to the given path and
63
73
  # +:path_handler+ to the path handler instance.
64
- def create_node(path)
74
+ def create_node(path, node_klass = Node)
65
75
  return nil if path.meta_info['draft']
66
76
  parent = parent_node(path)
67
77
  dest_path = self.dest_path(parent, path)
@@ -71,6 +81,7 @@ module Webgen
71
81
  if node_path != path
72
82
  raise Webgen::NodeCreationError.new("Another node <#{node}> with the same alcn or destination path already exists")
73
83
  elsif node_path.meta_info == path.meta_info
84
+ @website.blackboard.dispatch_msg(:reused_existing_node, node)
74
85
  return node
75
86
  else
76
87
  node.tree.delete_node(node)
@@ -84,7 +95,7 @@ module Webgen
84
95
  path.meta_info['modified_at'] = Time.now
85
96
  end
86
97
 
87
- node = Webgen::Node.new(parent, path.cn, dest_path, path.meta_info)
98
+ node = node_klass.new(parent, path.cn, dest_path, path.meta_info.dup)
88
99
  node.node_info[:path] = path
89
100
  node.node_info[:path_handler] = self
90
101