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/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
|
|