webby 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/webby/file.rb CHANGED
@@ -1,4 +1,4 @@
1
- # $Id: file.rb 2 2007-08-20 17:55:30Z tim_pease $
1
+ # $Id: file.rb 46 2007-11-27 03:31:29Z tim_pease $
2
2
 
3
3
  require 'yaml'
4
4
 
@@ -40,7 +40,7 @@ class File < ::File
40
40
  fd = new name, 'r'
41
41
  fd.read *args
42
42
  ensure
43
- fd.close
43
+ fd.close unless fd.nil?
44
44
  end
45
45
 
46
46
  # call-seq:
@@ -54,7 +54,7 @@ class File < ::File
54
54
  fd = new name, 'r'
55
55
  fd.readlines sep
56
56
  ensure
57
- fd.close
57
+ fd.close unless fd.nil?
58
58
  end
59
59
 
60
60
  # call-seq:
@@ -67,7 +67,7 @@ class File < ::File
67
67
  fd = new name, 'r'
68
68
  fd.meta_data
69
69
  ensure
70
- fd.close
70
+ fd.close unless fd.nil?
71
71
  end
72
72
  end
73
73
 
@@ -140,7 +140,7 @@ class File < ::File
140
140
  seek 0, IO::SEEK_END
141
141
  end
142
142
 
143
- %w(getc gets read read_nonblock readbytes readchar readline readlines readpartial scanf sysread).each do |m|
143
+ %w(getc gets read read_nonblock readbytes readchar readline readlines readpartial scanf).each do |m|
144
144
  self.class_eval <<-CODE
145
145
  def #{m}(*a)
146
146
  skip_meta_data
@@ -169,17 +169,14 @@ class File < ::File
169
169
  cur = tell
170
170
 
171
171
  seek 0
172
- line = readline
172
+ line = gets
173
173
  return unless META_SEP =~ line
174
174
 
175
- loop do
176
- line = readline
175
+ while line = gets
177
176
  break if META_SEP =~ line
178
177
  end
179
- return tell
180
-
181
- rescue EOFError
182
- return
178
+ return if line.nil?
179
+ tell
183
180
 
184
181
  ensure
185
182
  seek cur
data/lib/webby/main.rb CHANGED
@@ -1,4 +1,4 @@
1
- # $Id: main.rb 20 2007-08-28 23:24:14Z tim_pease $
1
+ # $Id: main.rb 35 2007-09-25 23:31:03Z tim_pease $
2
2
 
3
3
  require 'fileutils'
4
4
  require 'find'
@@ -34,6 +34,15 @@ class Main
34
34
  else m.create_site end
35
35
  end
36
36
 
37
+ # call-seq:
38
+ # Main.new
39
+ #
40
+ # Create a new Main webby object for building websites.
41
+ #
42
+ def initialize
43
+ @log = Logging::Logger[self]
44
+ end
45
+
37
46
  # call-seq:
38
47
  # parse( args ) => nil
39
48
  #
@@ -142,8 +151,7 @@ class Main
142
151
  # Prints a "creating _msg_" to the screen.
143
152
  #
144
153
  def creating( msg )
145
- print "creating "
146
- puts msg
154
+ @log.info "creating #{msg}"
147
155
  end
148
156
 
149
157
  # call-seq:
@@ -152,8 +160,7 @@ class Main
152
160
  # Prints a "updating _msg_" to the screen.
153
161
  #
154
162
  def updating( msg )
155
- print "updating "
156
- puts msg
163
+ @log.info "updating #{msg}"
157
164
  end
158
165
 
159
166
  # call-seq:
@@ -162,8 +169,7 @@ class Main
162
169
  # Prints an abort _msg_ to the screen and then exits the Ruby interpreter.
163
170
  #
164
171
  def abort( msg )
165
- puts msg
166
- puts "Aborting!"
172
+ @log.fatal msg
167
173
  exit 1
168
174
  end
169
175
 
@@ -1,56 +1,140 @@
1
- # $Id: pages_db.rb 18 2007-08-28 15:48:17Z tim_pease $
1
+ # $Id: pages_db.rb 46 2007-11-27 03:31:29Z tim_pease $
2
2
 
3
3
  module Webby
4
4
 
5
- #
5
+ # A rudimentary "database" for holding resource objects and finding them.
6
+ # The database is held in a Ruby hash keyed by the directories in the
7
+ # content folder.
6
8
  #
7
9
  class PagesDB
8
- include Enumerable
9
10
 
10
11
  # call-seq:
11
12
  # PagesDB.new
12
13
  #
14
+ # Create a new pages database object. This is used to store resources and
15
+ # to find them by their attributes.
16
+ #
13
17
  def initialize
14
18
  @db = Hash.new {|h,k| h[k] = []}
15
19
  end
16
20
 
17
21
  # call-seq:
18
- # add( resource )
22
+ # add( resource ) => resource
23
+ #
24
+ # Add the given _resource_ to the database. It will not be added a second
25
+ # time if it already exists in the database.
19
26
  #
20
27
  def add( page )
21
- @db[page.dir] << page
22
- self
28
+ ary = @db[page.dir]
29
+
30
+ # make sure we don't duplicate pages
31
+ ary.delete page if ary.include? page
32
+ ary << page
33
+
34
+ page
23
35
  end
24
36
  alias :<< :add
25
37
 
26
38
  # call-seq:
27
- # clear
39
+ # clear => self
40
+ #
41
+ # Removes all resources from the database.
28
42
  #
29
43
  def clear
30
44
  @db.clear
45
+ self
31
46
  end
32
47
 
33
48
  # call-seq:
34
49
  # each {|resource| block}
35
50
  #
51
+ # Iterate over each resource in the database and pass it to the given
52
+ # block.
53
+ #
36
54
  def each( &b )
37
55
  keys = @db.keys.sort
38
56
  keys.each do |k|
39
57
  @db[k].sort.each(&b)
40
58
  end
59
+ self
41
60
  end
42
61
 
43
62
  # call-seq:
44
- # find_by_name( name )
63
+ # find( opts = {} ) => resource or nil
64
+ # find( opts = {} ) {|resource| block} => resource or nil
65
+ #
66
+ # Find a specific resource in the database. A resource can be found using
67
+ # any combination of attributes by passing them in as options to the
68
+ # +find+ method. This will used simple equality comparison to find the
69
+ # resource.
70
+ #
71
+ # For more complex finders, a block should be supplied. The usage
72
+ # follows that of of the Enumerable#find method. The method will return
73
+ # the first resource for which the block returns true.
74
+ #
75
+ # If the :all option is given as true, then all resources that match the
76
+ # finder criteria will be returned in an array. If none are found, an
77
+ # empty array will be returned.
78
+ #
79
+ # Options include:
80
+ #
81
+ # :all => true
82
+ # :in_directory => 'directory'
45
83
  #
46
- def find_by_name( name )
47
- self.find {|page| page.filename == name}
84
+ # Examples:
85
+ #
86
+ # # find the "index" resource in the "foo/bar" directory
87
+ # pages_db.find( :filename => 'index', :in_directory => 'foo/bar' )
88
+ #
89
+ # # find all resources named "widgets" whose color is "blue"
90
+ # pages_db.find( :name => 'widgets', :color => 'blue', :all => true )
91
+ #
92
+ # # find all resources created in the past week
93
+ # pages_db.find( :all => true ) do |resource|
94
+ # resource.created_at > Time.now - (7 * 24 * 3600)
95
+ # end
96
+ #
97
+ def find( opts = {}, &block )
98
+ find_all = if opts.has_key?(:all) then opts.delete(:all)
99
+ else false end
100
+
101
+ dir = if opts.has_key?(:in_directory) then opts.delete(:in_directory)
102
+ else nil end
103
+ if dir && !@db.has_key?(dir)
104
+ raise RuntimeError, "unknown directory '#{dir}'"
105
+ end
106
+
107
+ block ||= lambda do |page|
108
+ found = true
109
+ opts.each do |key, value|
110
+ found &&= page.__send__(key.to_sym) == value
111
+ break if not found
112
+ end
113
+ found
114
+ end
115
+
116
+ ary = []
117
+ search = dir ? @db[dir] : self
118
+ search.each do |page|
119
+ if block.call(page)
120
+ ary << page
121
+ break unless find_all
122
+ end
123
+ end
124
+
125
+ return ary if find_all
126
+ return ary.first
48
127
  end
49
128
 
50
129
  # call-seq:
51
130
  # siblings( page, opts = {} ) => array
52
131
  #
132
+ # Returns an array of resources that are siblings of the given _page_
133
+ # resource. A sibling is any resource that is in the same directory as the
134
+ # _page_.
135
+ #
53
136
  # Options include:
137
+ #
54
138
  # :sorty_by => 'attribute'
55
139
  # :reverse => true
56
140
  #
@@ -60,7 +144,7 @@ class PagesDB
60
144
  return ary unless opts.has_key? :sort_by
61
145
 
62
146
  m = opts[:sort_by]
63
- ary.sort! {|a,b| a.send(m) <=> b.send(m)}
147
+ ary.sort! {|a,b| a.__send__(m) <=> b.__send__(m)}
64
148
  ary.reverse! if opts[:reverse]
65
149
  ary
66
150
  end
@@ -68,7 +152,12 @@ class PagesDB
68
152
  # call-seq:
69
153
  # children( page, opts = {} ) => array
70
154
  #
155
+ # Returns an array of resources that are children of the given _page_
156
+ # resource. A child is any resource that exists in a subdirectory of the
157
+ # page's directory.
158
+ #
71
159
  # Options include:
160
+ #
72
161
  # :sorty_by => 'attribute'
73
162
  # :reverse => true
74
163
  #
@@ -82,7 +171,7 @@ class PagesDB
82
171
  return ary unless opts.has_key? :sort_by
83
172
 
84
173
  m = opts[:sort_by]
85
- ary.sort! {|a,b| a.send(m) <=> b.send(m)}
174
+ ary.sort! {|a,b| a.__send__(m) <=> b.__send__(m)}
86
175
  ary.reverse! if opts[:reverse]
87
176
  ary
88
177
  end
@@ -1,8 +1,10 @@
1
- # $Id: renderer.rb 27 2007-09-18 18:09:25Z tim_pease $
1
+ # $Id: renderer.rb 46 2007-11-27 03:31:29Z tim_pease $
2
2
 
3
3
  require 'erb'
4
4
  try_require 'bluecloth'
5
5
  try_require 'redcloth'
6
+ try_require 'haml'
7
+ try_require 'sass'
6
8
 
7
9
  module Webby
8
10
 
@@ -11,7 +13,7 @@ module Webby
11
13
  #
12
14
  # A page is filtered based on the settings of the 'filter' option in the
13
15
  # page's meta-data information. For example, if 'textile' is specified as
14
- # a filter, then the page will be run through the RedCloth markup filer.
16
+ # a filter, then the page will be run through the RedCloth markup filter.
15
17
  # More than one filter can be used on a page; they will be run in the
16
18
  # order specified in the meta-data.
17
19
  #
@@ -21,6 +23,24 @@ module Webby
21
23
  class Renderer
22
24
  include ERB::Util
23
25
 
26
+ # call-seq:
27
+ # Renderer.write( page )
28
+ #
29
+ # Render the given _page_ and write the resulting output to the page's
30
+ # destination. If the _page_ uses pagination, then multiple destination
31
+ # files will be created -- one for each paginated data set in the page.
32
+ #
33
+ def self.write( page )
34
+ renderer = self.new(page)
35
+
36
+ loop {
37
+ ::File.open(page.destination, 'w') do |fd|
38
+ fd.write renderer.layout_page
39
+ end
40
+ break unless renderer.next_page
41
+ }
42
+ end
43
+
24
44
  # call-seq:
25
45
  # Renderer.new( page )
26
46
  #
@@ -37,6 +57,8 @@ class Renderer
37
57
  @page = page
38
58
  @pages = Resource.pages
39
59
  @content = nil
60
+
61
+ @log = Logging::Logger[self]
40
62
  end
41
63
 
42
64
  # call-seq:
@@ -50,10 +72,10 @@ class Renderer
50
72
  def layout_page
51
73
  layouts = Resource.layouts
52
74
  obj = @page
53
- str = @page.render
75
+ str = @page.render(self)
54
76
 
55
77
  loop do
56
- lyt = layouts.find_by_name obj.layout
78
+ lyt = layouts.find :filename => obj.layout
57
79
  break if lyt.nil?
58
80
 
59
81
  @content, str = str, ::Webby::File.read(lyt.path)
@@ -84,6 +106,49 @@ class Renderer
84
106
  str
85
107
  end
86
108
 
109
+ # call-seq:
110
+ # paginate( items, per_page ) {|item| block}
111
+ #
112
+ # Iterate the given _block_ for each item selected from the _items_ array
113
+ # using the given number of items _per_page_. The first time the page is
114
+ # rendered, the items passed to the block are selected using the range
115
+ # (0...per_page). The next rendering selects (per_page...2*per_page). This
116
+ # continues until all _items_ have been paginated.
117
+ #
118
+ # Calling this method creates a <code>@pager</code> object that can be
119
+ # accessed from the _page_. The <code>@pager</code> contains information
120
+ # about the next page, the current page number, the previous page, and the
121
+ # number of items in the current page.
122
+ #
123
+ def paginate( items, count, &block )
124
+ @pager ||= Paginator.new(items.length, count, @page) do |offset, per_page|
125
+ items[offset,per_page]
126
+ end.first
127
+
128
+ @pager.each &block
129
+ end
130
+
131
+ # call-seq:
132
+ # next_page => true or false
133
+ #
134
+ # Returns +true+ if there is a next page to render. Returns +false+ if
135
+ # there is no next page or if pagination has not been configured for the
136
+ # current page.
137
+ #
138
+ def next_page
139
+ return false unless defined? @pager and @pager
140
+
141
+ # go to the next page; break out if there is no next page
142
+ if @pager.next?
143
+ @pager = @pager.next
144
+ else
145
+ @page.number = nil
146
+ return false
147
+ end
148
+
149
+ true
150
+ end
151
+
87
152
  # Render text via ERB using the built in ERB library.
88
153
  #
89
154
  def erb_filter( str )
@@ -96,7 +161,7 @@ class Renderer
96
161
  def markdown_filter( str )
97
162
  BlueCloth.new(str).to_html
98
163
  rescue NameError
99
- $stderr.puts 'ERROR: markdown filter failed (BlueCloth not installed?)'
164
+ @log.error 'markdown filter failed (BlueCloth not installed?)'
100
165
  exit
101
166
  end
102
167
 
@@ -105,7 +170,7 @@ class Renderer
105
170
  def textile_filter( str )
106
171
  RedCloth.new(str).to_html
107
172
  rescue NameError
108
- $stderr.puts 'ERROR: textile filter failed (RedCloth not installed?)'
173
+ @log.error 'textile filter failed (RedCloth not installed?)'
109
174
  exit
110
175
  end
111
176
 
@@ -114,7 +179,29 @@ class Renderer
114
179
  def coderay_filter( str )
115
180
  CodeRayFilter.new(str).to_html
116
181
  rescue NameError
117
- $stderr.puts "ERROR: coderay filter failed (CodeRay not installed?)"
182
+ @log.error 'coderay filter failed (CodeRay not installed?)'
183
+ exit
184
+ end
185
+
186
+ # Render text via the Haml library
187
+ #
188
+ def haml_filter( str )
189
+ opts = @page.haml_options || {}
190
+ opts[:locals] ||= {}
191
+ opts[:locals].merge!({:page => @page, :pages => @pages})
192
+ Haml::Engine.new(str, opts).to_html
193
+ rescue NameError
194
+ @log.error 'haml filter failed (Haml not installed?)'
195
+ exit
196
+ end
197
+
198
+ # Render text via the Sass library (part of Haml)
199
+ #
200
+ def sass_filter( str )
201
+ opts = @page.sass_options || {}
202
+ Sass::Engine.new(str, opts).render
203
+ rescue NameError
204
+ @log.error 'sass filter failed (Haml not installed?)'
118
205
  exit
119
206
  end
120
207