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.
Files changed (45) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +44 -0
  3. data/README.txt +50 -0
  4. data/Rakefile +29 -0
  5. data/bin/webby +14 -0
  6. data/data/Rakefile +6 -0
  7. data/data/content/css/blueprint/License.txt +21 -0
  8. data/data/content/css/blueprint/Readme.txt +93 -0
  9. data/data/content/css/blueprint/lib/buttons.css +112 -0
  10. data/data/content/css/blueprint/lib/compressed.css +127 -0
  11. data/data/content/css/blueprint/lib/grid.css +177 -0
  12. data/data/content/css/blueprint/lib/img/baseline-black.png +0 -0
  13. data/data/content/css/blueprint/lib/img/baseline.png +0 -0
  14. data/data/content/css/blueprint/lib/img/grid.png +0 -0
  15. data/data/content/css/blueprint/lib/img/icons/cross.png +0 -0
  16. data/data/content/css/blueprint/lib/img/icons/textfield_key.png +0 -0
  17. data/data/content/css/blueprint/lib/img/icons/tick.png +0 -0
  18. data/data/content/css/blueprint/lib/reset.css +37 -0
  19. data/data/content/css/blueprint/lib/typography.css +159 -0
  20. data/data/content/css/blueprint/print.css +75 -0
  21. data/data/content/css/blueprint/screen.css +34 -0
  22. data/data/content/css/site.css +0 -0
  23. data/data/content/index.rhtml +18 -0
  24. data/data/layouts/default.rhtml +55 -0
  25. data/data/tasks/create.rake +7 -0
  26. data/data/templates/page.erb +18 -0
  27. data/lib/webby.rb +67 -0
  28. data/lib/webby/auto_builder.rb +75 -0
  29. data/lib/webby/builder.rb +165 -0
  30. data/lib/webby/file.rb +191 -0
  31. data/lib/webby/main.rb +129 -0
  32. data/lib/webby/pages_db.rb +70 -0
  33. data/lib/webby/renderer.rb +94 -0
  34. data/lib/webby/resource.rb +174 -0
  35. data/lib/webby/utils.rb +24 -0
  36. data/lib/webby/webby_task.rb +136 -0
  37. data/spec/spec.opts +1 -0
  38. data/spec/spec_helper.rb +12 -0
  39. data/spec/webby/file_spec.rb +107 -0
  40. data/tasks/doc.rake +60 -0
  41. data/tasks/gem.rake +112 -0
  42. data/tasks/manifest.rake +39 -0
  43. data/tasks/setup.rb +108 -0
  44. data/tasks/spec.rake +37 -0
  45. 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
@@ -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
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,12 @@
1
+ # $Id: spec_helper.rb 1 2007-08-18 21:39:50Z tim_pease $
2
+
3
+ begin
4
+ require 'webby'
5
+ rescue LoadError
6
+ path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ raise if $:.include? path
8
+ $: << path
9
+ retry
10
+ end
11
+
12
+ # EOF
@@ -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