Object
This class is used by Website to do the actual rendering of the website. It
collects all source paths using the source classes
creates nodes using the source handler classes
writes changed nodes out using an output class
deletes old nodes
Render the current website. Before the actual rendering is done, the sources are checked for changes, i.e. nodes for deleted sources are deleted, nodes for new and changed sources are updated.
# File lib/webgen/sourcehandler.rb, line 54 54: def render 55: begin 56: website.logger.mark_new_cycle if website.logger 57: 58: puts "Updating tree..." 59: time = Benchmark.measure do 60: website.cache.reset_volatile_cache 61: update_tree 62: end 63: puts "...done in " + ('%2.4f' % time.real) + ' seconds' 64: 65: if !website.tree.root 66: puts 'No source files found - maybe not a webgen website?' 67: return nil 68: end 69: 70: puts "Writing changed nodes..." 71: time = Benchmark.measure do 72: write_tree 73: end 74: puts "...done in " + ('%2.4f' % time.real) + ' seconds' 75: end while website.tree.node_access[:alcn].any? {|name,node| node.flagged?(:created) || node.flagged?(:reinit)} 76: :success 77: rescue Webgen::Error 78: raise 79: rescue Exception => e 80: raise Webgen::Error.new(e) 81: end
Prepare everything to create from the path using the source_handler. If a block is given, the actual creation of the nodes is deferred to it. Otherwise the # method of the source_handler is used. After the nodes are created, it is also checked if they have all needed properties.
# File lib/webgen/sourcehandler.rb, line 233 233: def create_nodes(path, source_handler) #:yields: path 234: path = path.dup 235: path.meta_info = default_meta_info(path, source_handler.class.name) 236: (website.cache[:sourcehandler_path_mi] ||= {})[[path.path, source_handler.class.name]] = path.meta_info.dup 237: website.blackboard.dispatch_msg(:before_node_created, path) 238: *nodes = if block_given? 239: yield(path) 240: else 241: source_handler.create_node(path) 242: end 243: nodes = nodes.flatten.compact 244: nodes.each {|node| website.blackboard.dispatch_msg(:after_node_created, node)} 245: nodes 246: rescue Webgen::Error => e 247: e.alcn = path unless e.alcn 248: raise 249: rescue Exception => e 250: raise Webgen::NodeCreationError.new(e, source_handler.class.name, path) 251: end
Use the source handlers to create nodes for the paths in the website.tree and return the nodes that have been created.
# File lib/webgen/sourcehandler.rb, line 212 212: def create_nodes_from_paths(paths) 213: nodes = Set.new 214: website.config['sourcehandler.invoke'].sort.each do |priority, shns| 215: shns.each do |shn| 216: sh = website.cache.instance(shn) 217: handler_paths = paths_for_handler(shn, paths) 218: handler_paths.sort {|a,b| a.path.length <=> b.path.length}.each do |path| 219: if !website.tree[path.parent_path] 220: nodes.merge(create_nodes_from_paths([path.parent_path])) 221: end 222: nodes += create_nodes(path, sh) 223: end 224: end 225: end 226: nodes 227: end
Return the default meta info for the pair of path and sh_name.
# File lib/webgen/sourcehandler.rb, line 254 254: def default_meta_info(path, sh_name) 255: path.meta_info.merge(website.config['sourcehandler.default_meta_info'][:all]). 256: merge(website.config['sourcehandler.default_meta_info'][sh_name] || {}) 257: end
Return a hash with all source paths.
# File lib/webgen/sourcehandler.rb, line 176 176: def find_all_source_paths 177: if !defined?(@paths) 178: active_source = Webgen::Source::Stacked.new(website.config['sources'].collect do |mp, name, *args| 179: [mp, Webgen::Common.const_for_name(name).new(*args)] 180: end) 181: passive_source = Webgen::Source::Stacked.new(website.config['passive_sources'].collect do |mp, name, *args| 182: [mp, Webgen::Common.const_for_name(name).new(*args)] 183: end, true) 184: passive_source.paths.each {|path| path.passive = true } 185: source = Webgen::Source::Stacked.new([['/', active_source], ['/', passive_source]]) 186: 187: @paths = {} 188: source.paths.each do |path| 189: if !(website.config['sourcehandler.ignore'].any? {|pat| File.fnmatch(pat, path, File::FNM_CASEFOLD|File::FNM_DOTMATCH)}) 190: @paths[path.source_path] = path 191: end 192: end 193: end 194: @paths 195: end
Check if the default meta information for node has changed since the last run. But don’t take the node’s path’s modified_at meta information into account since that changes on every path change.
# File lib/webgen/sourcehandler.rb, line 262 262: def meta_info_changed?(node) 263: path = node.node_info[:creation_path] 264: old_mi = website.cache[:sourcehandler_path_mi][[path, node.node_info[:processor]]] 265: old_mi.delete('modified_at') 266: new_mi = default_meta_info(@paths[path] || Webgen::Path.new(path), node.node_info[:processor]) 267: new_mi.delete('modified_at') 268: node.flag(:dirty_meta_info) if !old_mi || old_mi != new_mi 269: end
Return only the subset of paths which are handled by the source handler name.
# File lib/webgen/sourcehandler.rb, line 198 198: def paths_for_handler(name, paths) 199: patterns = website.config['sourcehandler.patterns'][name] 200: return [] if patterns.nil? 201: 202: options = (website.config['sourcehandler.casefold'] ? File::FNM_CASEFOLD : 0) | 203: (website.config['sourcehandler.use_hidden_files'] ? File::FNM_DOTMATCH : 0) | 204: File::FNM_PATHNAME 205: find_all_source_paths.values_at(*paths).compact.select do |path| 206: patterns.any? {|pat| File.fnmatch(pat, path, options)} 207: end 208: end
Update the website.tree by creating/reinitializing all needed nodes.
# File lib/webgen/sourcehandler.rb, line 88 88: def update_tree 89: unused_paths = Set.new 90: referenced_nodes = Set.new 91: all_but_passive_paths = Set.new(find_all_source_paths.select {|name, path| !path.passive?}.collect {|name, path| name}) 92: begin 93: used_paths = all_but_passive_paths - unused_paths 94: paths_to_use = Set.new 95: nodes_to_delete = Set.new 96: passive_nodes = Set.new 97: 98: website.tree.node_access[:alcn].each do |alcn, node| 99: next if node == website.tree.dummy_root 100: 101: begin 102: used_paths.delete(node.node_info[:src]) 103: 104: src_path = find_all_source_paths[node.node_info[:src]] 105: if !src_path 106: nodes_to_delete << node 107: elsif (!node.flagged?(:created) && src_path.changed?) || node.meta_info_changed? 108: node.flag(:reinit) 109: paths_to_use << node.node_info[:src] 110: elsif node.changed? 111: # nothing to be done here but method node.changed? has to be called 112: end 113: 114: if src_path && src_path.passive? 115: passive_nodes << node 116: elsif src_path 117: referenced_nodes += node.node_info[:used_meta_info_nodes] + node.node_info[:used_nodes] 118: end 119: rescue Webgen::Error => e 120: e.alcn = node.alcn unless e.alcn 121: raise 122: rescue Exception => e 123: raise Webgen::Error.new(e, nil, node) 124: end 125: end 126: 127: # add unused passive nodes to node_to_delete set 128: unreferenced_passive_nodes, other_passive_nodes = passive_nodes.partition do |pnode| 129: !referenced_nodes.include?(pnode.alcn) 130: end 131: refs = other_passive_nodes.collect {|n| (n.node_info[:used_meta_info_nodes] + n.node_info[:used_nodes]).to_a}.flatten 132: unreferenced_passive_nodes.each {|n| nodes_to_delete << n if !refs.include?(n.alcn)} 133: 134: nodes_to_delete.each {|node| website.tree.delete_node(node)} 135: used_paths.merge(paths_to_use) 136: paths = create_nodes_from_paths(used_paths).collect {|n| n.node_info[:src]} 137: unused_paths.merge(used_paths - paths) 138: website.tree.node_access[:alcn].each {|name, node| website.tree.delete_node(node) if node.flagged?(:reinit)} 139: website.cache.reset_volatile_cache 140: end until used_paths.empty? 141: end
Write out all changed nodes of the website.tree.
# File lib/webgen/sourcehandler.rb, line 144 144: def write_tree 145: output = website.blackboard.invoke(:output_instance) 146: 147: website.tree.node_access[:alcn].select do |name, node| 148: use_node = (node != website.tree.dummy_root && node.flagged?(:dirty)) 149: node.unflag(:dirty_meta_info) 150: node.unflag(:created) 151: node.unflag(:dirty) 152: use_node 153: end.sort.each do |name, node| 154: begin 155: next if node['no_output'] || !(content = node.content) 156: 157: puts " "*4 + name, :verbose 158: type = if node.is_directory? 159: :directory 160: elsif node.is_fragment? 161: :fragment 162: else 163: :file 164: end 165: output.write(node.path, content, type) 166: rescue Webgen::Error => e 167: e.alcn = node.alcn unless e.alcn 168: raise 169: rescue Exception => e 170: raise Webgen::RenderError.new(e, nil, node) 171: end 172: end 173: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.