gettalong-webgen 0.5.5.20081001 → 0.5.5.20081010

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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