webby 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/Manifest.txt +6 -0
- data/README.txt +10 -9
- data/Rakefile +2 -0
- data/bin/webby +1 -0
- data/data/content/css/site.css +59 -0
- data/data/layouts/default.rhtml +9 -9
- data/data/tasks/create.rake +1 -0
- data/data/tasks/growl.rake +12 -0
- data/data/tasks/heel.rake +12 -6
- data/lib/webby.rb +35 -2
- data/lib/webby/auto_builder.rb +14 -6
- data/lib/webby/builder.rb +31 -23
- data/lib/webby/file.rb +9 -12
- data/lib/webby/main.rb +13 -7
- data/lib/webby/pages_db.rb +101 -12
- data/lib/webby/renderer.rb +94 -7
- data/lib/webby/resource.rb +46 -13
- data/lib/webby/stelan/paginator.rb +149 -0
- data/lib/webby/stelan/spawner.rb +337 -0
- data/spec/webby/file_spec.rb +1 -2
- data/website/Rakefile +2 -0
- data/website/content/css/coderay.css +111 -0
- data/website/content/css/site.css +121 -25
- data/website/content/download.txt +7 -1
- data/website/content/index.txt +7 -9
- data/website/content/manual.txt +23 -0
- data/website/content/robots.txt +6 -0
- data/website/content/tips_and_tricks.txt +2 -2
- data/website/content/tutorial.txt +8 -8
- data/website/layouts/default.rhtml +16 -13
- data/website/tasks/create.rake +2 -0
- data/website/tasks/growl.rake +12 -0
- data/website/tasks/heel.rake +12 -6
- metadata +19 -4
data/lib/webby/file.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: file.rb
|
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
|
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 =
|
172
|
+
line = gets
|
173
173
|
return unless META_SEP =~ line
|
174
174
|
|
175
|
-
|
176
|
-
line = readline
|
175
|
+
while line = gets
|
177
176
|
break if META_SEP =~ line
|
178
177
|
end
|
179
|
-
return
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
166
|
-
puts "Aborting!"
|
172
|
+
@log.fatal msg
|
167
173
|
exit 1
|
168
174
|
end
|
169
175
|
|
data/lib/webby/pages_db.rb
CHANGED
@@ -1,56 +1,140 @@
|
|
1
|
-
# $Id: pages_db.rb
|
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]
|
22
|
-
|
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
|
-
#
|
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
|
-
|
47
|
-
|
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.
|
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.
|
174
|
+
ary.sort! {|a,b| a.__send__(m) <=> b.__send__(m)}
|
86
175
|
ary.reverse! if opts[:reverse]
|
87
176
|
ary
|
88
177
|
end
|
data/lib/webby/renderer.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
# $Id: renderer.rb
|
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
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
|