module Webgen::ContentProcessor::Blocks

Replaces special XML tags with the rendered content of a node block.

The module provides a ::call method so that it can be used by the content processor extension. However, it also provides the ::render_block method that contains the actual logic for rendering a block of a node given a render context.

Public Class Methods

call(context) click to toggle source

Replace the webgen:block xml tags with the rendered content of the specified node.

   # File lib/webgen/content_processor/blocks.rb
19 def self.call(context)
20   context.content.gsub!(BLOCK_RE) do |match|
21     attr = {}
22     match_object = $~
23     attr[:line_nr_proc] = lambda { match_object.pre_match.scan("\n").size + 1 }
24     match.scan(BLOCK_ATTR_RE) {|name, sep, content| attr[name.to_sym] = content}
25     render_block(context, attr)
26   end
27   context
28 end
render_block(context, options) click to toggle source

Render a block of a page node and return the result.

The Webgen::Context object context is used as the render context and the options hash needs to hold all relevant information, that is:

:name (mandatory)

The name of the block that should be used.

:chain

The node chain used for rendering. If this is not specified, the node chain from the context is used. It needs to be a String in the format '(A)LCN;(A)LCN;…' or an array of nodes.

:node

Defines which node in the node chain should be used. Valid values are next (= default value; the next node in the node chain), first (the first node in the node chain with a block called name) or current (the currently rendered node, ignores the chain option).

:notfound

If this property is set to ignore, a missing block will not raise an error. It is unset by default, so missing blocks will raise errors.

   # File lib/webgen/content_processor/blocks.rb
52 def self.render_block(context, options)
53   if options[:chain].nil?
54     used_chain = (context[:chain].length > 1 ? context[:chain][1..-1] : context[:chain].dup)
55   elsif options[:chain].kind_of?(Array)
56     used_chain = options[:chain]
57   else
58     paths = options[:chain].split(';')
59     used_chain = paths.collect do |path|
60       context.ref_node.resolve(path.strip, context.dest_node.lang, true)
61     end.compact
62     return '' if used_chain.length != paths.length
63   end
64   dest_node = context.dest_node
65 
66   if options[:node] == 'first'
67     used_chain.shift while used_chain.length > 0 && !used_chain.first.blocks.has_key?(options[:name])
68   elsif options[:node] == 'current'
69     used_chain = context[:chain].dup
70   end
71   block_node = used_chain.first
72 
73   if !block_node || !block_node.blocks.has_key?(options[:name])
74     if options[:notfound] == 'ignore'
75       return ''
76     elsif block_node
77       raise Webgen::RenderError.new("No block named '#{options[:name]}' found in <#{block_node}>",
78                                     'content_processor.blocks', context.dest_node,
79                                     context.ref_node, (options[:line_nr_proc].call if options[:line_nr_proc]))
80     else
81       raise Webgen::RenderError.new("No node in the render chain has a block named '#{options[:name]}'",
82                                     'content_processor.blocks', context.dest_node,
83                                     context.ref_node, (options[:line_nr_proc].call if options[:line_nr_proc]))
84     end
85   end
86 
87   tmp_context = block_node.render_block(options[:name], context.clone(:chain => used_chain, :dest_node => dest_node))
88   tmp_context.content
89 end