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.



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

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

Instance Attribute Details

#blocksObject (readonly)

The hash of blocks for the page.



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

def blocks
  @blocks
end

#meta_infoObject (readonly)

The contents of the meta information block.



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

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.



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

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:



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
97
# File 'lib/webgen/page.rb', line 69

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 : Utils.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.



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

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 = Utils.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.



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

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