gettalong-webgen 0.5.5.20081001 → 0.5.5.20081010

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/doc/extensions.page +1 -1
  2. data/doc/reference_configuration.page +85 -0
  3. data/doc/tag/tikz.page +158 -0
  4. data/lib/webgen/common/sitemap.rb +2 -3
  5. data/lib/webgen/contentprocessor/blocks.rb +0 -2
  6. data/lib/webgen/contentprocessor/context.rb +0 -3
  7. data/lib/webgen/contentprocessor/erubis.rb +0 -2
  8. data/lib/webgen/default_config.rb +8 -1
  9. data/lib/webgen/node.rb +49 -24
  10. data/lib/webgen/page.rb +25 -15
  11. data/lib/webgen/path.rb +20 -10
  12. data/lib/webgen/sourcehandler/base.rb +36 -14
  13. data/lib/webgen/sourcehandler/copy.rb +2 -2
  14. data/lib/webgen/sourcehandler/directory.rb +16 -13
  15. data/lib/webgen/sourcehandler/feed.rb +3 -6
  16. data/lib/webgen/sourcehandler/fragment.rb +6 -11
  17. data/lib/webgen/sourcehandler/memory.rb +41 -0
  18. data/lib/webgen/sourcehandler/metainfo.rb +21 -21
  19. data/lib/webgen/sourcehandler/page.rb +8 -12
  20. data/lib/webgen/sourcehandler/sitemap.rb +0 -2
  21. data/lib/webgen/sourcehandler/template.rb +0 -4
  22. data/lib/webgen/sourcehandler/virtual.rb +18 -18
  23. data/lib/webgen/sourcehandler.rb +83 -70
  24. data/lib/webgen/tag/breadcrumbtrail.rb +1 -4
  25. data/lib/webgen/tag/coderay.rb +0 -3
  26. data/lib/webgen/tag/date.rb +0 -2
  27. data/lib/webgen/tag/executecommand.rb +1 -2
  28. data/lib/webgen/tag/includefile.rb +1 -3
  29. data/lib/webgen/tag/langbar.rb +1 -4
  30. data/lib/webgen/tag/menu.rb +1 -4
  31. data/lib/webgen/tag/metainfo.rb +0 -2
  32. data/lib/webgen/tag/relocatable.rb +2 -3
  33. data/lib/webgen/tag/sitemap.rb +0 -3
  34. data/lib/webgen/tag/tikz.rb +117 -0
  35. data/lib/webgen/tag.rb +1 -0
  36. data/lib/webgen/tree.rb +9 -5
  37. data/test/test_common_sitemap.rb +4 -4
  38. data/test/test_contentprocessor_context.rb +1 -1
  39. data/test/test_contentprocessor_redcloth.rb +1 -0
  40. data/test/test_contentprocessor_tags.rb +1 -1
  41. data/test/test_node.rb +33 -13
  42. data/test/test_output_filesystem.rb +1 -1
  43. data/test/test_page.rb +13 -4
  44. data/test/test_path.rb +37 -5
  45. data/test/test_source_filesystem.rb +1 -1
  46. data/test/test_source_stacked.rb +1 -1
  47. data/test/test_sourcehandler_base.rb +30 -1
  48. data/test/test_sourcehandler_copy.rb +1 -1
  49. data/test/test_sourcehandler_directory.rb +16 -1
  50. data/test/test_sourcehandler_feed.rb +6 -7
  51. data/test/test_sourcehandler_fragment.rb +1 -1
  52. data/test/test_sourcehandler_memory.rb +42 -0
  53. data/test/test_sourcehandler_metainfo.rb +23 -21
  54. data/test/test_sourcehandler_page.rb +5 -7
  55. data/test/test_sourcehandler_template.rb +1 -1
  56. data/test/test_sourcehandler_virtual.rb +2 -2
  57. data/test/test_tag_base.rb +0 -1
  58. data/test/test_tag_breadcrumbtrail.rb +4 -4
  59. data/test/test_tag_includefile.rb +3 -3
  60. data/test/test_tag_langbar.rb +5 -6
  61. data/test/test_tag_menu.rb +7 -7
  62. data/test/test_tag_metainfo.rb +1 -1
  63. data/test/test_tag_relocatable.rb +1 -1
  64. data/test/test_tag_tikz.rb +66 -0
  65. data/test/test_tree.rb +2 -7
  66. metadata +7 -2
@@ -7,8 +7,8 @@ module Webgen::SourceHandler
7
7
  include Webgen::WebsiteAccess
8
8
  include Base
9
9
 
10
- # Create the node for +parent+ and +path+. If the +path+ has the name of a content processor in
11
- # the extension, it is preprocessed.
10
+ # Create the node for +parent+ and +path+. If the +path+ has the name of a content processor as
11
+ # the first part in the extension, it is preprocessed.
12
12
  def create_node(parent, path)
13
13
  if path.ext.index('.')
14
14
  processor, *rest = path.ext.split('.')
@@ -1,24 +1,27 @@
1
- require 'webgen/sourcehandler/base'
2
-
3
1
  module Webgen::SourceHandler
4
2
 
5
3
  # Handles directory source paths.
6
4
  class Directory
7
5
 
8
6
  include Base
7
+ include Webgen::WebsiteAccess
8
+
9
+ def initialize # :nodoc:
10
+ website.blackboard.add_service(:create_directories, method(:create_directories))
11
+ end
9
12
 
10
- # Creation of directory nodes is special because once they are created, they are only deleted
11
- # when the source path gets deleted. Otherwise, only the meta information of the node gets
12
- # updated.
13
- def create_node(parent, path)
14
- if node = node_exists?(parent, path)
15
- node.meta_info.clear
16
- node.meta_info.update(path.meta_info)
17
- node.dirty = true
18
- node
19
- else
20
- super(parent, path)
13
+ # Recursively create the directories specified in +dirname+ under +parent+ (a leading slash is
14
+ # ignored). The path +path+ is the path that lead to the creation of these directories.
15
+ def create_directories(parent, dirname, path)
16
+ dirname.sub(/^\//, '').split('/').each do |dir|
17
+ dir_path = Webgen::Path.new(File.join(parent.absolute_lcn, dir, '/'), path)
18
+ nodes = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
19
+ dir_path, self) do |dir_parent, dir_path|
20
+ node_exists?(dir_parent, dir_path) || create_node(dir_parent, dir_path)
21
+ end
22
+ parent = nodes.first
21
23
  end
24
+ parent
22
25
  end
23
26
 
24
27
  # Return an empty string to signal that the directory should be written to the output.
@@ -1,6 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/sourcehandler/base'
3
-
4
1
  module Webgen::SourceHandler
5
2
 
6
3
  # Source handler for creating atom and/or rss feeds.
@@ -107,12 +104,12 @@ module Webgen::SourceHandler
107
104
  feed
108
105
  end
109
106
 
110
- # Check if the +node+ has meta information from any meta info node and if so, if the meta info
111
- # node in question has changed.
107
+ # Check if the any of the nodes used by this feed +node+ have changed and then mark the node as
108
+ # dirty.
112
109
  def node_changed?(node)
113
110
  return if node.node_info[:processor] != self.class.name
114
111
  entries = node.feed_entries
115
- node.dirty = true if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
112
+ node.flag(:dirty) if entries.map {|n| n.absolute_lcn } != website.cache[[:sourcehandler_feed, node.node_info[:src]]] ||
116
113
  entries.any? {|n| n.changed?}
117
114
  end
118
115
 
@@ -1,6 +1,3 @@
1
- require 'webgen/sourcehandler/base'
2
- require 'webgen/websiteaccess'
3
-
4
1
  module Webgen::SourceHandler
5
2
 
6
3
  # Handles page fragment nodes and provides utility methods for parsing HTML headers and generating
@@ -53,15 +50,13 @@ module Webgen::SourceHandler
53
50
  def create_fragment_nodes(sections, parent, path, in_menu, si = 1000 )
54
51
  sections.each do |level, id, title, sub_sections|
55
52
  node = website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
56
- path, self) do |cn_parent, cn_path|
57
- ptemp = Webgen::Path.new('#' + id)
58
- ptemp.meta_info = cn_path.meta_info.merge(ptemp.meta_info)
59
- create_node(cn_parent, ptemp)
53
+ Webgen::Path.new('#' + id, path.source_path),
54
+ self) do |cn_parent, cn_path|
55
+ cn_path.meta_info['title'] = title
56
+ cn_path.meta_info['in_menu'] = in_menu
57
+ cn_path.meta_info['sort_info'] = si = si.succ
58
+ create_node(cn_parent, cn_path)
60
59
  end.first
61
- node['title'] = title
62
- node['in_menu'] = in_menu
63
- node['sort_info'] = si = si.succ
64
- node.node_info[:src] = path.path
65
60
  create_fragment_nodes(sub_sections, node, path, in_menu, si.succ)
66
61
  end
67
62
  end
@@ -0,0 +1,41 @@
1
+ module Webgen::SourceHandler
2
+
3
+ # This source handler should be used for handling nodes that are created during the write
4
+ # phase.
5
+ class Memory
6
+
7
+ include Webgen::WebsiteAccess
8
+ include Base
9
+
10
+ def initialize #:nodoc:
11
+ website.blackboard.add_listener(:node_flagged) do |node, *flags|
12
+ node.tree[node.node_info[:memory_source_alcn]].flag(:dirty) if node.node_info[:memory_source_alcn]
13
+ end
14
+ end
15
+
16
+ # Create a node under +parent+ for the +path+. The +source_alcn+ specified the node that creates
17
+ # this memory node when written. You have two options for providing the content for this node:
18
+ # either you set +data+ to a string (or a Webgen::Path::SourceIO object) or you provide a block
19
+ # which takes the created node as argument and return a string (or a Webgen::Path::SourceIO
20
+ # object).
21
+ def create_node(parent, path, source_alcn, data = nil)
22
+ super(parent, path) do |node|
23
+ node.node_info[:memory_source_alcn] = source_alcn
24
+ (@data ||= {})[node.absolute_lcn] = lambda { data || yield(node) }
25
+ end
26
+ end
27
+
28
+ # Return the content of the memory +node+. If the memory node was not created in this webgen
29
+ # run, it will be flagged for reinitialization (and therefore recreation).
30
+ def content(node)
31
+ if @data && @data[node.absolute_lcn]
32
+ @data[node.absolute_lcn].call
33
+ else
34
+ node.flag(:reinit)
35
+ nil
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -1,7 +1,5 @@
1
1
  require 'pathname'
2
2
  require 'yaml'
3
- require 'webgen/sourcehandler/base'
4
- require 'webgen/websiteaccess'
5
3
 
6
4
  module Webgen::SourceHandler
7
5
 
@@ -19,7 +17,7 @@ module Webgen::SourceHandler
19
17
  website.blackboard.add_listener(:before_node_created, method(:before_node_created))
20
18
  website.blackboard.add_listener(:before_node_deleted, method(:before_node_deleted))
21
19
  website.blackboard.add_listener(:after_node_created, method(:after_node_created))
22
- self.nodes ||= Set.new
20
+ self.nodes ||= []
23
21
  end
24
22
 
25
23
  # Create a meta info node from +parent+ and +path+.
@@ -30,18 +28,18 @@ module Webgen::SourceHandler
30
28
  node.node_info[mi_key] = {}
31
29
  YAML::load(page.blocks[block_name].content).each do |key, value|
32
30
  key = Pathname.new(key =~ /^\// ? key : File.join(parent.absolute_lcn, key)).cleanpath.to_s
33
- key.chomp('/') unless key == '/'
34
31
  node.node_info[mi_key][key] = value
35
32
  end if page.blocks.has_key?(block_name)
36
33
  end
37
- website.cache[[:sh_metainfo_node_mi, node.absolute_lcn]] = {
34
+
35
+ mark_all_matched_dirty(node, :no_old_data)
36
+
37
+ website.cache.permanent[[:sh_metainfo_node_mi, node.absolute_lcn]] = {
38
38
  :mi_paths => node.node_info[:mi_paths],
39
39
  :mi_alcn => node.node_info[:mi_alcn]
40
40
  }
41
41
 
42
- mark_all_matched_dirty(node)
43
-
44
- self.nodes << node
42
+ self.nodes << node unless self.nodes.include?(node)
45
43
  self.nodes = self.nodes.sort_by {|n| n.absolute_lcn}
46
44
  end
47
45
  end
@@ -59,19 +57,21 @@ module Webgen::SourceHandler
59
57
  #######
60
58
 
61
59
  # Return +true+ if any meta information for +node+ provided by +mi_node+ has changed.
62
- def meta_info_changed?(mi_node, node, use_cache = true)
63
- use_cache = false if !website.cache.old_data[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
64
- cached = website.cache[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
65
- path = website.blackboard.invoke(:source_paths)[node.node_info[:src]]
66
- (mi_node.node_info[:mi_paths].any? {|pattern, mi| path =~ pattern && (!use_cache || mi != cached[:mi_paths][pattern])} ||
67
- mi_node.node_info[:mi_alcn].any? {|pattern, mi| node =~ pattern && (!use_cache || mi != cached[:mi_alcn][pattern])})
60
+ def meta_info_changed?(mi_node, node, option = nil)
61
+ cached = website.cache.permanent[[:sh_metainfo_node_mi, mi_node.absolute_lcn]]
62
+ (mi_node.node_info[:mi_paths].any? do |pattern, mi|
63
+ Webgen::Path.match(node.node_info[:creation_path], pattern) &&
64
+ (option == :force || (!cached && option == :no_old_data) || mi != cached[:mi_paths][pattern])
65
+ end || mi_node.node_info[:mi_alcn].any? do |pattern, mi|
66
+ node =~ pattern && (option == :force || (!cached && option == :no_old_data) || mi != cached[:mi_alcn][pattern])
67
+ end)
68
68
  end
69
69
 
70
70
  # Mark all nodes that are matched by a path or an alcn specifcation in the meta info node +node+
71
71
  # as dirty.
72
- def mark_all_matched_dirty(node, use_cache = true)
72
+ def mark_all_matched_dirty(node, option = nil)
73
73
  node.tree.node_access[:alcn].each do |path, n|
74
- n.dirty_meta_info = true if meta_info_changed?(node, n, use_cache)
74
+ n.flag(:dirty_meta_info) if meta_info_changed?(node, n, option)
75
75
  end
76
76
  end
77
77
 
@@ -79,7 +79,7 @@ module Webgen::SourceHandler
79
79
  def before_node_created(parent, path)
80
80
  self.nodes.each do |node|
81
81
  node.node_info[:mi_paths].each do |pattern, mi|
82
- path.meta_info.update(mi) if path =~ pattern
82
+ path.meta_info.update(mi) if Webgen::Path.match(path, pattern)
83
83
  end
84
84
  end
85
85
  end
@@ -96,10 +96,9 @@ module Webgen::SourceHandler
96
96
  # Check if the +node+ has meta information from any meta info node and if so, if the meta info
97
97
  # node in question has changed.
98
98
  def node_meta_info_changed?(node)
99
- return if self.nodes.include?(node)
100
99
  self.nodes.each do |n|
101
- if n.created && meta_info_changed?(n, node)
102
- node.dirty_meta_info = true
100
+ if n.flagged(:created) && meta_info_changed?(n, node)
101
+ node.flag(:dirty_meta_info)
103
102
  return
104
103
  end
105
104
  end
@@ -108,7 +107,8 @@ module Webgen::SourceHandler
108
107
  # Delete the meta info node +node+ from the internal array.
109
108
  def before_node_deleted(node)
110
109
  return unless node.node_info[:processor] == self.class.name
111
- mark_all_matched_dirty(node, false) if !website.blackboard.invoke(:source_paths).include?(node.node_info[:src])
110
+ mark_all_matched_dirty(node, :force)
111
+ website.cache.permanent.delete([:sh_metainfo_node_mi, node.absolute_lcn])
112
112
  self.nodes.delete(node)
113
113
  end
114
114
 
@@ -1,6 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/sourcehandler/base'
3
-
4
1
  module Webgen::SourceHandler
5
2
 
6
3
  # Source handler for handling content files in Webgen Page Format.
@@ -20,7 +17,7 @@ module Webgen::SourceHandler
20
17
  path.ext = 'html' if path.ext == 'page'
21
18
 
22
19
  super(parent, path) do |node|
23
- website.cache[[:sh_page_node_mi, node.absolute_lcn]] = node.meta_info.dup
20
+ node.node_info[:sh_page_node_mi] = Webgen::Page.meta_info_from_data(path.io.data)
24
21
 
25
22
  node.node_info[:page] = page
26
23
  tmp_logger = website.logger
@@ -35,7 +32,7 @@ module Webgen::SourceHandler
35
32
  website.cache.permanent[:page_sections][node.absolute_lcn] = sections
36
33
  website.blackboard.invoke(:create_fragment_nodes,
37
34
  sections,
38
- node, website.blackboard.invoke(:source_paths)[path.path],
35
+ node, website.blackboard.invoke(:source_paths)[path.source_path],
39
36
  node.meta_info['fragments_in_menu'])
40
37
  website.logger = tmp_logger
41
38
  end
@@ -63,13 +60,12 @@ module Webgen::SourceHandler
63
60
 
64
61
  # Checks if the meta information provided by the file in Webgen Page Format changed.
65
62
  def meta_info_changed?(node)
66
- return if !node.created || node.node_info[:processor] != self.class.name
67
- ckey = [:sh_page_node_mi, node.absolute_lcn]
68
- old_mi = website.cache.old_data[ckey]
69
- old_mi.delete('modified_at') if old_mi
70
- new_mi = website.cache.new_data[ckey]
71
- new_mi.delete('modified_at')
72
- node.dirty_meta_info = true if old_mi != new_mi
63
+ path = website.blackboard.invoke(:source_paths)[node.node_info[:src]]
64
+ return if node.node_info[:processor] != self.class.name || !path.changed?
65
+
66
+ old_mi = node.node_info[:sh_page_node_mi]
67
+ new_mi = Webgen::Page.meta_info_from_data(path.io.data)
68
+ node.flag(:dirty_meta_info) if old_mi && old_mi != new_mi
73
69
  end
74
70
 
75
71
  end
@@ -1,5 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/sourcehandler/base'
3
1
  require 'uri'
4
2
  require 'time'
5
3
 
@@ -1,7 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/loggable'
3
- require 'webgen/sourcehandler/base'
4
-
5
1
  module Webgen::SourceHandler
6
2
 
7
3
  # Source handler for handling template files in Webgen Page Format.
@@ -1,7 +1,5 @@
1
1
  require 'uri'
2
2
  require 'yaml'
3
- require 'webgen/sourcehandler/base'
4
- require 'webgen/websiteaccess'
5
3
 
6
4
  module Webgen::SourceHandler
7
5
 
@@ -18,22 +16,25 @@ module Webgen::SourceHandler
18
16
  def create_node(parent, path)
19
17
  page = page_from_path(path)
20
18
  nodes = []
21
- YAML::load(page.blocks['content'].content).each do |key, value|
19
+ YAML::load(page.blocks['content'].content).each do |key, meta_info|
22
20
  key = (key =~ /^\// ? key : File.join(parent.absolute_lcn, key))
23
21
  temp_parent = create_directories(parent.tree.root, File.dirname(key), path)
24
22
 
25
- temp_path = Webgen::Path.new(key)
26
- temp_path.meta_info.update(value || {})
27
- temp_path.meta_info['modified_at'] = path.meta_info['modified_at']
28
- temp_path.meta_info['no_output'] = true
29
- output_path = temp_path.meta_info.delete('url') || key
23
+ meta_info ||= {}
24
+ meta_info['modified_at'] = path.meta_info['modified_at']
25
+ meta_info['no_output'] = true
26
+ output_path = meta_info.delete('url') || key
30
27
  output_path = (URI::parse(output_path).absolute? || output_path =~ /^\// ?
31
28
  output_path : File.join(temp_parent.absolute_lcn, output_path))
32
29
 
33
30
  if key =~ /\/$/
34
- nodes << create_directory(temp_parent, key, path, temp_path.meta_info)
31
+ nodes << create_directory(temp_parent, key, path, meta_info)
35
32
  else
36
- nodes << super(temp_parent, temp_path, output_path) {|n| n.node_info[:src] = path.path}
33
+ nodes += website.blackboard.invoke(:create_nodes, parent.tree, temp_parent.absolute_lcn,
34
+ Webgen::Path.new(key, path.source_path), self) do |cn_parent, cn_path|
35
+ cn_path.meta_info.update(meta_info)
36
+ super(cn_parent, cn_path, output_path)
37
+ end
37
38
  end
38
39
  end if page.blocks.has_key?('content')
39
40
  nodes.compact
@@ -55,17 +56,16 @@ module Webgen::SourceHandler
55
56
  def create_directory(parent, dir, path, meta_info = nil)
56
57
  dir_handler = website.cache.instance('Webgen::SourceHandler::Directory')
57
58
  website.blackboard.invoke(:create_nodes, parent.tree, parent.absolute_lcn,
58
- Webgen::Path.new(File.join(dir, '/')),
59
+ Webgen::Path.new(File.join(dir, '/'), path.source_path),
59
60
  dir_handler) do |par, temp_path|
60
- node = nil
61
- if (node = dir_handler.node_exists?(par, temp_path)) && (!meta_info || node.node_info[:src] != path.path)
62
- parent, node = node, nil
63
- else
61
+ parent = dir_handler.node_exists?(par, temp_path)
62
+ if (parent && (parent.node_info[:src] == path.source_path) && !meta_info.nil?) ||
63
+ !parent
64
64
  temp_path.meta_info.update(meta_info) if meta_info
65
- parent = node = dir_handler.create_node(par, temp_path)
66
- parent.node_info[:src] = path.path
65
+ parent.flag(:reinit) if parent
66
+ parent = dir_handler.create_node(par, temp_path)
67
67
  end
68
- node
68
+ parent
69
69
  end
70
70
  parent
71
71
  end
@@ -19,6 +19,7 @@ module Webgen
19
19
  autoload :Virtual, 'webgen/sourcehandler/virtual'
20
20
  autoload :Feed, 'webgen/sourcehandler/feed'
21
21
  autoload :Sitemap, 'webgen/sourcehandler/sitemap'
22
+ autoload :Memory, 'webgen/sourcehandler/memory'
22
23
 
23
24
  # This class is used by Website to do the actual rendering of the website. It
24
25
  #
@@ -39,52 +40,87 @@ module Webgen
39
40
  # Render the nodes provided in the +tree+. Before the actual rendering is done, the sources
40
41
  # are checked (nodes for deleted sources are deleted, nodes for new and changed sources).
41
42
  def render(tree)
42
- # Add new and changed nodes, remove nodes of deleted paths
43
- puts "Generating tree..."
44
- time = Benchmark.measure do
45
- used_paths = Set.new
46
- paths = Set.new([nil])
47
- while paths.length > 0
48
- used_paths += (paths = Set.new(find_all_source_paths.keys) - used_paths - clean(tree))
49
- create_nodes_from_paths(tree, paths)
50
- website.cache.reset_volatile_cache
43
+ begin
44
+ puts "Updating tree..."
45
+ time = Benchmark.measure do
46
+ update_tree(tree)
51
47
  end
52
- end
53
- puts "...done in " + ('%2.4f' % time.real) + ' seconds'
54
-
55
- output = website.blackboard.invoke(:output_instance)
48
+ puts "...done in " + ('%2.4f' % time.real) + ' seconds'
56
49
 
57
- puts "Writing changed nodes..."
58
- time = Benchmark.measure do
59
- tree.node_access[:alcn].sort.each do |name, node|
60
- node.dirty_meta_info = node.created = false
61
- next if node == tree.dummy_root || !node.dirty
62
- node.dirty = false
63
-
64
- begin
65
- if !node['no_output'] && (content = node.content)
66
- puts " "*4 + name, :verbose
67
- type = if node.is_directory?
68
- :directory
69
- elsif node.is_fragment?
70
- :fragment
71
- else
72
- :file
73
- end
74
- output.write(node.path, content, type)
75
- end
76
- rescue
77
- raise RuntimeError, "Error while processing <#{node.absolute_lcn}>: #{$!.message}", $!.backtrace
78
- end
50
+ puts "Writing changed nodes..."
51
+ time = Benchmark.measure do
52
+ write_tree(tree)
79
53
  end
80
- end
81
- puts "...done in " + ('%2.4f' % time.real) + ' seconds'
54
+ puts "...done in " + ('%2.4f' % time.real) + ' seconds'
55
+ end while tree.node_access[:alcn].any? {|name,node| node.flagged(:created) || node.flagged(:reinit)}
82
56
  end
83
57
 
84
58
  #######
85
59
  private
86
60
  #######
87
61
 
62
+ # Update the +tree+ by creating/reinitializing all needed nodes.
63
+ def update_tree(tree)
64
+ unused_paths = Set.new
65
+ begin
66
+ used_paths = Set.new(find_all_source_paths.keys) - unused_paths
67
+ paths_to_use = Set.new
68
+ nodes_to_delete = Set.new
69
+
70
+ tree.node_access[:alcn].each do |alcn, node|
71
+ next if node == tree.dummy_root
72
+ used_paths.delete(node.node_info[:src])
73
+
74
+ deleted = !find_all_source_paths.include?(node.node_info[:src])
75
+ if deleted
76
+ nodes_to_delete << node
77
+ #TODO: delete output path
78
+ elsif (!node.flagged(:created) && find_all_source_paths[node.node_info[:src]].changed?) || node.meta_info_changed?
79
+ node.flag(:reinit)
80
+ paths_to_use << node.node_info[:src]
81
+ elsif node.changed?
82
+ # nothing to be done here
83
+ end
84
+ end
85
+
86
+ nodes_to_delete.each {|node| tree.delete_node(node)}
87
+ used_paths.merge(paths_to_use)
88
+ paths = create_nodes_from_paths(tree, used_paths.to_a.sort)
89
+ unused_paths.merge(used_paths - paths)
90
+ tree.node_access[:alcn].each {|name, node| tree.delete_node(node) if node.flagged(:reinit)}
91
+ website.cache.reset_volatile_cache
92
+ end until used_paths.empty?
93
+ end
94
+
95
+ # Write out all changed nodes of the +tree+.
96
+ def write_tree(tree)
97
+ output = website.blackboard.invoke(:output_instance)
98
+
99
+ tree.node_access[:alcn].select do |name, node|
100
+ use_node = (node != tree.dummy_root && node.flagged(:dirty))
101
+ node.unflag(:dirty_meta_info)
102
+ node.unflag(:created)
103
+ node.unflag(:dirty)
104
+ use_node
105
+ end.sort.each do |name, node|
106
+ next if node['no_output'] || !(content = node.content)
107
+
108
+ begin
109
+ puts " "*4 + name, :verbose
110
+ type = if node.is_directory?
111
+ :directory
112
+ elsif node.is_fragment?
113
+ :fragment
114
+ else
115
+ :file
116
+ end
117
+ output.write(node.path, content, type)
118
+ rescue
119
+ raise RuntimeError, "Error while processing <#{node.absolute_lcn}>: #{$!.message}", $!.backtrace
120
+ end
121
+ end
122
+ end
123
+
88
124
  # Return a hash with all source paths.
89
125
  def find_all_source_paths
90
126
  if !defined?(@paths)
@@ -94,7 +130,7 @@ module Webgen
94
130
  @paths = {}
95
131
  source.paths.each do |path|
96
132
  if !(website.config['sourcehandler.ignore'].any? {|pat| File.fnmatch(pat, path, File::FNM_CASEFOLD|File::FNM_DOTMATCH)})
97
- @paths[path.path] = path
133
+ @paths[path.source_path] = path
98
134
  end
99
135
  end
100
136
  end
@@ -115,16 +151,20 @@ module Webgen
115
151
 
116
152
  # Use the source handlers to create nodes for the +paths+ in the +tree+.
117
153
  def create_nodes_from_paths(tree, paths)
154
+ used_paths = Set.new
118
155
  website.config['sourcehandler.invoke'].sort.each do |priority, shns|
119
156
  shns.each do |shn|
120
157
  sh = website.cache.instance(shn)
121
- paths_for_handler(shn, paths).sort.each do |path|
158
+ handler_paths = paths_for_handler(shn, paths)
159
+ used_paths.merge(handler_paths)
160
+ handler_paths.sort {|a,b| a.path.length <=> b.path.length}.each do |path|
122
161
  parent_dir = path.directory.split('/').collect {|p| Path.new(p).cn}.join('/')
123
162
  parent_dir += '/' if path != '/' && parent_dir == ''
124
163
  create_nodes(tree, parent_dir, path, sh)
125
164
  end
126
165
  end
127
166
  end
167
+ used_paths
128
168
  end
129
169
 
130
170
  # Prepare everything to create nodes under the absolute lcn path +parent_path_name+ in the
@@ -142,7 +182,7 @@ module Webgen
142
182
  *nodes = if block_given?
143
183
  yield(parent, path)
144
184
  else
145
- source_handler.create_node(parent, path.dup)
185
+ source_handler.create_node(parent, path)
146
186
  end
147
187
  nodes.flatten.compact.each do |node|
148
188
  website.blackboard.dispatch_msg(:after_node_created, node)
@@ -160,39 +200,12 @@ module Webgen
160
200
  # take the node's path's +modified_at+ meta information into account since that changes on
161
201
  # every path change.
162
202
  def meta_info_changed?(node)
163
- path = node.node_info[:src]
203
+ path = node.node_info[:creation_path]
164
204
  old_mi = website.cache[:sourcehandler_path_mi][[path, node.node_info[:processor]]]
165
205
  old_mi.delete('modified_at')
166
- new_mi = default_meta_info(@paths[path], node.node_info[:processor])
206
+ new_mi = default_meta_info(@paths[path] || Webgen::Path.new(path), node.node_info[:processor])
167
207
  new_mi.delete('modified_at')
168
- node.dirty_meta_info = true if !old_mi || old_mi != new_mi
169
- end
170
-
171
- # Clean the +tree+ by deleting nodes which have changed or which don't have an associated
172
- # source anymore. Return all paths for which nodes need to be created.
173
- def clean(tree)
174
- paths_to_delete = Set.new
175
- paths_not_to_delete = Set.new
176
- nodes_to_be_deleted = Set.new
177
- tree.node_access[:alcn].each do |alcn, node|
178
- next if node == tree.dummy_root || tree[alcn].nil?
179
-
180
- deleted = !find_all_source_paths.include?(node.node_info[:src])
181
- if !node.created && (deleted ||
182
- find_all_source_paths[node.node_info[:src]].changed? ||
183
- node.changed?)
184
- paths_not_to_delete << node.node_info[:src]
185
- nodes_to_be_deleted << [node, deleted]
186
- else
187
- paths_to_delete << node.node_info[:src]
188
- end
189
- end
190
-
191
- nodes_to_be_deleted.each {|node, deleted| tree.delete_node(node, deleted)}
192
- #TODO: delete output path
193
-
194
- # source paths that should be used
195
- paths_to_delete - paths_not_to_delete
208
+ node.flag(:dirty_meta_info) if !old_mi || old_mi != new_mi
196
209
  end
197
210
 
198
211
  end
@@ -1,6 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/tag'
3
-
4
1
  module Webgen::Tag
5
2
 
6
3
  # Generates a breadcrumb trail for the page. This is especially useful when pages are in deep
@@ -60,7 +57,7 @@ module Webgen::Tag
60
57
 
61
58
  if (list.map {|n| n.absolute_lcn} != cached_list) ||
62
59
  list.any? {|n| (r = n.routing_node(cn.lang)) && r != node && r.meta_info_changed?}
63
- node.dirty = true
60
+ node.flag(:dirty)
64
61
  break
65
62
  end
66
63
  end
@@ -1,6 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/tag'
3
-
4
1
  module Webgen::Tag
5
2
 
6
3
  # Provides syntax highlighting via the +coderay+ library.
@@ -1,5 +1,3 @@
1
- require 'webgen/tag'
2
-
3
1
  module Webgen::Tag
4
2
 
5
3
  # Prints out the date using a format string which will be passed to Time#strftime. Therefore you
@@ -1,6 +1,5 @@
1
- require 'webgen/tag'
2
1
  require 'cgi'
3
- require "tempfile"
2
+ require 'tempfile'
4
3
  require 'rbconfig'
5
4
 
6
5
  module Webgen::Tag
@@ -1,5 +1,3 @@
1
- require 'webgen/websiteaccess'
2
- require 'webgen/tag'
3
1
  require 'cgi'
4
2
 
5
3
  module Webgen::Tag
@@ -33,7 +31,7 @@ module Webgen::Tag
33
31
 
34
32
  def node_changed?(node)
35
33
  if filenames = node.node_info[:tag_includefile_filenames]
36
- node.dirty = true if filenames.any? {|f, mtime| File.mtime(f) > mtime}
34
+ node.flag(:dirty) if filenames.any? {|f, mtime| File.mtime(f) > mtime}
37
35
  end
38
36
  end
39
37