Parent

Class/Module Index [+]

Quicksearch

Webgen::ContentProcessor::Tags

Processes special webgen tags to provide dynamic content.

webgen tags are an easy way to add dynamically generated content to websites, for example menus or breadcrumb trails.

Public Instance Methods

call(context) click to toggle source

Replace all webgen tags in the content of context with the rendered content.

# File lib/webgen/contentprocessor/tags.rb, line 23
def call(context)
  replace_tags(context) do |tag, param_string, body|
    log(:debug) { "Replacing tag #{tag} with data '#{param_string}' and body '#{body}' in <#{context.ref_node}>" }
    process_tag(tag, param_string, body, context)
  end
  context
end
process_tag(tag, params, body, context) click to toggle source

Process the tag and return the result. The parameter params needs to be a Hash holding all needed and optional parameters for the tag or a parameter String in YAML format and body is the optional body for the tag. context needs to be a valid Webgen::Context object.

# File lib/webgen/contentprocessor/tags.rb, line 34
def process_tag(tag, params, body, context)
  result = ''
  processor = processor_for_tag(tag)
  if !processor.nil?
    params = if params.kind_of?(String)
               processor.create_tag_params(params, context.ref_node)
             else
               processor.create_params_hash(params, context.ref_node)
             end

    processor.set_params(params)
    result, process_output = processor.call(tag, body, context)
    processor.set_params(nil)
    result = call(context.clone(:content => result)).content if process_output
  else
    raise Webgen::RenderError.new("No tag processor for '#{tag}' found", self.class.name,
                                  context.dest_node, context.ref_node)
  end
  result
end

Private Instance Methods

processor_for_tag(tag) click to toggle source

Return the tag processor for tag or nil if tag is unknown.

# File lib/webgen/contentprocessor/tags.rb, line 155
def processor_for_tag(tag)
  map = website.config['contentprocessor.tags.map']
  klass = if map.has_key?(tag)
            map[tag]
          elsif map.has_key?(:default)
            map[:default]
          else
            nil
          end
  klass.nil? ? nil : website.cache.instance(klass)
end
replace_tags(context) click to toggle source

Return the context.content provided by context.ref_node with all webgen tags replaced. When a webgen tag is encountered by the parser, the method yields all found information and substitutes the returned string for the tag.

# File lib/webgen/contentprocessor/tags.rb, line 67
def replace_tags(context) #:yields: tag_name, param_string, body
  scanner = StringScanner.new(context.content)
  data = ProcessingStruct.new(:before_tag)
  while true
    case data.state
    when :before_tag
      if scanner.skip_until(@start_re)
        data.state = :in_start_tag
        data.backslashes = scanner[1].length
        data.brackets = 1
        data.tag = scanner[2]
        data.simple_tag = (scanner[3] == ':')
        data.params_start_pos = scanner.pos
        data.start_pos = scanner.pos - scanner.matched.length
      else
        data.state = :done
      end

    when :in_start_tag
      data.brackets += (scanner[1] == '{' ? 1 : -1) while data.brackets != 0 && scanner.skip_until(BRACKETS_RE)
      if data.brackets != 0
        raise Webgen::RenderError.new("Unbalanced curly brackets for tag '#{data.tag}'", self.class.name,
                                      context.dest_node, context.ref_node)
      else
        data.params_end_pos = data.body_end_pos = data.end_pos = scanner.pos - 1
        data.state = (data.simple_tag ? :process : :in_body)
      end

    when :process
      if RUBY_VERSION >= '1.9'
        begin
          enc = scanner.string.encoding
          scanner.string.force_encoding('ASCII-8BIT')
          if data.backslashes % 2 == 0
            result = yield(data.tag, scanner.string[data.params_start_pos...data.params_end_pos].force_encoding(enc),
                           scanner.string[(data.params_end_pos+1)...data.body_end_pos].to_s.force_encoding(enc)).to_s
            scanner.string[data.start_pos..data.end_pos] = "\\" * (data.backslashes / 2) + result.force_encoding('ASCII-8BIT')
            scanner.pos = data.start_pos + result.length
          else
            scanner.string[data.start_pos, 1 + data.backslashes / 2] = ''
            scanner.pos -= 1 + data.backslashes / 2
          end
        ensure
          scanner.string.force_encoding(enc) if RUBY_VERSION >= '1.9'
        end
      else
        if data.backslashes % 2 == 0
          result = yield(data.tag, scanner.string[data.params_start_pos...data.params_end_pos],
                         scanner.string[(data.params_end_pos+1)...data.body_end_pos]).to_s
          scanner.string[data.start_pos..data.end_pos] = "\\" * (data.backslashes / 2) + result
          scanner.pos = data.start_pos + result.length
        else
          scanner.string[data.start_pos, 1 + data.backslashes / 2] = ''
          scanner.pos -= 1 + data.backslashes / 2
        end
      end
      data.state = :before_tag

    when :in_body
      while (result = scanner.skip_until(@end_re))
        next unless scanner[2] == data.tag
        if scanner[1].length % 2 == 1
          scanner.string[(scanner.pos - scanner.matched.length), 1 + scanner[1].length / 2] = ''
          scanner.pos -= 1 + scanner[1].length / 2
        else
          break
        end
      end
      if result
        data.state = :process
        data.end_pos = scanner.pos - 1
        data.body_end_pos = scanner.pos - scanner.matched.length + scanner[1].length / 2
      else
        raise Webgen::RenderError.new("Invalid body part - no end tag found for '#{data.tag}'", self.class.name,
                                      context.dest_node, context.ref_node)
      end

    when :done
      break
    end
  end
  scanner.string
rescue Webgen::RenderError => e
  e.line = scanner.string[0...scanner.pos].scan("\n").size + 1 unless e.line
  raise
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.