Class: Webgen::Page

Inherits:
Object
  • Object
show all
Defined in:
lib/webgen/page.rb

Overview

A Page object wraps a meta information hash and a hash of name => block content associations.

It is normally generated from a file or string in Webgen Page Format using the provided class methods.

Defined Under Namespace

Classes: FormatError

Constant Summary collapse

RE_NEWLINE =

:stopdoc:

/\r?\n/
RE_META_INFO_START =
/\A---[ \t]*#{RE_NEWLINE}/
RE_META_INFO =
/#{RE_META_INFO_START}.*?#{RE_NEWLINE}(?=---.*?#{RE_NEWLINE}|\Z)/m
RE_BLOCKS_START_SIMPLE =
/^---[ \t]*$|^---[ \t]+(\w+)[ \t]*(?:[ \t]+-+[ \t]*)?$|^$/
RE_BLOCKS_START_COMPLEX =
/^---[ \t]+?(?:[ \t]*((?:\w+:\S*[ \t]*)*))?(?:[ \t]+-+[ \t]*)?$/
RE_BLOCKS_START =
/^---(?:[ \t]+.*?|)(?=#{RE_NEWLINE})/
RE_BLOCKS =
/(?:(#{RE_BLOCKS_START})|\A)#{RE_NEWLINE}?(.*?)(?:(?=#{RE_BLOCKS_START})|\z)/m
RE_PAGE =
/(#{RE_META_INFO})?(.*)/m

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(meta_info = {}, blocks = {}) ⇒ Page

Create a new Page object with the meta information provided in meta_info and the given blocks.



110
111
112
113
# File 'lib/webgen/page.rb', line 110

def initialize(meta_info = {}, blocks = {})
  @meta_info = meta_info
  @blocks = blocks
end

Instance Attribute Details

#blocksObject (readonly)

The hash of blocks for the page.



106
107
108
# File 'lib/webgen/page.rb', line 106

def blocks
  @blocks
end

#meta_infoObject (readonly)

The contents of the meta information block.



103
104
105
# File 'lib/webgen/page.rb', line 103

def meta_info
  @meta_info
end

Class Method Details

.from_data(data) ⇒ Object

Parse the given string data in Webgen Page Format.

This method returns a Page object containing the hash with the meta information and the parsed blocks.



36
37
38
39
40
41
# File 'lib/webgen/page.rb', line 36

def from_data(data)
  md = RE_PAGE.match(data)
  meta_info = parse_meta_info(md[1], data =~ RE_META_INFO_START)
  blocks = parse_blocks(md[2] || '', meta_info)
  new(meta_info, blocks)
end

.parse_blocks(data, meta_info) ⇒ Object

Parse all blocks in data and return them.

The key ‘blocks’ of the meta information hash is updated with information found on block starting lines.

Raises:



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/webgen/page.rb', line 68

def parse_blocks(data, meta_info)
  scanned = data.scan(RE_BLOCKS)
  raise(FormatError, 'No content blocks specified') if scanned.length == 0

  blocks = {}
  scanned.each_with_index do |block_data, index|
    index += 1
    options, content = *block_data
    if md = RE_BLOCKS_START_SIMPLE.match(options.to_s)
      options = {'name' => md[1]}
    else
      md = RE_BLOCKS_START_COMPLEX.match(options.to_s)
      raise(FormatError, "Found invalid blocks starting line for block #{index}: #{options}") if content =~ /\A---/ || md.nil?
      options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, (v == '' ? nil : YAML::load(v))]}.flatten]
    end

    name = options.delete('name') || (index == 1 ? 'content' : 'block' + (index).to_s)
    raise(FormatError, "Previously used name '#{name}' also used for block #{index}") if blocks.has_key?(name)
    content ||= ''
    content.gsub!(/^(\\+)(---.*?)$/) {|m| "\\" * ($1.length / 2) + $2}
    content.chomp! unless index == scanned.length

    blocks[name] = content
    ((meta_info['blocks'] ||= {})[name] ||= {}).merge!(options) unless options.empty?
  end
  meta_info['blocks'].delete_if {|k,v| v.empty?} if meta_info.has_key?('blocks')
  meta_info.delete('blocks') if meta_info.has_key?('blocks') && meta_info['blocks'].empty?
  blocks
end

.parse_meta_info(mi_data, has_mi_start) ⇒ Object

Parse the meta info string in mi_data and return the hash with the meta information. The original data is used for checking the validness of the meta information block.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/webgen/page.rb', line 45

def parse_meta_info(mi_data, has_mi_start)
  if mi_data.nil? && has_mi_start
    raise FormatError, 'Found start line for meta information block but no valid meta information block'
  elsif mi_data.nil?
    {}
  else
    begin
      meta_info = YAML::load(mi_data.to_s)
      unless meta_info.kind_of?(Hash)
        raise FormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
      end
    rescue ArgumentError, SyntaxError, YAML::SyntaxError => e
      raise FormatError, "Invalid YAML syntax in meta information block: #{e.message}"
    end
    meta_info
  end
end

Instance Method Details

#to_sObject

Convert the Page object back into a string.



116
117
118
119
120
121
122
123
# File 'lib/webgen/page.rb', line 116

def to_s
  str = ""
  str << @meta_info.to_yaml
  blocks.each do |name, value|
    str << "--- #{name}\n" << value.gsub(/^---.*?$/) {|m| "\\#{m}" } << (value =~ /\n$/ ? "" : "\n")
  end
  str
end