webby 0.1.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 +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
|