Class: Webgen::ContentProcessor::Blocks

Inherits:
Object
  • Object
show all
Includes:
Loggable
Defined in:
lib/webgen/contentprocessor/blocks.rb

Overview

Replaces special xml tags with the rendered content of a node.

Constant Summary collapse

BLOCK_RE =
/<webgen:block\s*?((?:\s\w+=('|")[^'"]+\2)+)\s*\/>/
BLOCK_ATTR_RE =
/(\w+)=('|")([^'"]+)\2/

Instance Method Summary collapse

Methods included from Loggable

#log, #puts

Instance Method Details

#call(context) ⇒ Object

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



14
15
16
17
18
19
20
21
# File 'lib/webgen/contentprocessor/blocks.rb', line 14

def call(context)
  context.content.gsub!(BLOCK_RE) do |match|
    attr = {}
    match.scan(BLOCK_ATTR_RE) {|name, sep, content| attr[name.to_sym] = content}
    render_block(context, attr)
  end
  context
end

#render_block(context, options) ⇒ Object

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.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/webgen/contentprocessor/blocks.rb', line 41

def render_block(context, options)
  if options[:chain].nil?
    used_chain = (context[:chain].length > 1 ? context[:chain][1..-1] : context[:chain]).dup
  elsif options[:chain].kind_of?(Array)
    used_chain = options[:chain]
  else
    paths = options[:chain].split(';')
    used_chain = paths.collect do |path|
      temp_node = context.ref_node.resolve(path.strip, context.dest_node.lang)
      if temp_node.nil?
        context.dest_node.flag(:dirty)
        log(:error) { "Could not resolve <#{path.strip}> in <#{context.ref_node.alcn}> while rendering blocks" }
      end
      temp_node
    end.compact
    return '' if used_chain.length != paths.length
    dest_node = context.content_node
  end

  if options[:node] == 'first'
    used_chain.shift while used_chain.length > 0 && !used_chain.first.node_info[:page].blocks.has_key?(options[:name])
  elsif options[:node] == 'current'
    used_chain = context[:chain].dup
  end
  block_node = used_chain.first

  if !block_node || !block_node.node_info[:page].blocks.has_key?(options[:name])
    if options[:notfound] == 'ignore'
      return ''
    elsif block_node
      raise "Node <#{block_node.alcn}> has no block named '#{options[:name]}'"
    else
      raise "No node in the chain has a block named '#{options[:name]}'"
    end
  end

  context.dest_node.node_info[:used_nodes] << block_node.alcn
  tmp_context = block_node.node_info[:page].blocks[options[:name]].render(context.clone(:chain => used_chain, :dest_node => dest_node))
  tmp_context.content
end