webby 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +7 -0
  2. data/Manifest.txt +30 -1
  3. data/Rakefile +6 -2
  4. data/bin/webby +1 -1
  5. data/data/Rakefile +6 -2
  6. data/data/content/{index.rhtml → index.txt} +0 -0
  7. data/data/tasks/create.rake +6 -1
  8. data/data/tasks/deploy.rake +22 -0
  9. data/data/tasks/heel.rake +26 -0
  10. data/data/tasks/setup.rb +27 -0
  11. data/lib/webby.rb +20 -12
  12. data/lib/webby/builder.rb +6 -19
  13. data/lib/webby/main.rb +85 -15
  14. data/lib/webby/pages_db.rb +24 -1
  15. data/lib/webby/renderer.rb +25 -3
  16. data/lib/webby/resource.rb +89 -13
  17. data/lib/webby/webby_task.rb +19 -41
  18. data/tasks/doc.rake +2 -19
  19. data/tasks/gem.rake +14 -41
  20. data/tasks/manifest.rake +1 -1
  21. data/tasks/rubyforge.rake +57 -0
  22. data/tasks/setup.rb +6 -5
  23. data/tasks/spec.rake +3 -3
  24. data/tasks/website.rake +38 -0
  25. data/website/Rakefile +13 -0
  26. data/website/content/css/blueprint/lib/buttons.css +112 -0
  27. data/website/content/css/blueprint/lib/compressed.css +127 -0
  28. data/website/content/css/blueprint/lib/grid.css +177 -0
  29. data/website/content/css/blueprint/lib/img/baseline-black.png +0 -0
  30. data/website/content/css/blueprint/lib/img/baseline.png +0 -0
  31. data/website/content/css/blueprint/lib/img/grid.png +0 -0
  32. data/website/content/css/blueprint/lib/img/icons/cross.png +0 -0
  33. data/website/content/css/blueprint/lib/img/icons/textfield_key.png +0 -0
  34. data/website/content/css/blueprint/lib/img/icons/tick.png +0 -0
  35. data/website/content/css/blueprint/lib/reset.css +37 -0
  36. data/website/content/css/blueprint/lib/typography.css +159 -0
  37. data/website/content/css/blueprint/print.css +75 -0
  38. data/website/content/css/blueprint/screen.css +34 -0
  39. data/website/content/css/site.css +22 -0
  40. data/website/content/download.txt +8 -0
  41. data/website/content/index.txt +28 -0
  42. data/website/content/tutorial.txt +130 -0
  43. data/website/layouts/default.rhtml +49 -0
  44. data/website/tasks/create.rake +11 -0
  45. data/website/tasks/deploy.rake +22 -0
  46. data/website/tasks/heel.rake +26 -0
  47. data/website/tasks/setup.rb +27 -0
  48. data/website/templates/page.erb +8 -0
  49. metadata +33 -14
@@ -1,4 +1,4 @@
1
- # $Id: pages_db.rb 6 2007-08-22 22:25:53Z tim_pease $
1
+ # $Id: pages_db.rb 18 2007-08-28 15:48:17Z tim_pease $
2
2
 
3
3
  module Webby
4
4
 
@@ -7,20 +7,32 @@ module Webby
7
7
  class PagesDB
8
8
  include Enumerable
9
9
 
10
+ # call-seq:
11
+ # PagesDB.new
12
+ #
10
13
  def initialize
11
14
  @db = Hash.new {|h,k| h[k] = []}
12
15
  end
13
16
 
17
+ # call-seq:
18
+ # add( resource )
19
+ #
14
20
  def add( page )
15
21
  @db[page.dir] << page
16
22
  self
17
23
  end
18
24
  alias :<< :add
19
25
 
26
+ # call-seq:
27
+ # clear
28
+ #
20
29
  def clear
21
30
  @db.clear
22
31
  end
23
32
 
33
+ # call-seq:
34
+ # each {|resource| block}
35
+ #
24
36
  def each( &b )
25
37
  keys = @db.keys.sort
26
38
  keys.each do |k|
@@ -28,6 +40,9 @@ class PagesDB
28
40
  end
29
41
  end
30
42
 
43
+ # call-seq:
44
+ # find_by_name( name )
45
+ #
31
46
  def find_by_name( name )
32
47
  self.find {|page| page.filename == name}
33
48
  end
@@ -37,6 +52,7 @@ class PagesDB
37
52
  #
38
53
  # Options include:
39
54
  # :sorty_by => 'attribute'
55
+ # :reverse => true
40
56
  #
41
57
  def siblings( page, opts = {} )
42
58
  ary = @db[page.dir].dup
@@ -49,6 +65,13 @@ class PagesDB
49
65
  ary
50
66
  end
51
67
 
68
+ # call-seq:
69
+ # children( page, opts = {} ) => array
70
+ #
71
+ # Options include:
72
+ # :sorty_by => 'attribute'
73
+ # :reverse => true
74
+ #
52
75
  def children( page, opts = {} )
53
76
  rgxp = Regexp.new "\\A#{page.dir}/[^/]+"
54
77
 
@@ -1,4 +1,4 @@
1
- # $Id: renderer.rb 2 2007-08-20 17:55:30Z tim_pease $
1
+ # $Id: renderer.rb 19 2007-08-28 22:48:24Z tim_pease $
2
2
 
3
3
  require 'erb'
4
4
 
@@ -7,7 +7,17 @@ try_require 'redcloth'
7
7
 
8
8
  module Webby
9
9
 
10
+ # The Webby::Renderer is used to _filter_ and _layout_ the text found in the
11
+ # resource page files in the content directory.
10
12
  #
13
+ # A page is filtered based on the settings of the 'filter' option in the
14
+ # page's meta-data information. For example, if 'textile' is specified as
15
+ # a filter, then the page will be run through the RedCloth markup filer.
16
+ # More than one filter can be used on a page; they will be run in the
17
+ # order specified in the meta-data.
18
+ #
19
+ # A page is rendered into a layout specified by the 'layout' option in the
20
+ # page's meta-data information.
11
21
  #
12
22
  class Renderer
13
23
  include ERB::Util
@@ -15,6 +25,10 @@ class Renderer
15
25
  # call-seq:
16
26
  # Renderer.new( page )
17
27
  #
28
+ # Create a new renderer for the given _page_. The renderer will apply the
29
+ # desired filters to the _page_ (from the page's meta-data) and then
30
+ # render the filtered page into the desired layout.
31
+ #
18
32
  def initialize( page )
19
33
  unless page.is_page?
20
34
  raise ArgumentError,
@@ -27,7 +41,12 @@ class Renderer
27
41
  end
28
42
 
29
43
  # call-seq:
30
- # layout_page
44
+ # layout_page => string
45
+ #
46
+ # Apply the desired filters to the page and then render the filtered page
47
+ # into the desired layout. The filters to apply to the page are determined
48
+ # from the page's meta-data. The layout to use is also determined from the
49
+ # page's meta-data.
31
50
  #
32
51
  def layout_page
33
52
  layouts = Resource.layouts
@@ -51,7 +70,10 @@ class Renderer
51
70
  end
52
71
 
53
72
  # call-seq:
54
- # render_page
73
+ # render_page => string
74
+ #
75
+ # Apply the desired filters to the page. The filters to apply are
76
+ # determined from the page's meta-data.
55
77
  #
56
78
  def render_page
57
79
  str = ::Webby::File.read(@page.path)
@@ -1,30 +1,65 @@
1
- # $Id: resource.rb 5 2007-08-22 04:25:49Z tim_pease $
1
+ # $Id: resource.rb 17 2007-08-28 04:11:00Z tim_pease $
2
2
 
3
3
  module Webby
4
4
 
5
+ # A Webby::Resource is any file that can be found in the content directory
6
+ # or in the layout directory. This class contains information about the
7
+ # resources available to Webby. This information includes the resource
8
+ # type (static, page, layout), if the resource is dirty (it needs to be
9
+ # rendered), the output location of the rendered resource, etc.
5
10
  #
11
+ # A resource is a "layout" if the resource is found in the layout
12
+ # directory. Static and page resources are found in the content directory.
13
+ #
14
+ # A resource is considered static only if it *does not* contain a YAML
15
+ # meta-data header at the top of the file. These resources will be copied
16
+ # as-is from the content directory to the output directory.
17
+ #
18
+ # If a resouce does have meta-data, then it will be processed (i.e.
19
+ # rendered/filtered) by Webby, and the rendered results will be written to
20
+ # the output directory.
6
21
  #
7
22
  class Resource
8
23
 
9
24
  class << self
25
+ # Returns the pages hash object.
10
26
  def pages
11
27
  @pages ||= PagesDB.new
12
28
  end
13
29
 
30
+ # Returns the layouts hash object.
14
31
  def layouts
15
32
  @layouts ||= PagesDB.new
16
33
  end
17
34
 
35
+ # Clear the contents of the +layouts+ and the +pages+ hash objects.
18
36
  def clear
19
37
  self.pages.clear
20
38
  self.layouts.clear
21
39
  end
22
40
  end # class << self
23
41
 
42
+ # The full path to the resource file
43
+ attr_reader :path
44
+
45
+ # The directory of the resource excluding the content directory
46
+ attr_reader :dir
47
+
48
+ # The resource filename excluding path and extension
49
+ attr_reader :filename
50
+
51
+ # Extesion of the resource file
52
+ attr_reader :ext
53
+
54
+ # Resource file modification time
55
+ attr_reader :mtime
56
+
24
57
  # call-seq:
25
- # Resource.new( filename, defaults = {} ) => page
58
+ # Resource.new( filename ) => resource
26
59
  #
27
- def initialize( fn, defaults = {} )
60
+ # Creates a new resource object given the _filename_.
61
+ #
62
+ def initialize( fn )
28
63
  @path = fn.sub(%r/\A(?:\.\/|\/)/o, '').freeze
29
64
  @dir = ::File.dirname(@path).sub(%r/\A[^\/]+\/?/o, '')
30
65
  @filename = ::File.basename(@path).sub(%r/\.\w+\z/o, '')
@@ -36,7 +71,9 @@ class Resource
36
71
  # deal with the meta-data
37
72
  @mdata = ::Webby::File.meta_data(@path)
38
73
  @have_mdata = !@mdata.nil?
39
- @mdata = @have_mdata ? defaults.merge(@mdata) : {}
74
+
75
+ @mdata ||= {}
76
+ @mdata = ::Webby.page_defaults.merge(@mdata) if is_page?
40
77
  @mdata.sanitize!
41
78
 
42
79
  self.class.pages << self if is_page? or is_static?
@@ -46,6 +83,9 @@ class Resource
46
83
  # call-seq:
47
84
  # equal?( other ) => true or false
48
85
  #
86
+ # Returns +true+ if the path of this resource is equivalent to the path of
87
+ # the _other_ resource. Returns +false+ if this is not the case.
88
+ #
49
89
  def equal?( other )
50
90
  return false unless self.class == other.class
51
91
  @path == other.path
@@ -56,17 +96,25 @@ class Resource
56
96
  # call-seq:
57
97
  # resource <=> other => -1, 0, +1, or nil
58
98
  #
99
+ # Resource comparison operates on the full path of the resource objects
100
+ # and uses the standard String comparison operator. Returns +nil+ if
101
+ # _other_ is not a Resource instance.
102
+ #
59
103
  def <=>( other )
60
104
  return unless self.class == other.class
61
105
  @path <=> other.path
62
106
  end
63
107
 
64
-
65
- attr_reader :path, :dir, :filename, :mtime, :ext
66
-
67
108
  # call-seq:
68
109
  # extension => string
69
110
  #
111
+ # Returns the extension that will be appended to the output destination
112
+ # filename. The extension is determined by looking at the following:
113
+ #
114
+ # * this resource's meta-data for an 'extension' property
115
+ # * the meta-data of this resource's layout for an 'extension' propery
116
+ # * the extension of this resource file
117
+ #
70
118
  def extension
71
119
  return @mdata['extension'] if @mdata.has_key? 'extension'
72
120
 
@@ -79,19 +127,39 @@ class Resource
79
127
  @ext
80
128
  end
81
129
 
130
+ # call-seq:
131
+ # destination => string
132
+ #
133
+ # Returns the path in the output directory where the results of rendering
134
+ # this resource should be stored. This path is used to determine if the
135
+ # resource is dirty and in need of rendering.
136
+ #
137
+ # The destination for any resource can be overridden by explicitly setting
138
+ # the 'destination' propery in the resource's meta-data.
139
+ #
82
140
  def destination
83
- return @destination if defined? @destination
84
- return @destination = ::Webby.config['output_dir'] if is_layout?
141
+ return @dest if defined? @dest
142
+ return @dest = ::Webby.config['output_dir'] if is_layout?
85
143
 
86
- @destination = File.join(::Webby.config['output_dir'], dir, filename)
87
- @destination << '.'
88
- @destination << extension
89
- @destination
144
+ @dest = if @mdata.has_key? 'destination' then @mdata['destination']
145
+ else File.join(dir, filename) end
146
+
147
+ @dest = File.join(::Webby.config['output_dir'], @dest)
148
+ @dest << '.'
149
+ @dest << extension
150
+ @dest
90
151
  end
91
152
 
92
153
  # call-seq:
93
154
  # render => string
94
155
  #
156
+ # Creates a new Webby::Renderer instance and uses that instance to render
157
+ # the resource contents using the configured filter(s). The filter(s) to
158
+ # use is defined in the resource's meta-data as the 'filter' key.
159
+ #
160
+ # Note, this only renders this resource. The returned string does not
161
+ # include any layout rendering.
162
+ #
95
163
  def render
96
164
  raise Error, "page '#@path' is in a rendering loop" if @rendering
97
165
 
@@ -164,6 +232,14 @@ class Resource
164
232
  @mdata['dirty'] = false
165
233
  end
166
234
 
235
+ # call-seq:
236
+ # method_missing( symbol [, *args, &block] ) => result
237
+ #
238
+ # Invoked by Ruby when a message is sent to the resource that it cannot
239
+ # handle. The default behavior is to convert _symbol_ to a string and
240
+ # search for that string in the resource's meta-data. If found, the
241
+ # meta-data item is returned; otherwise, +nil+ is returned.
242
+ #
167
243
  def method_missing( name, *a, &b )
168
244
  @mdata[name.to_s]
169
245
  end
@@ -1,4 +1,4 @@
1
- # $Id: webby_task.rb 7 2007-08-22 22:31:08Z tim_pease $
1
+ # $Id: webby_task.rb 15 2007-08-25 19:05:39Z tim_pease $
2
2
 
3
3
  begin
4
4
  require 'rake'
@@ -33,27 +33,22 @@ module Rake
33
33
  #
34
34
  class WebbyTask < TaskLib
35
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
36
+ # Define a setter and getter for each key in the Webby configuration hash
37
+ ::Webby.config.keys.each do |key|
38
+ self.class_eval do
39
+ define_method(key) {::Webby.config[key]}
40
+ define_method(key+'=') {|val| ::Webby.config[key] = val}
41
+ end
42
+ end
50
43
 
51
- # Global page attributes (default is {})
52
- attr_reader :page_defaults
44
+ # Global page attributes
45
+ def page_defaults
46
+ ::Webby.page_defaults
47
+ end
53
48
 
54
49
  # Merge the given _hash_ with the page defaults hash
55
50
  def page_defaults=( hash )
56
- @page_defaults.merge! hash
51
+ ::Webby.page_defaults.merge! hash
57
52
  end
58
53
 
59
54
  # call-seq:
@@ -63,34 +58,17 @@ class WebbyTask < TaskLib
63
58
  # pages in the website.
64
59
  #
65
60
  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
61
  yield self if block_given?
77
62
 
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
63
+ # load any user defined libraries
64
+ glob = File.join(FileUtils.pwd, 'lib', '**', '*.rb')
65
+ Dir.glob(glob).sort.each {|fn| require fn}
86
66
 
67
+ # create the Webby rake tasks
87
68
  define_build_tasks
88
69
  namespace(:create) {define_create_tasks}
89
70
  end
90
71
 
91
-
92
- private
93
-
94
72
  # Defines the :build and :rebuild tasks
95
73
  #
96
74
  def define_build_tasks
@@ -114,7 +92,7 @@ class WebbyTask < TaskLib
114
92
  # task for creating a new page based on that template.
115
93
  #
116
94
  def define_create_tasks
117
- FileList["#{@template_dir}/*"].each do |template|
95
+ FileList["#{template_dir}/*"].each do |template|
118
96
  name = template.pathmap '%n'
119
97
 
120
98
  desc "create a new #{name} page"
@@ -122,7 +100,7 @@ class WebbyTask < TaskLib
122
100
  raise "Usage: rake #{t.name} path" unless ARGV.length == 2
123
101
 
124
102
  page = t.application.top_level_tasks.pop
125
- page = File.join(@content_dir, page)
103
+ page = File.join(content_dir, page)
126
104
  page << '.txt' if File.extname(page).empty?
127
105
 
128
106
  ::Webby::Builder.create page, :from => template
@@ -1,7 +1,6 @@
1
- # $Id$
1
+ # $Id: doc.rake 11 2007-08-23 15:45:16Z tim_pease $
2
2
 
3
3
  require 'rake/rdoctask'
4
- require 'rake/contrib/sshpublisher'
5
4
 
6
5
  namespace :doc do
7
6
 
@@ -9,7 +8,7 @@ namespace :doc do
9
8
  Rake::RDocTask.new do |rd|
10
9
  rd.main = PROJ.rdoc_main
11
10
  rd.options << '-d' if !WIN32 and `which dot` =~ %r/\/dot/
12
- rd.rdoc_dir = 'doc'
11
+ rd.rdoc_dir = PROJ.rdoc_dir
13
12
 
14
13
  incl = Regexp.new(PROJ.rdoc_include.join('|'))
15
14
  excl = Regexp.new(PROJ.rdoc_exclude.join('|'))
@@ -37,22 +36,6 @@ namespace :doc do
37
36
  rm_r 'ri' rescue nil
38
37
  end
39
38
 
40
- if PROJ.rubyforge_name && HAVE_RUBYFORGE
41
- desc "Publish RDoc to RubyForge"
42
- task :release => %w(doc:clobber_rdoc doc:rdoc) do
43
- config = YAML.load(
44
- File.read(File.expand_path('~/.rubyforge/user-config.yml'))
45
- )
46
-
47
- host = "#{config['username']}@rubyforge.org"
48
- remote_dir = "/var/www/gforge-projects/#{rubyforge_name}/"
49
- remote_dir << PROJ.rdoc_remote_dir || PROJ.name
50
- local_dir = 'doc'
51
-
52
- Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
53
- end
54
- end
55
-
56
39
  end # namespace :doc
57
40
 
58
41
  task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
@@ -1,11 +1,10 @@
1
- # $Id$
1
+ # $Id: gem.rake 11 2007-08-23 15:45:16Z tim_pease $
2
2
 
3
3
  require 'rake/gempackagetask'
4
- require 'rubyforge' if PROJ.rubyforge_name && HAVE_RUBYFORGE
5
4
 
6
5
  namespace :gem do
7
6
 
8
- spec = Gem::Specification.new do |s|
7
+ PROJ.spec = Gem::Specification.new do |s|
9
8
  s.name = PROJ.name
10
9
  s.version = PROJ.version
11
10
  s.summary = PROJ.summary
@@ -19,9 +18,6 @@ namespace :gem do
19
18
  PROJ.dependencies.each do |dep|
20
19
  s.add_dependency(*dep)
21
20
  end
22
- if PROJ.rubyforge_name && HAVE_RUBYFORGE
23
- s.add_dependency('rubyforge', ">= #{::RubyForge::VERSION}")
24
- end
25
21
  s.add_dependency('rake', ">= #{RAKEVERSION}")
26
22
 
27
23
  s.files = PROJ.files
@@ -32,8 +28,15 @@ namespace :gem do
32
28
  dirs = Dir['{lib,ext}']
33
29
  s.require_paths = dirs unless dirs.empty?
34
30
 
35
- rdoc_files = PROJ.files.grep %r/txt$/
36
- rdoc_files.delete 'Manifest.txt'
31
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
32
+ excl = PROJ.rdoc_exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
33
+ excl = Regexp.new(excl.join('|'))
34
+ rdoc_files = PROJ.files.find_all do |fn|
35
+ case fn
36
+ when excl: false
37
+ when incl: true
38
+ else false end
39
+ end
37
40
  s.rdoc_options = PROJ.rdoc_opts + ['--main', PROJ.rdoc_main]
38
41
  s.extra_rdoc_files = rdoc_files
39
42
  s.has_rdoc = true
@@ -57,17 +60,17 @@ namespace :gem do
57
60
 
58
61
  desc 'Show information about the gem'
59
62
  task :debug do
60
- puts spec.to_ruby
63
+ puts PROJ.spec.to_ruby
61
64
  end
62
65
 
63
- Rake::GemPackageTask.new(spec) do |pkg|
66
+ Rake::GemPackageTask.new(PROJ.spec) do |pkg|
64
67
  pkg.need_tar = PROJ.need_tar
65
68
  pkg.need_zip = PROJ.need_zip
66
69
  end
67
70
 
68
71
  desc 'Install the gem'
69
72
  task :install => [:clobber, :package] do
70
- sh "#{SUDO} #{GEM} install pkg/#{spec.file_name}"
73
+ sh "#{SUDO} #{GEM} install pkg/#{PROJ.spec.file_name}"
71
74
  end
72
75
 
73
76
  desc 'Uninstall the gem'
@@ -75,36 +78,6 @@ namespace :gem do
75
78
  sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' #{PROJ.name}"
76
79
  end
77
80
 
78
- if PROJ.rubyforge_name && HAVE_RUBYFORGE
79
- desc 'Package and upload to RubyForge'
80
- task :release => [:clobber, :package] do |t|
81
- v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
82
- abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
83
- pkg = "pkg/#{spec.full_name}"
84
-
85
- if $DEBUG then
86
- puts "release_id = rf.add_release #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
87
- puts "rf.add_file #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
88
- end
89
-
90
- rf = RubyForge.new
91
- puts 'Logging in'
92
- rf.login
93
-
94
- c = rf.userconfig
95
- c['release_notes'] = PROJ.description if PROJ.description
96
- c['release_changes'] = PROJ.changes if PROJ.changes
97
- c['preformatted'] = true
98
-
99
- files = [(PROJ.need_tar ? "#{pkg}.tgz" : nil),
100
- (PROJ.need_zip ? "#{pkg}.zip" : nil),
101
- "#{pkg}.gem"].compact
102
-
103
- puts "Releasing #{PROJ.name} v. #{PROJ.version}"
104
- rf.add_release PROJ.rubyforge_name, PROJ.name, PROJ.version, *files
105
- end
106
- end
107
-
108
81
  end # namespace :gem
109
82
 
110
83
  task :clobber => 'gem:clobber_package'