webby 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +44 -0
- data/README.txt +50 -0
- data/Rakefile +29 -0
- data/bin/webby +14 -0
- data/data/Rakefile +6 -0
- data/data/content/css/blueprint/License.txt +21 -0
- data/data/content/css/blueprint/Readme.txt +93 -0
- data/data/content/css/blueprint/lib/buttons.css +112 -0
- data/data/content/css/blueprint/lib/compressed.css +127 -0
- data/data/content/css/blueprint/lib/grid.css +177 -0
- data/data/content/css/blueprint/lib/img/baseline-black.png +0 -0
- data/data/content/css/blueprint/lib/img/baseline.png +0 -0
- data/data/content/css/blueprint/lib/img/grid.png +0 -0
- data/data/content/css/blueprint/lib/img/icons/cross.png +0 -0
- data/data/content/css/blueprint/lib/img/icons/textfield_key.png +0 -0
- data/data/content/css/blueprint/lib/img/icons/tick.png +0 -0
- data/data/content/css/blueprint/lib/reset.css +37 -0
- data/data/content/css/blueprint/lib/typography.css +159 -0
- data/data/content/css/blueprint/print.css +75 -0
- data/data/content/css/blueprint/screen.css +34 -0
- data/data/content/css/site.css +0 -0
- data/data/content/index.rhtml +18 -0
- data/data/layouts/default.rhtml +55 -0
- data/data/tasks/create.rake +7 -0
- data/data/templates/page.erb +18 -0
- data/lib/webby.rb +67 -0
- data/lib/webby/auto_builder.rb +75 -0
- data/lib/webby/builder.rb +165 -0
- data/lib/webby/file.rb +191 -0
- data/lib/webby/main.rb +129 -0
- data/lib/webby/pages_db.rb +70 -0
- data/lib/webby/renderer.rb +94 -0
- data/lib/webby/resource.rb +174 -0
- data/lib/webby/utils.rb +24 -0
- data/lib/webby/webby_task.rb +136 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/webby/file_spec.rb +107 -0
- data/tasks/doc.rake +60 -0
- data/tasks/gem.rake +112 -0
- data/tasks/manifest.rake +39 -0
- data/tasks/setup.rb +108 -0
- data/tasks/spec.rake +37 -0
- metadata +128 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
# $Id: resource.rb 5 2007-08-22 04:25:49Z tim_pease $
|
2
|
+
|
3
|
+
module Webby
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
class Resource
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def pages
|
11
|
+
@pages ||= PagesDB.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def layouts
|
15
|
+
@layouts ||= PagesDB.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear
|
19
|
+
self.pages.clear
|
20
|
+
self.layouts.clear
|
21
|
+
end
|
22
|
+
end # class << self
|
23
|
+
|
24
|
+
# call-seq:
|
25
|
+
# Resource.new( filename, defaults = {} ) => page
|
26
|
+
#
|
27
|
+
def initialize( fn, defaults = {} )
|
28
|
+
@path = fn.sub(%r/\A(?:\.\/|\/)/o, '').freeze
|
29
|
+
@dir = ::File.dirname(@path).sub(%r/\A[^\/]+\/?/o, '')
|
30
|
+
@filename = ::File.basename(@path).sub(%r/\.\w+\z/o, '')
|
31
|
+
@ext = ::File.extname(@path).sub(%r/\A\.?/o, '')
|
32
|
+
@mtime = ::File.mtime @path
|
33
|
+
|
34
|
+
@rendering = false
|
35
|
+
|
36
|
+
# deal with the meta-data
|
37
|
+
@mdata = ::Webby::File.meta_data(@path)
|
38
|
+
@have_mdata = !@mdata.nil?
|
39
|
+
@mdata = @have_mdata ? defaults.merge(@mdata) : {}
|
40
|
+
@mdata.sanitize!
|
41
|
+
|
42
|
+
self.class.pages << self if is_page? or is_static?
|
43
|
+
self.class.layouts << self if is_layout?
|
44
|
+
end
|
45
|
+
|
46
|
+
# call-seq:
|
47
|
+
# equal?( other ) => true or false
|
48
|
+
#
|
49
|
+
def equal?( other )
|
50
|
+
return false unless self.class == other.class
|
51
|
+
@path == other.path
|
52
|
+
end
|
53
|
+
alias :== :equal?
|
54
|
+
alias :eql? :equal?
|
55
|
+
|
56
|
+
# call-seq:
|
57
|
+
# resource <=> other => -1, 0, +1, or nil
|
58
|
+
#
|
59
|
+
def <=>( other )
|
60
|
+
return unless self.class == other.class
|
61
|
+
@path <=> other.path
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
attr_reader :path, :dir, :filename, :mtime, :ext
|
66
|
+
|
67
|
+
# call-seq:
|
68
|
+
# extension => string
|
69
|
+
#
|
70
|
+
def extension
|
71
|
+
return @mdata['extension'] if @mdata.has_key? 'extension'
|
72
|
+
|
73
|
+
if @mdata.has_key? 'layout'
|
74
|
+
lyt = self.class.layouts.find_by_name @mdata['layout']
|
75
|
+
break if lyt.nil?
|
76
|
+
return lyt.extension
|
77
|
+
end
|
78
|
+
|
79
|
+
@ext
|
80
|
+
end
|
81
|
+
|
82
|
+
def destination
|
83
|
+
return @destination if defined? @destination
|
84
|
+
return @destination = ::Webby.config['output_dir'] if is_layout?
|
85
|
+
|
86
|
+
@destination = File.join(::Webby.config['output_dir'], dir, filename)
|
87
|
+
@destination << '.'
|
88
|
+
@destination << extension
|
89
|
+
@destination
|
90
|
+
end
|
91
|
+
|
92
|
+
# call-seq:
|
93
|
+
# render => string
|
94
|
+
#
|
95
|
+
def render
|
96
|
+
raise Error, "page '#@path' is in a rendering loop" if @rendering
|
97
|
+
|
98
|
+
@rendering = true
|
99
|
+
content = Renderer.new(self).render_page
|
100
|
+
@rendering = false
|
101
|
+
|
102
|
+
return content
|
103
|
+
|
104
|
+
rescue
|
105
|
+
@rendering = false
|
106
|
+
raise
|
107
|
+
end
|
108
|
+
|
109
|
+
# call-seq:
|
110
|
+
# is_layout? => true or false
|
111
|
+
#
|
112
|
+
# Returns +true+ if this resource is a layout.
|
113
|
+
#
|
114
|
+
def is_layout?
|
115
|
+
@is_layout ||=
|
116
|
+
!(%r/\A(?:\.\/|\/)?#{::Webby.config['layout_dir']}\//o =~ @path).nil?
|
117
|
+
end
|
118
|
+
|
119
|
+
# call-seq:
|
120
|
+
# is_static? => true or false
|
121
|
+
#
|
122
|
+
# Returns +true+ if this resource is a static file.
|
123
|
+
#
|
124
|
+
def is_static?
|
125
|
+
!@have_mdata
|
126
|
+
end
|
127
|
+
|
128
|
+
# call-seq:
|
129
|
+
# is_page? => true or false
|
130
|
+
#
|
131
|
+
# Returns +true+ if this resource is a page suitable for rendering.
|
132
|
+
#
|
133
|
+
def is_page?
|
134
|
+
@have_mdata and !is_layout?
|
135
|
+
end
|
136
|
+
|
137
|
+
# call-seq:
|
138
|
+
# dirty? => true or false
|
139
|
+
#
|
140
|
+
# Returns +true+ if this resource is newer than its corresponding output
|
141
|
+
# product. The resource needs to be rendered (if a page or layout) or
|
142
|
+
# copied (if a static file) to the output directory.
|
143
|
+
#
|
144
|
+
def dirty?
|
145
|
+
return @mdata['dirty'] if @mdata.has_key? 'dirty'
|
146
|
+
|
147
|
+
# if the destination file does not exist, then we are dirty
|
148
|
+
return @mdata['dirty'] = true unless test ?e, destination
|
149
|
+
|
150
|
+
# if this file's mtime is larger than the destination file's
|
151
|
+
# mtime, then we are dirty
|
152
|
+
@mdata['dirty'] = @mtime > File.mtime(destination)
|
153
|
+
return @mdata['dirty'] if is_static? or @mdata['dirty']
|
154
|
+
|
155
|
+
# check to see if the layout is dirty, and it it is then we
|
156
|
+
# are dirty, too
|
157
|
+
if @mdata.has_key? 'layout'
|
158
|
+
lyt = self.class.layouts.find_by_name @mdata['layout']
|
159
|
+
break if lyt.nil?
|
160
|
+
return @mdata['dirty'] = true if lyt.dirty?
|
161
|
+
end
|
162
|
+
|
163
|
+
# if we got here, then we are not dirty
|
164
|
+
@mdata['dirty'] = false
|
165
|
+
end
|
166
|
+
|
167
|
+
def method_missing( name, *a, &b )
|
168
|
+
@mdata[name.to_s]
|
169
|
+
end
|
170
|
+
|
171
|
+
end # class Resource
|
172
|
+
end # module Webby
|
173
|
+
|
174
|
+
# EOF
|
data/lib/webby/utils.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# $Id: utils.rb 1 2007-08-18 21:39:50Z tim_pease $
|
2
|
+
|
3
|
+
module Enumerable
|
4
|
+
def injecting( initial )
|
5
|
+
inject(initial) do |memo, obj|
|
6
|
+
yield(memo, obj); memo
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Hash
|
12
|
+
def sanitize!
|
13
|
+
h = self.injecting({}) do |h, (k, v)|
|
14
|
+
h[k] = case v
|
15
|
+
when 'none', 'nil': nil
|
16
|
+
when 'true', 'yes': true
|
17
|
+
when 'false', 'no': false
|
18
|
+
else v end
|
19
|
+
end
|
20
|
+
self.replace h
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# EOF
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# $Id: webby_task.rb 7 2007-08-22 22:31:08Z tim_pease $
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/tasklib'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
raise unless gem 'rake'
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
module Rake
|
13
|
+
|
14
|
+
# The WebbyTask defines several rake tasks for working with Webby based
|
15
|
+
# websites:
|
16
|
+
#
|
17
|
+
# [:build] Build the site by compiling only those resources in the content
|
18
|
+
# folder that have been modifed recently. If the a content file
|
19
|
+
# has a modification time more recent then its corresponding
|
20
|
+
# output file, then it will be built by this task.
|
21
|
+
#
|
22
|
+
# [:rebuild] Rebuild the entire site from the content folder and store the
|
23
|
+
# results in the output folder.
|
24
|
+
#
|
25
|
+
# [:autobuild] Monitors the content and layout directories for modified
|
26
|
+
# resources and compiles those files as needed. This task
|
27
|
+
# returns only when the user hits Ctrl-C.
|
28
|
+
#
|
29
|
+
# [:create:page] Create a new page in the content folder based on the
|
30
|
+
# template 'page' found in the templates folder. One task
|
31
|
+
# will be created for each file found in the templates
|
32
|
+
# folder.
|
33
|
+
#
|
34
|
+
class WebbyTask < TaskLib
|
35
|
+
|
36
|
+
# Location of the generated website
|
37
|
+
attr_accessor :output_dir
|
38
|
+
|
39
|
+
# Location of the webiste source material
|
40
|
+
attr_accessor :content_dir
|
41
|
+
|
42
|
+
# Location of the layout files for generated pages
|
43
|
+
attr_accessor :layout_dir
|
44
|
+
|
45
|
+
# Location of the page templates
|
46
|
+
attr_accessor :template_dir
|
47
|
+
|
48
|
+
# Array of patterns used to exclude files
|
49
|
+
attr_accessor :exclude
|
50
|
+
|
51
|
+
# Global page attributes (default is {})
|
52
|
+
attr_reader :page_defaults
|
53
|
+
|
54
|
+
# Merge the given _hash_ with the page defaults hash
|
55
|
+
def page_defaults=( hash )
|
56
|
+
@page_defaults.merge! hash
|
57
|
+
end
|
58
|
+
|
59
|
+
# call-seq:
|
60
|
+
# WebbyTask.new {|self| block}
|
61
|
+
#
|
62
|
+
# Create the tasks used by Webby to build a website and to create new
|
63
|
+
# pages in the website.
|
64
|
+
#
|
65
|
+
def initialize
|
66
|
+
@output_dir = 'output'
|
67
|
+
@content_dir = 'content'
|
68
|
+
@layout_dir = 'layouts'
|
69
|
+
@template_dir = 'templates'
|
70
|
+
@exclude = %w(tmp$ bak$ ~$ CVS \.svn)
|
71
|
+
@page_defaults = {
|
72
|
+
'extension' => 'html',
|
73
|
+
'layout' => 'default'
|
74
|
+
}
|
75
|
+
|
76
|
+
yield self if block_given?
|
77
|
+
|
78
|
+
::Webby.config.merge!({
|
79
|
+
'output_dir' => @output_dir,
|
80
|
+
'content_dir' => @content_dir,
|
81
|
+
'layout_dir' => @layout_dir,
|
82
|
+
'template_dir' => @template_dir,
|
83
|
+
'exclude' => @exclude
|
84
|
+
})
|
85
|
+
::Webby.page_defaults.merge! @page_defaults
|
86
|
+
|
87
|
+
define_build_tasks
|
88
|
+
namespace(:create) {define_create_tasks}
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Defines the :build and :rebuild tasks
|
95
|
+
#
|
96
|
+
def define_build_tasks
|
97
|
+
desc "build the website"
|
98
|
+
task :build do |t|
|
99
|
+
::Webby::Builder.run
|
100
|
+
end
|
101
|
+
|
102
|
+
desc "rebuild the website"
|
103
|
+
task :rebuild do |t|
|
104
|
+
::Webby::Builder.run :rebuild => true
|
105
|
+
end
|
106
|
+
|
107
|
+
desc "continuously build the website"
|
108
|
+
task :autobuild do |t|
|
109
|
+
::Webby::AutoBuilder.run
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Scans the templates directory for any files, and creats a corresponding
|
114
|
+
# task for creating a new page based on that template.
|
115
|
+
#
|
116
|
+
def define_create_tasks
|
117
|
+
FileList["#{@template_dir}/*"].each do |template|
|
118
|
+
name = template.pathmap '%n'
|
119
|
+
|
120
|
+
desc "create a new #{name} page"
|
121
|
+
task name do |t|
|
122
|
+
raise "Usage: rake #{t.name} path" unless ARGV.length == 2
|
123
|
+
|
124
|
+
page = t.application.top_level_tasks.pop
|
125
|
+
page = File.join(@content_dir, page)
|
126
|
+
page << '.txt' if File.extname(page).empty?
|
127
|
+
|
128
|
+
::Webby::Builder.create page, :from => template
|
129
|
+
end # task
|
130
|
+
end # each
|
131
|
+
end
|
132
|
+
|
133
|
+
end # class WebbyTask
|
134
|
+
end # module Rake
|
135
|
+
|
136
|
+
# EOF
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# $Id: file_spec.rb 1 2007-08-18 21:39:50Z tim_pease $
|
2
|
+
|
3
|
+
require 'spec/spec_helper.rb'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
describe Webby::File do
|
7
|
+
|
8
|
+
FN = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lorem_ipsum.txt'))
|
9
|
+
FN_YAML = FN.gsub %r/\.txt\z/, '_yaml.txt'
|
10
|
+
LINES = [
|
11
|
+
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla orci\n",
|
12
|
+
"ante, aliquet ac, vulputate ut, suscipit et, sapien. Integer elementum\n",
|
13
|
+
"nisi quis magna tincidunt mattis. Aliquam semper. Pellentesque pretium.\n",
|
14
|
+
"Ut a ligula sit amet pede malesuada laoreet. Ut et purus. Morbi turpis\n",
|
15
|
+
"justo, pharetra vitae, consequat a, sodales vitae, tortor. Donec non\n",
|
16
|
+
"massa. Maecenas adipiscing venenatis nisi. Proin vulputate lorem posuere\n",
|
17
|
+
"mi. Cras sagittis. Pellentesque tortor mauris, accumsan vitae, ultrices\n",
|
18
|
+
"vel, tristique ultricies, eros. Donec fringilla hendrerit mauris. Nam in\n",
|
19
|
+
"orci. Curabitur congue consectetuer leo. Donec ut pede. Proin et lorem.\n",
|
20
|
+
"Aliquam eget lacus. In nibh.\n"
|
21
|
+
]
|
22
|
+
|
23
|
+
before do
|
24
|
+
File.open(FN,'w') {|fd| fd.write LINES}
|
25
|
+
File.open(FN_YAML,'w') do |fd|
|
26
|
+
fd.write "--- \n- one\n- two\n- three\n--- \n"
|
27
|
+
fd.write LINES
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
after do
|
32
|
+
File.delete FN if File.exists?(FN)
|
33
|
+
File.delete FN_YAML if File.exists?(FN_YAML)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should return nil for meta-data on regular files' do
|
37
|
+
begin
|
38
|
+
fd = Webby::File.new FN, 'r'
|
39
|
+
fd.meta_data.should == nil
|
40
|
+
|
41
|
+
fd.readlines.should == LINES
|
42
|
+
ensure
|
43
|
+
fd.close
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should add meta-data to the top of a file' do
|
48
|
+
Webby::File.open(FN,'a+') do |fd|
|
49
|
+
fd.meta_data.should == nil
|
50
|
+
fd.meta_data = %w(one two three)
|
51
|
+
end
|
52
|
+
|
53
|
+
Webby::File.open(FN,'r') do |fd|
|
54
|
+
fd.meta_data.should == %w(one two three)
|
55
|
+
end
|
56
|
+
|
57
|
+
File.open(FN_YAML, 'r') do |fd|
|
58
|
+
ary = LINES.dup
|
59
|
+
ary.insert 0, [
|
60
|
+
"--- \n",
|
61
|
+
"- one\n",
|
62
|
+
"- two\n",
|
63
|
+
"- three\n",
|
64
|
+
"--- \n"
|
65
|
+
]
|
66
|
+
fd.readlines.should == ary.flatten
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should remove the meta-data when set to nil' do
|
71
|
+
Webby::File.open(FN_YAML,'a+') do |fd|
|
72
|
+
fd.meta_data.should == %w(one two three)
|
73
|
+
fd.meta_data = nil
|
74
|
+
end
|
75
|
+
|
76
|
+
Webby::File.open(FN_YAML,'r') do |fd|
|
77
|
+
fd.meta_data.should == nil
|
78
|
+
end
|
79
|
+
|
80
|
+
File.open(FN_YAML, 'r') do |fd|
|
81
|
+
fd.readlines.should == LINES
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should skip the meta-data when reading from the file' do
|
86
|
+
begin
|
87
|
+
fd = Webby::File.new FN_YAML, 'r'
|
88
|
+
fd.meta_data.should == %w(one two three)
|
89
|
+
|
90
|
+
fd.getc.should == ?L; fd.seek 0
|
91
|
+
fd.gets.should == LINES.first; fd.seek 0
|
92
|
+
fd.read(5).should == 'Lorem'; fd.seek 0
|
93
|
+
fd.read_nonblock(11) == 'Lorem ipsum'; fd.seek 0
|
94
|
+
fd.readchar.should == ?L; fd.seek 0
|
95
|
+
fd.readline.should == LINES.first; fd.seek 0
|
96
|
+
fd.readlines.should == LINES; fd.seek 0
|
97
|
+
fd.readpartial(11).should == 'Lorem ipsum'; fd.seek 0
|
98
|
+
fd.sysread(11).should == 'Lorem ipsum'; fd.seek 0
|
99
|
+
|
100
|
+
ensure
|
101
|
+
fd.close
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end # describe Webby::File
|
106
|
+
|
107
|
+
# EOF
|