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
data/lib/webby/file.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# $Id: file.rb 2 2007-08-20 17:55:30Z tim_pease $
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Webby
|
6
|
+
|
7
|
+
# The Webby::File class is identical to the core Ruby file class except for
|
8
|
+
# YAML meta-data stored at the top of the file. This meta-data is made
|
9
|
+
# available through the <code>meta_data</code> and <code>meta_data=</code>
|
10
|
+
# functions.
|
11
|
+
#
|
12
|
+
# The meta-data data must be found between two YAML block separators "---",
|
13
|
+
# each on their own line.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# ---
|
18
|
+
# layout: blog
|
19
|
+
# filter: markdown
|
20
|
+
# tags:
|
21
|
+
# - ruby
|
22
|
+
# - web development
|
23
|
+
# ---
|
24
|
+
# This is a blog entry formatted using MarkDown and tagged as "ruby" and
|
25
|
+
# "web development". The layout being used is the "blog" format.
|
26
|
+
#
|
27
|
+
class File < ::File
|
28
|
+
|
29
|
+
META_SEP = %r/\A---\s*\r?\n\z/o # :nodoc:
|
30
|
+
|
31
|
+
class << self
|
32
|
+
# call-seq:
|
33
|
+
# Webby::File.read( name [, length [, offset]]) => string
|
34
|
+
#
|
35
|
+
# Opens the file, optionally seeks to the given _offset_, then returns
|
36
|
+
# _length_ bytes (defaulting to the rest of the file). +read+ ensures
|
37
|
+
# the file is closed before returning.
|
38
|
+
#
|
39
|
+
def read( name, *args )
|
40
|
+
fd = new name, 'r'
|
41
|
+
fd.read *args
|
42
|
+
ensure
|
43
|
+
fd.close
|
44
|
+
end
|
45
|
+
|
46
|
+
# call-seq:
|
47
|
+
# Webby::File.readlines( name, sep_string = $/ ) => array
|
48
|
+
#
|
49
|
+
# Reads the entire file specified by _name_ as individual lines, and
|
50
|
+
# returns those lines in an array. Lines are separated by _sep_string_.
|
51
|
+
# +readlines+ ensures the file is closed before returning.
|
52
|
+
#
|
53
|
+
def readlines( name, sep = $/ )
|
54
|
+
fd = new name, 'r'
|
55
|
+
fd.readlines sep
|
56
|
+
ensure
|
57
|
+
fd.close
|
58
|
+
end
|
59
|
+
|
60
|
+
# call-seq:
|
61
|
+
# Webby::File.meta_data( name ) => object or nil
|
62
|
+
#
|
63
|
+
# Reads the meta-data from the file specified by _name_. +meta_data+
|
64
|
+
# ensures the files is closed before returning.
|
65
|
+
#
|
66
|
+
def meta_data( name )
|
67
|
+
fd = new name, 'r'
|
68
|
+
fd.meta_data
|
69
|
+
ensure
|
70
|
+
fd.close
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# call-seq:
|
75
|
+
# Webby::File.new( filename, mode = "r" ) => file
|
76
|
+
# Webby::File.new( filename [, mode [, perm]] ) => file
|
77
|
+
#
|
78
|
+
# Opens the file named by _filename_ according to _mode_ (default is 'r')
|
79
|
+
# and returns a new +Webby::File+ object. See the description of class
|
80
|
+
# +IO+ for a description of _mode_. The file _mode_ may optionally be
|
81
|
+
# specified as a +Fixnum+ by or-ing together the flags (+O_RDONLY+ etc,
|
82
|
+
# again described under +IO+). Optional permission bits may be given in
|
83
|
+
# _perm_. These _mode_ and permission bits are platform dependent; on Unix
|
84
|
+
# systems, see +open(2)+ for details.
|
85
|
+
#
|
86
|
+
# f = File.new("testfile", "r")
|
87
|
+
# f = File.new("newfile", "w+")
|
88
|
+
# f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
|
89
|
+
#
|
90
|
+
def initialize( *args )
|
91
|
+
super
|
92
|
+
@meta_end = end_of_meta_data
|
93
|
+
end
|
94
|
+
|
95
|
+
# call-seq:
|
96
|
+
# meta_data
|
97
|
+
#
|
98
|
+
# Returns the meta-data defined at the top of the file. Returns +nil+ if
|
99
|
+
# no meta-data is defined. The meta-data is returned as Ruby objects
|
100
|
+
#
|
101
|
+
# Meta-data is stored in YAML format between two YAML separators "---" on
|
102
|
+
# their own lines.
|
103
|
+
#
|
104
|
+
def meta_data
|
105
|
+
return if @meta_end.nil?
|
106
|
+
|
107
|
+
cur, meta_end, @meta_end = tell, @meta_end, nil
|
108
|
+
seek 0
|
109
|
+
return YAML.load(self)
|
110
|
+
|
111
|
+
ensure
|
112
|
+
@meta_end = meta_end if defined? meta_end and meta_end
|
113
|
+
seek cur if defined? cur and cur
|
114
|
+
end
|
115
|
+
|
116
|
+
# call-seq
|
117
|
+
# meta_data = object
|
118
|
+
#
|
119
|
+
# Stores the given _object_ as meta-data in YAML format at the top of the
|
120
|
+
# file. If the _objectc_ is +nil+, then the meta-data section will be
|
121
|
+
# removed from the file.
|
122
|
+
#
|
123
|
+
# Meta-data is stored in YAML format between two YAML separators "---" on
|
124
|
+
# their own lines.
|
125
|
+
#
|
126
|
+
def meta_data=( data )
|
127
|
+
return if data.nil? and @meta_end.nil?
|
128
|
+
|
129
|
+
seek 0
|
130
|
+
lines = readlines
|
131
|
+
|
132
|
+
truncate 0
|
133
|
+
unless data.nil?
|
134
|
+
write YAML.dump(data)
|
135
|
+
write "--- #$/"
|
136
|
+
end
|
137
|
+
lines.each {|line| write line}
|
138
|
+
ensure
|
139
|
+
@meta_end = end_of_meta_data
|
140
|
+
seek 0, IO::SEEK_END
|
141
|
+
end
|
142
|
+
|
143
|
+
%w(getc gets read read_nonblock readbytes readchar readline readlines readpartial scanf sysread).each do |m|
|
144
|
+
self.class_eval <<-CODE
|
145
|
+
def #{m}(*a)
|
146
|
+
skip_meta_data
|
147
|
+
super
|
148
|
+
end
|
149
|
+
CODE
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# Moves the file pointer to the end of the meta-data section. Does nothing
|
156
|
+
# if there is no meta-data section or if the file pointer is already past
|
157
|
+
# the meta-data section.
|
158
|
+
#
|
159
|
+
def skip_meta_data
|
160
|
+
return if @meta_end.nil?
|
161
|
+
return if tell >= @meta_end
|
162
|
+
seek @meta_end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns the position in this file where the meta-data ends and the file
|
166
|
+
# data begins. If there is no meta-data in the file, returns +nil+.
|
167
|
+
#
|
168
|
+
def end_of_meta_data
|
169
|
+
cur = tell
|
170
|
+
|
171
|
+
seek 0
|
172
|
+
line = readline
|
173
|
+
return unless META_SEP =~ line
|
174
|
+
|
175
|
+
loop do
|
176
|
+
line = readline
|
177
|
+
break if META_SEP =~ line
|
178
|
+
end
|
179
|
+
return tell
|
180
|
+
|
181
|
+
rescue EOFError
|
182
|
+
return
|
183
|
+
|
184
|
+
ensure
|
185
|
+
seek cur
|
186
|
+
end
|
187
|
+
|
188
|
+
end # class File
|
189
|
+
end # module Webby
|
190
|
+
|
191
|
+
# EOF
|
data/lib/webby/main.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# $Id: main.rb 2 2007-08-20 17:55:30Z tim_pease $
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'find'
|
5
|
+
|
6
|
+
module Webby
|
7
|
+
|
8
|
+
# The Webby::Main class contains all the functionality needed by the +webby+
|
9
|
+
# command line application.
|
10
|
+
#
|
11
|
+
class Main
|
12
|
+
|
13
|
+
# Directory where the Webby website will be created
|
14
|
+
attr_accessor :site
|
15
|
+
|
16
|
+
# Directory where the prototype Webby website can be found
|
17
|
+
attr_accessor :data
|
18
|
+
|
19
|
+
# call-seq:
|
20
|
+
# Main.run( *args ) => nil
|
21
|
+
#
|
22
|
+
# Create a new instance of Main, and run the +webby+ application given the
|
23
|
+
# command line _args_.
|
24
|
+
#
|
25
|
+
def self.run( *args )
|
26
|
+
self.new.run *args
|
27
|
+
end
|
28
|
+
|
29
|
+
# call-seq:
|
30
|
+
# run( *args ) => nil
|
31
|
+
#
|
32
|
+
# Run the +webby+ application given the command line _args_.
|
33
|
+
#
|
34
|
+
def run( *args )
|
35
|
+
abort "Usage: #{$0} /path/to/your/site" unless args.length == 1
|
36
|
+
|
37
|
+
self.site = args.at 0
|
38
|
+
self.data = File.join(::Webby::PATH, 'data')
|
39
|
+
|
40
|
+
# see if the site already exists
|
41
|
+
abort "#{site} already exists" if test ?e, site
|
42
|
+
|
43
|
+
# copy over files from the data directory
|
44
|
+
files = site_files
|
45
|
+
|
46
|
+
files.keys.sort.each do |dir|
|
47
|
+
mkdir dir
|
48
|
+
files[dir].each {|file| cp file}
|
49
|
+
end
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
# call-seq:
|
54
|
+
# mkdir( dir ) => nil
|
55
|
+
#
|
56
|
+
# Make a directory in the user specified site location. A message will be
|
57
|
+
# displayed to the screen indicating tha the directory is being created.
|
58
|
+
#
|
59
|
+
def mkdir( dir )
|
60
|
+
dir = dir.empty? ? site : ::File.join(site, dir)
|
61
|
+
creating dir
|
62
|
+
FileUtils.mkdir_p dir
|
63
|
+
end
|
64
|
+
|
65
|
+
# call-seq:
|
66
|
+
# cp( file ) => nil
|
67
|
+
#
|
68
|
+
# Copy a file from the Webby prototype website location to the user
|
69
|
+
# specified site location. A message will be displayed to the screen
|
70
|
+
# indicating tha the file is being created.
|
71
|
+
#
|
72
|
+
def cp( file )
|
73
|
+
src = ::File.join(data, file)
|
74
|
+
dst = ::File.join(site, file)
|
75
|
+
creating dst
|
76
|
+
FileUtils.cp src, dst
|
77
|
+
end
|
78
|
+
|
79
|
+
# call-seq:
|
80
|
+
# creating( msg ) => nil
|
81
|
+
#
|
82
|
+
# Prints a "creating _msg_" to the screen.
|
83
|
+
#
|
84
|
+
def creating( msg )
|
85
|
+
print "creating "
|
86
|
+
puts msg
|
87
|
+
end
|
88
|
+
|
89
|
+
# call-seq:
|
90
|
+
# abort( msg ) => nil
|
91
|
+
#
|
92
|
+
# Prints an abort _msg_ to the screen and then exits the Ruby interpreter.
|
93
|
+
#
|
94
|
+
def abort( msg )
|
95
|
+
puts msg
|
96
|
+
puts "Aborting!"
|
97
|
+
exit 1
|
98
|
+
end
|
99
|
+
|
100
|
+
# call-seq:
|
101
|
+
# site_files => hash
|
102
|
+
#
|
103
|
+
# Iterates over all the files in the Webby prototype website directory and
|
104
|
+
# stores them in a hash.
|
105
|
+
#
|
106
|
+
def site_files
|
107
|
+
exclude = %r/tmp$|bak$|~$|CVS|\.svn/o
|
108
|
+
|
109
|
+
rgxp = %r/\A#{data}\/?/o
|
110
|
+
paths = Hash.new {|h,k| h[k] = []}
|
111
|
+
|
112
|
+
Find.find(data) do |p|
|
113
|
+
next if exclude =~ p
|
114
|
+
|
115
|
+
if test(?d, p)
|
116
|
+
paths[p.sub(rgxp, '')]
|
117
|
+
next
|
118
|
+
end
|
119
|
+
dir = ::File.dirname(p).sub(rgxp, '')
|
120
|
+
paths[dir] << p.sub(rgxp, '')
|
121
|
+
end
|
122
|
+
|
123
|
+
paths
|
124
|
+
end
|
125
|
+
|
126
|
+
end # class Main
|
127
|
+
end # module Webby
|
128
|
+
|
129
|
+
# EOF
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# $Id: pages_db.rb 6 2007-08-22 22:25:53Z tim_pease $
|
2
|
+
|
3
|
+
module Webby
|
4
|
+
|
5
|
+
#
|
6
|
+
#
|
7
|
+
class PagesDB
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@db = Hash.new {|h,k| h[k] = []}
|
12
|
+
end
|
13
|
+
|
14
|
+
def add( page )
|
15
|
+
@db[page.dir] << page
|
16
|
+
self
|
17
|
+
end
|
18
|
+
alias :<< :add
|
19
|
+
|
20
|
+
def clear
|
21
|
+
@db.clear
|
22
|
+
end
|
23
|
+
|
24
|
+
def each( &b )
|
25
|
+
keys = @db.keys.sort
|
26
|
+
keys.each do |k|
|
27
|
+
@db[k].sort.each(&b)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_by_name( name )
|
32
|
+
self.find {|page| page.filename == name}
|
33
|
+
end
|
34
|
+
|
35
|
+
# call-seq:
|
36
|
+
# siblings( page, opts = {} ) => array
|
37
|
+
#
|
38
|
+
# Options include:
|
39
|
+
# :sorty_by => 'attribute'
|
40
|
+
#
|
41
|
+
def siblings( page, opts = {} )
|
42
|
+
ary = @db[page.dir].dup
|
43
|
+
ary.delete page
|
44
|
+
return ary unless opts.has_key? :sort_by
|
45
|
+
|
46
|
+
m = opts[:sort_by]
|
47
|
+
ary.sort! {|a,b| a.send(m) <=> b.send(m)}
|
48
|
+
ary.reverse! if opts[:reverse]
|
49
|
+
ary
|
50
|
+
end
|
51
|
+
|
52
|
+
def children( page, opts = {} )
|
53
|
+
rgxp = Regexp.new "\\A#{page.dir}/[^/]+"
|
54
|
+
|
55
|
+
keys = @db.keys.find_all {|k| rgxp =~ k}
|
56
|
+
ary = keys.map {|k| @db[k]}
|
57
|
+
ary.flatten!
|
58
|
+
|
59
|
+
return ary unless opts.has_key? :sort_by
|
60
|
+
|
61
|
+
m = opts[:sort_by]
|
62
|
+
ary.sort! {|a,b| a.send(m) <=> b.send(m)}
|
63
|
+
ary.reverse! if opts[:reverse]
|
64
|
+
ary
|
65
|
+
end
|
66
|
+
|
67
|
+
end # class PagesDB
|
68
|
+
end # module Webby
|
69
|
+
|
70
|
+
# EOF
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# $Id: renderer.rb 2 2007-08-20 17:55:30Z tim_pease $
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
try_require 'bluecloth'
|
6
|
+
try_require 'redcloth'
|
7
|
+
|
8
|
+
module Webby
|
9
|
+
|
10
|
+
#
|
11
|
+
#
|
12
|
+
class Renderer
|
13
|
+
include ERB::Util
|
14
|
+
|
15
|
+
# call-seq:
|
16
|
+
# Renderer.new( page )
|
17
|
+
#
|
18
|
+
def initialize( page )
|
19
|
+
unless page.is_page?
|
20
|
+
raise ArgumentError,
|
21
|
+
"only page resources can be rendered '#{page.path}'"
|
22
|
+
end
|
23
|
+
|
24
|
+
@page = page
|
25
|
+
@pages = Resource.pages
|
26
|
+
@content = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# call-seq:
|
30
|
+
# layout_page
|
31
|
+
#
|
32
|
+
def layout_page
|
33
|
+
layouts = Resource.layouts
|
34
|
+
obj = @page
|
35
|
+
str = @page.render
|
36
|
+
|
37
|
+
loop do
|
38
|
+
lyt = layouts.find_by_name obj.layout
|
39
|
+
break if lyt.nil?
|
40
|
+
|
41
|
+
@content, str = str, ::Webby::File.read(lyt.path)
|
42
|
+
|
43
|
+
lyt.filter.to_a.each do |filter|
|
44
|
+
str = self.send(filter + '_filter', str)
|
45
|
+
end
|
46
|
+
|
47
|
+
@content, obj = nil, lyt
|
48
|
+
end
|
49
|
+
|
50
|
+
str
|
51
|
+
end
|
52
|
+
|
53
|
+
# call-seq:
|
54
|
+
# render_page
|
55
|
+
#
|
56
|
+
def render_page
|
57
|
+
str = ::Webby::File.read(@page.path)
|
58
|
+
|
59
|
+
@page.filter.to_a.each do |filter|
|
60
|
+
str = self.send(filter + '_filter', str)
|
61
|
+
end
|
62
|
+
|
63
|
+
str
|
64
|
+
end
|
65
|
+
|
66
|
+
# Render text via ERB using the built in ERB library.
|
67
|
+
#
|
68
|
+
def erb_filter( str )
|
69
|
+
b = binding
|
70
|
+
ERB.new(str, nil, '-').result(b)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Render text via markdown using the BlueCloth library.
|
74
|
+
#
|
75
|
+
def markdown_filter( str )
|
76
|
+
BlueCloth.new(str).to_html
|
77
|
+
rescue NameError
|
78
|
+
$stderr.puts 'ERROR: markdown filter failed (BlueCloth not installed?)'
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
|
82
|
+
# Render text via textile using the RedCloth library.
|
83
|
+
#
|
84
|
+
def textile_filter( str )
|
85
|
+
RedCloth.new(str).to_html
|
86
|
+
rescue NameError
|
87
|
+
$stderr.puts 'ERROR: textile filter failed (RedCloth not installed?)'
|
88
|
+
exit
|
89
|
+
end
|
90
|
+
|
91
|
+
end # class Renderer
|
92
|
+
end # module Webby
|
93
|
+
|
94
|
+
# EOF
|