webby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,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
@@ -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